@tangle-network/agent-app 0.43.46 → 0.43.48

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 (40) hide show
  1. package/dist/assistant/index.d.ts +3 -2
  2. package/dist/assistant/index.js +3 -2
  3. package/dist/assistant/index.js.map +1 -1
  4. package/dist/chat-routes/index.d.ts +407 -160
  5. package/dist/chat-routes/index.js +512 -102
  6. package/dist/chat-routes/index.js.map +1 -1
  7. package/dist/chat-store/index.d.ts +3 -2
  8. package/dist/chat-store/index.js +19 -1
  9. package/dist/chat-store/index.js.map +1 -1
  10. package/dist/chunk-23LUHHHN.js +282 -0
  11. package/dist/chunk-23LUHHHN.js.map +1 -0
  12. package/dist/{chunk-4AUQIAYU.js → chunk-5MG74GVQ.js} +2 -281
  13. package/dist/chunk-5MG74GVQ.js.map +1 -0
  14. package/dist/chunk-BQV42AFK.js +99 -0
  15. package/dist/chunk-BQV42AFK.js.map +1 -0
  16. package/dist/{chunk-6E2XJSCT.js → chunk-JGYOYY5D.js} +65 -2
  17. package/dist/chunk-JGYOYY5D.js.map +1 -0
  18. package/dist/{chunk-7VMUOD3G.js → chunk-PHIXZC6Y.js} +1 -1
  19. package/dist/chunk-PHIXZC6Y.js.map +1 -0
  20. package/dist/{file-index-Bn6sitKb.d.ts → file-index-b26ee-_R.d.ts} +1 -1
  21. package/dist/index.d.ts +4 -2
  22. package/dist/index.js +38 -22
  23. package/dist/{parts-1_3y2JmR.d.ts → parts-IB-Kbb7z.d.ts} +146 -2
  24. package/dist/sandbox/index.d.ts +1 -1
  25. package/dist/stale-turn-lock-C8Na1cFZ.d.ts +149 -0
  26. package/dist/stream/index.d.ts +5 -192
  27. package/dist/stream/index.js +14 -12
  28. package/dist/stream-normalizer-DWvtmY6F.d.ts +48 -0
  29. package/dist/teams/index.js +9 -9
  30. package/dist/teams/invitations-api.js +7 -7
  31. package/dist/turn-buffer-C9mEgoop.d.ts +146 -0
  32. package/dist/turn-stream/index.d.ts +551 -0
  33. package/dist/turn-stream/index.js +837 -0
  34. package/dist/turn-stream/index.js.map +1 -0
  35. package/dist/web-react/index.d.ts +4 -3
  36. package/dist/web-react/index.js +24 -2
  37. package/package.json +6 -1
  38. package/dist/chunk-4AUQIAYU.js.map +0 -1
  39. package/dist/chunk-6E2XJSCT.js.map +0 -1
  40. package/dist/chunk-7VMUOD3G.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { F as FileMention } from './parts-1_3y2JmR.js';
1
+ import { K as FileMention } from './parts-IB-Kbb7z.js';
2
2
 
3
3
  /**
4
4
  * `createSandboxFileIndexRoute` — server side of `@`-file-mentions
package/dist/index.d.ts CHANGED
@@ -17,9 +17,11 @@ export { KeyCrypto, KeyProvisioner, PlanLimit, PlatformBalanceInfo, PlatformBala
17
17
  export { HttpHeadProbeConfig, PreflightProbe, PreflightProbeResult, PreflightProbeVerdict, PreflightReport, RouterChatProbeConfig, SandboxAuthProbeConfig, formatPreflightReport, httpHeadProbe, routerChatProbe, runPreflight, sandboxAuthProbe } from './preflight/index.js';
18
18
  export { ObjectBody, ObjectKeyParts, ObjectStore, PutObjectOptions, R2LikeBucket, R2LikeObjectBody, R2LikeObjectHead, SignObjectUrlArgs, VerifyObjectUrlResult, assertSafeKeySegment, createProxiedArtifactRoute, createR2ObjectStore, objectKey, signObjectUrl, verifyObjectUrl } from './object-store/index.js';
19
19
  export { B as BULK_DELETE_MAX_THREADS, C as ChatStoreInputError, t as threadTitleFromMessage } from './core-7qIM7svy.js';
20
- export { C as ChatFilePart, a as ChatImagePart, b as ChatInteractionPart, c as ChatMentionKind, d as ChatMentionPart, e as ChatMessagePart, f as ChatNoticePart, g as ChatPartTime, h as ChatPlanPart, i as ChatReasoningPart, j as ChatStepFinishPart, k as ChatStepStartPart, l as ChatSubtaskPart, m as ChatTextPart, n as ChatToolPart, o as ChatToolState, p as ChatToolStatus, q as ChatUsageTokens, S as StorableHarnessPartKind, r as isChatInteractionPart, s as isChatMentionPart, t as isChatPlanPart, u as isChatStepFinishPart, v as isChatTextPart, w as isChatToolPart, x as mentionInputToPart, y as mentionPartsFromMessageParts, z as toChatMessageParts } from './parts-1_3y2JmR.js';
20
+ export { C as ChatAttachmentKind, a as ChatAttachmentPart, b as ChatFilePart, c as ChatImagePart, d as ChatInteractionPart, e as ChatMentionKind, f as ChatMentionPart, g as ChatMessagePart, h as ChatNoticePart, i as ChatPartTime, j as ChatPlanPart, k as ChatReasoningPart, l as ChatStepFinishPart, m as ChatStepStartPart, n as ChatSubtaskPart, o as ChatTextPart, p as ChatToolPart, q as ChatToolState, r as ChatToolStatus, s as ChatUsageTokens, D as DEFAULT_ATTACHMENT_PROMPT_HEADER, S as StorableHarnessPartKind, t as attachmentInputToPart, u as attachmentKindForMime, v as attachmentPartsFromMessageParts, w as buildAttachmentPromptBlock, x as historyContentWithAttachments, y as isChatAttachmentPart, z as isChatInteractionPart, A as isChatMentionPart, B as isChatPlanPart, E as isChatStepFinishPart, F as isChatTextPart, G as isChatToolPart, H as mentionInputToPart, I as mentionPartsFromMessageParts, J as toChatMessageParts } from './parts-IB-Kbb7z.js';
21
21
  export { DeriveKeyOptions, createFieldCrypto, decodeHexKey, decryptAesGcm, decryptBytes, decryptWithKey, deriveKey, encryptAesGcm, encryptBytes, encryptWithKey } from './crypto/index.js';
22
- export { BufferedTurnEvent, BufferedTurnOptions, BufferedTurnTap, D1LikeForTurns, JsonRecord, MISSING_TOOL_TERMINAL_ERROR, MISSING_TOOL_TERMINAL_REASON, PersistedChatMessageForTurn, PumpBufferedTurnOptions, ReplayTurnEventsOptions, ResolvedChatTurn, StreamEvent, TURN_EVENTS_MIGRATION_SQL, TURN_STATUS_SCOPE_MIGRATION_SQL, TurnEventStore, TurnStatus, asRecord, asString, attachmentPartKey, buildUserTextParts, coalesceChatStreamEvents, coalesceDeltas, collapseRedundantTextParts, createBufferedTurnTap, createD1TurnEventStore, createMemoryTurnEventStore, encodeEvent, finalizeAssistantParts, finalizePendingInteractionParts, getPartKey, mergePersistedPart, messageHasTurnId, normalizeClientTurnId, normalizePersistedPart, normalizeTime, normalizeToolEvent, pumpBufferedTurn, replayTurnEvents, resolveChatTurn, resolveToolId, resolveToolName, terminalizeDanglingAssistantToolUpdates, terminalizeDanglingToolPart, terminalizeDanglingToolParts } from './stream/index.js';
22
+ export { J as JsonRecord, M as MISSING_TOOL_TERMINAL_ERROR, a as MISSING_TOOL_TERMINAL_REASON, S as StreamEvent, b as asRecord, c as asString, d as attachmentPartKey, e as collapseRedundantTextParts, f as encodeEvent, g as finalizeAssistantParts, h as finalizePendingInteractionParts, i as getPartKey, m as mergePersistedPart, n as normalizePersistedPart, j as normalizeTime, k as normalizeToolEvent, r as resolveToolId, l as resolveToolName, t as terminalizeDanglingAssistantToolUpdates, o as terminalizeDanglingToolPart, p as terminalizeDanglingToolParts } from './stream-normalizer-DWvtmY6F.js';
23
+ export { PersistedChatMessageForTurn, ResolvedChatTurn, buildUserTextParts, messageHasTurnId, normalizeClientTurnId, resolveChatTurn } from './stream/index.js';
24
+ export { B as BufferedTurnEvent, a as BufferedTurnOptions, b as BufferedTurnTap, D as D1LikeForTurns, P as PumpBufferedTurnOptions, R as ReplayTurnEventsOptions, T as TURN_EVENTS_MIGRATION_SQL, c as TURN_STATUS_SCOPE_MIGRATION_SQL, d as TurnEventStore, e as TurnStatus, f as coalesceChatStreamEvents, g as coalesceDeltas, h as createBufferedTurnTap, i as createD1TurnEventStore, j as createMemoryTurnEventStore, p as pumpBufferedTurn, r as replayTurnEvents } from './turn-buffer-C9mEgoop.js';
23
25
  export { HubExecClient, HubExecClientOptions, HubExecErrorCode, HubExecResult, HubInvokeDeps, HubInvokeInput, HubInvokeOutcome, ParsedIntegrationAction, invokeIntegrationHub, resolveIntegrationAction } from './integrations/index.js';
24
26
  export { C as ChatInteraction, a as ChatInteractionField, b as ChatInteractionStatus, c as ChatSelectField, d as ComposerAnswerDelivery, I as INTERACTION_CANCEL_EVENT, e as INTERACTION_EVENT, f as INTERACTION_RESOLVED_EVENT, g as InteractionAnswerValue, h as InteractionAnswers, i as InteractionCancelData, j as InteractionPersistedPart, k as InteractionRequestWire, N as NoticeKind, l as NoticePersistedPart, P as ParseInteractionAnswersResult, m as ParseInteractionResult, n as canTransitionInteractionStatus, o as cancelStatusFor, p as composerAnswerData, q as composerAnswerDeliveries, r as dedupeQuestionInteractionsByContent, s as fieldAcceptsFreeText, t as interactionFromWireRequest, u as interactionPartKey, v as interactionToPersistedPart, w as isRenderableInteractionKind, x as isSafeInteractionFieldKey, y as isTerminalInteractionStatus, z as noticePart, A as noticePartKey, B as parseInteractionAnswers, D as parseInteractionCancel, E as parseInteractionRequest, F as persistedPartToInteraction, G as questionInteractionContentSignature, H as stampInteractionAnswers } from './contract-KfqJh_au.js';
25
27
  export { BeforeInteractionAnswerArgs, DurableInteractionRouteArgs, DurableInteractionRoutePersistence, InteractionAnswerBodyValidation, InteractionAnswerRoute, InteractionAnswerRouteOptions, InteractionClientOutcome, InteractionConnectionResolution, InteractionRouteLogger, ResolveInteractionConnectionArgs, SidecarInteractionsConnection, SidecarInteractionsError, SidecarInteractionsResult, createInteractionAnswerRoute, listSessionInteractions, mapInteractionRespondFailure, respondToSessionInteraction, validateInteractionAnswerBody } from './interactions/index.js';
package/dist/index.js CHANGED
@@ -244,39 +244,20 @@ import {
244
244
  threadTitleFromMessage
245
245
  } from "./chunk-5EQCITY3.js";
246
246
  import {
247
- MISSING_TOOL_TERMINAL_ERROR,
248
- MISSING_TOOL_TERMINAL_REASON,
249
247
  TURN_EVENTS_MIGRATION_SQL,
250
248
  TURN_STATUS_SCOPE_MIGRATION_SQL,
251
- asRecord,
252
- asString,
253
- attachmentPartKey,
254
249
  buildUserTextParts,
255
250
  coalesceChatStreamEvents,
256
251
  coalesceDeltas,
257
- collapseRedundantTextParts,
258
252
  createBufferedTurnTap,
259
253
  createD1TurnEventStore,
260
254
  createMemoryTurnEventStore,
261
- encodeEvent,
262
- finalizeAssistantParts,
263
- finalizePendingInteractionParts,
264
- getPartKey,
265
- mergePersistedPart,
266
255
  messageHasTurnId,
267
256
  normalizeClientTurnId,
268
- normalizePersistedPart,
269
- normalizeTime,
270
- normalizeToolEvent,
271
257
  pumpBufferedTurn,
272
258
  replayTurnEvents,
273
- resolveChatTurn,
274
- resolveToolId,
275
- resolveToolName,
276
- terminalizeDanglingAssistantToolUpdates,
277
- terminalizeDanglingToolPart,
278
- terminalizeDanglingToolParts
279
- } from "./chunk-4AUQIAYU.js";
259
+ resolveChatTurn
260
+ } from "./chunk-23LUHHHN.js";
280
261
  import {
281
262
  createInteractionAnswerRoute,
282
263
  listSessionInteractions,
@@ -296,6 +277,13 @@ import {
296
277
  serializeCookie
297
278
  } from "./chunk-HFC4BTWJ.js";
298
279
  import {
280
+ DEFAULT_ATTACHMENT_PROMPT_HEADER,
281
+ attachmentInputToPart,
282
+ attachmentKindForMime,
283
+ attachmentPartsFromMessageParts,
284
+ buildAttachmentPromptBlock,
285
+ historyContentWithAttachments,
286
+ isChatAttachmentPart,
299
287
  isChatInteractionPart,
300
288
  isChatMentionPart,
301
289
  isChatPlanPart,
@@ -305,7 +293,28 @@ import {
305
293
  mentionInputToPart,
306
294
  mentionPartsFromMessageParts,
307
295
  toChatMessageParts
308
- } from "./chunk-6E2XJSCT.js";
296
+ } from "./chunk-JGYOYY5D.js";
297
+ import {
298
+ MISSING_TOOL_TERMINAL_ERROR,
299
+ MISSING_TOOL_TERMINAL_REASON,
300
+ asRecord,
301
+ asString,
302
+ attachmentPartKey,
303
+ collapseRedundantTextParts,
304
+ encodeEvent,
305
+ finalizeAssistantParts,
306
+ finalizePendingInteractionParts,
307
+ getPartKey,
308
+ mergePersistedPart,
309
+ normalizePersistedPart,
310
+ normalizeTime,
311
+ normalizeToolEvent,
312
+ resolveToolId,
313
+ resolveToolName,
314
+ terminalizeDanglingAssistantToolUpdates,
315
+ terminalizeDanglingToolPart,
316
+ terminalizeDanglingToolParts
317
+ } from "./chunk-5MG74GVQ.js";
309
318
  import {
310
319
  INTERACTION_CANCEL_EVENT,
311
320
  INTERACTION_EVENT,
@@ -524,6 +533,7 @@ export {
524
533
  ConversionMetricsSchema,
525
534
  CopyContentSchema,
526
535
  DEFAULT_APP_TOOL_PATHS,
536
+ DEFAULT_ATTACHMENT_PROMPT_HEADER,
527
537
  DEFAULT_DESIGN_CANVAS_MCP_DESCRIPTION,
528
538
  DEFAULT_HARNESS,
529
539
  DEFAULT_HEADER_NAMES,
@@ -604,7 +614,10 @@ export {
604
614
  assertSceneMediaSrc,
605
615
  assertSequenceMediaUrl,
606
616
  attachReasoningEffort,
617
+ attachmentInputToPart,
618
+ attachmentKindForMime,
607
619
  attachmentPartKey,
620
+ attachmentPartsFromMessageParts,
608
621
  authenticateToolRequest,
609
622
  bearerSubprotocolToken,
610
623
  bearerToken,
@@ -616,6 +629,7 @@ export {
616
629
  buildAppToolMcpServer,
617
630
  buildAppToolMcpServers,
618
631
  buildAppToolOpenAITools,
632
+ buildAttachmentPromptBlock,
619
633
  buildCaptionChunks,
620
634
  buildCatalog,
621
635
  buildConsentUrl,
@@ -755,6 +769,7 @@ export {
755
769
  getClient,
756
770
  getPartKey,
757
771
  handleAppToolRequest,
772
+ historyContentWithAttachments,
758
773
  httpHeadProbe,
759
774
  instantiateTemplate,
760
775
  interactionFromWireRequest,
@@ -762,6 +777,7 @@ export {
762
777
  interactionToPersistedPart,
763
778
  invokeIntegrationHub,
764
779
  isAppToolName,
780
+ isChatAttachmentPart,
765
781
  isChatInteractionPart,
766
782
  isChatMentionPart,
767
783
  isChatPlanPart,
@@ -29,6 +29,27 @@ interface ChatTurnFilePartInput {
29
29
  content?: string;
30
30
  }
31
31
  type ChatTurnPartInput = ChatTurnTextPartInput | ChatTurnFilePartInput;
32
+ /** The image/file split an attachment is rendered and persisted under — the
33
+ * same discriminant as {@link ChatMentionKind}, but a distinct name because an
34
+ * attachment carries content the product uploaded (`ChatAttachmentInput`)
35
+ * while a mention points at a file the box already has. Defined HERE (the
36
+ * import-free layer) so `ChatAttachmentInput` can reference it and the client
37
+ * composer imports it without pulling the persisted-part vocabulary;
38
+ * `/chat-store`'s parts module re-exports it alongside the attachment helpers. */
39
+ type ChatAttachmentKind = 'image' | 'file';
40
+ /** `POST` turn-body entry describing a file already uploaded to the product's
41
+ * store (vault/object-store) — distinct from an inline {@link
42
+ * ChatTurnFilePartInput} (which carries bytes) and from a {@link FileMention}
43
+ * (a sandbox path the box already holds). The route resolves this field with
44
+ * {@link resolveChatAttachments}: every path is re-validated and every size is
45
+ * re-derived from the stored body, so nothing here is trusted as sent. */
46
+ interface ChatAttachmentInput {
47
+ path: string;
48
+ name: string;
49
+ size: number;
50
+ mediaType: string;
51
+ kind: ChatAttachmentKind;
52
+ }
32
53
  /** POST body for the turn route. `content` may be empty when `parts` carry the
33
54
  * message (an image-only send). Product routing fields (workspaceId etc.) ride
34
55
  * alongside and are read by the product's `authorize` seam. */
@@ -45,6 +66,12 @@ interface ChatTurnRequestPayload {
45
66
  * route validates this field with {@link parseFileMentions} and replaces it
46
67
  * on the payload with the validated, deduped list. */
47
68
  mentions?: FileMention[];
69
+ /** Files uploaded to the product's store ahead of the turn — path
70
+ * references, NOT inline bytes (those ride `parts`). Validated and
71
+ * size-re-derived by {@link resolveChatAttachments} into persistable
72
+ * attachment parts; a product whose `parts` field is spoken for by inline
73
+ * uploads still sends store-backed files here. */
74
+ attachments?: ChatAttachmentInput[];
48
75
  model?: string;
49
76
  effort?: 'auto' | 'low' | 'medium' | 'high';
50
77
  harness?: string;
@@ -57,6 +84,41 @@ interface ChatTurnRequestPayload {
57
84
  * parser. */
58
85
  declare function chatTurnRequestInit(payload: ChatTurnRequestPayload): RequestInit;
59
86
  declare const INLINE_PARTS_MAX_BYTES = 950000;
87
+ /** Hard cap on the whole `/prompt` request body as it crosses the sandbox
88
+ * proxy — smaller in practice than a raw-file write cap because a dispatch
89
+ * carries several inline parts plus the flattened history in one request. */
90
+ declare const DISPATCH_REQUEST_MAX_BYTES: number;
91
+ /** Bytes reserved off the top of {@link DISPATCH_REQUEST_MAX_BYTES} for the
92
+ * JSON structure around the parts array (keys, delimiters, per-part
93
+ * `type`/`filename`/`mediaType` fields) that {@link base64WireLen} does not
94
+ * account for — keeps the inline budget off the exact proxy cap where one
95
+ * stray byte trips the 413. */
96
+ declare const DISPATCH_STRUCTURAL_RESERVE_BYTES: number;
97
+ /** Sidecar's hard cap on the `parts` array of one prompt request — a dispatch
98
+ * must never assemble more parts than this or the whole turn 400s. */
99
+ declare const DISPATCH_MAX_PARTS = 64;
100
+ /** Product-side cap on media parts per dispatch (current turn + carried
101
+ * history), well under {@link DISPATCH_MAX_PARTS}. History trimming that keeps
102
+ * a transcript's native media under this is a PRODUCT concern (the pointer
103
+ * block keeps trimmed media reachable); `buildDispatchParts` enforces only the
104
+ * total {@link DISPATCH_MAX_PARTS} cap. */
105
+ declare const DISPATCH_MAX_MEDIA_PARTS = 24;
106
+ /** Size a base64-encoded string occupies on the wire given the raw
107
+ * (pre-encoding) byte length: base64 packs 3 raw bytes into 4 output
108
+ * characters, rounded up to the next multiple of 4. */
109
+ declare function base64WireLen(byteLen: number): number;
110
+ /**
111
+ * Render a raw byte count as a human-readable size (`512B`, `3KB`, `12MB
112
+ * 500KB`). Ported EXACTLY from gtm-agent's `attachment-limits.ts` — byte-
113
+ * identical implementation, not a reinterpretation — so `resolve-attachments`'s
114
+ * and `promote-file-part`'s error strings match gtm's wording verbatim. Lives
115
+ * in the import-free wire layer (not `resolve-attachments.ts` alone) because
116
+ * BOTH the aggregate-cap message here and the per-file oversize message in
117
+ * `promote-file-part.ts` need it; a browser composer wanting the same
118
+ * formatting for a client-side pre-check can also import it with no engine
119
+ * pulled in.
120
+ */
121
+ declare function formatBytes(bytes: number): string;
60
122
  declare class ChatTurnInputError extends Error {
61
123
  readonly status: number;
62
124
  readonly code: string;
@@ -229,11 +291,15 @@ interface ChatToolPart {
229
291
  state: ChatToolState;
230
292
  }
231
293
  /** Union of the sidecar's legacy (path-based) and AI-SDK (url-based) file
232
- * shapes; response-side every field besides `type` is optional. */
294
+ * shapes; response-side every field besides `type` is optional. `name` is the
295
+ * attachment-flavored display label an uploaded/promoted file carries (see
296
+ * {@link ChatAttachmentPart}) — absent on a harness-emitted file part, which
297
+ * uses `filename`. */
233
298
  interface ChatFilePart {
234
299
  type: 'file';
235
300
  id?: string;
236
301
  filename?: string;
302
+ name?: string;
237
303
  mediaType?: string;
238
304
  url?: string;
239
305
  path?: string;
@@ -242,6 +308,7 @@ interface ChatFilePart {
242
308
  interface ChatImagePart {
243
309
  type: 'image';
244
310
  filename?: string;
311
+ name?: string;
245
312
  mediaType?: string;
246
313
  url?: string;
247
314
  path?: string;
@@ -364,5 +431,82 @@ declare function mentionPartsFromMessageParts(parts: ReadonlyArray<Record<string
364
431
  * than stored as `undefined`, so a stored row never carries a key that means
365
432
  * nothing. */
366
433
  declare function mentionInputToPart(input: FileMention): ChatMentionPart;
434
+ /** `image` for any `image/*` mime, `file` for everything else (including an
435
+ * absent/empty mime) — the same split the composer and the persisted-part
436
+ * discriminant both key on. */
437
+ declare function attachmentKindForMime(mime?: string): ChatAttachmentKind;
438
+
439
+ /**
440
+ * Persisted attachment part: structurally an attachment-flavored `ChatFilePart`
441
+ * / `ChatImagePart` (`path` + `name` promoted to required) rather than a
442
+ * separate union member — see the section note above. The index signature keeps
443
+ * it a `Record<string, unknown>` so it drops into the same untyped `parts`
444
+ * arrays every other stored part rides in, and lets the `type`-driven
445
+ * constructors below build it without union-discriminant gymnastics.
446
+ */
447
+ interface ChatAttachmentPart {
448
+ type: ChatAttachmentKind;
449
+ path: string;
450
+ name: string;
451
+ size?: number;
452
+ mediaType?: string;
453
+ turnId?: string;
454
+ [key: string]: unknown;
455
+ }
456
+ /** True for any `image`/`file` part carrying a non-empty string `path`.
457
+ * DELIBERATELY also matches a sidecar path-bearing file part (a mention-style
458
+ * `file` part with only `path`) — the guard is a structural attachment shape,
459
+ * not proof of provenance; a caller that needs to exclude those filters
460
+ * upstream. The `path.length > 0` check diverges from gtm's original guard
461
+ * (which only checked `typeof`), mirroring sibling {@link isChatMentionPart}:
462
+ * read-side robustness against a stored `{type:'file', path:''}` row — which
463
+ * would otherwise render a malformed `(vault: )` pointer line — justifies the
464
+ * small divergence from byte-for-byte gtm parity here; no legitimate write
465
+ * path ever produces an empty `path`. */
466
+ declare function isChatAttachmentPart(part: unknown): part is ChatAttachmentPart;
467
+ /** Drop absent/empty optional fields rather than persisting `undefined`/`''`
468
+ * — keeps stored parts minimal. */
469
+ declare function attachmentInputToPart(input: ChatAttachmentInput): ChatAttachmentPart;
470
+ /** Every attachment part on one message's stored `parts`, in stored order. */
471
+ declare function attachmentPartsFromMessageParts(parts: ReadonlyArray<Record<string, unknown>> | null | undefined): ChatAttachmentPart[];
472
+ /** gtm's exact default header for {@link buildAttachmentPromptBlock} — kept
473
+ * byte-identical because it feeds dispatched prompts (gtm-agent#618
474
+ * reproduces the prompt bytes through this module). Override only with intent. */
475
+ declare const DEFAULT_ATTACHMENT_PROMPT_HEADER = "Attached files (already saved to the workspace vault \u2014 read them from these paths):";
476
+ /**
477
+ * The agent-facing pointer block appended to the dispatched prompt — never
478
+ * persisted in `message.content`. Empty array → `''` so callers can append
479
+ * unconditionally. The sole producer of this text: both the current turn's
480
+ * dispatch and history projection ({@link historyContentWithAttachments}) build
481
+ * it from here, so the two can never drift. `header` overrides the first line
482
+ * ({@link DEFAULT_ATTACHMENT_PROMPT_HEADER}); the per-file line format is fixed.
483
+ *
484
+ * Every interpolated `name`/`path` is swept for control characters first
485
+ * (newline/carriage-return/tab included) and each one replaced with a single
486
+ * space — a single-line-per-file guarantee. Without it, a control character
487
+ * riding through on a PERSISTED row (`historyContentWithAttachments` reads
488
+ * whatever is already stored; a legacy or hand-edited row was never re-checked
489
+ * against `resolveChatAttachments`) could inject extra lines — fabricated
490
+ * pointer entries or instructions — into a prompt the agent trusts verbatim.
491
+ * The wire-side validator is the primary control; this is the backstop for
492
+ * rows it never saw.
493
+ */
494
+ declare function buildAttachmentPromptBlock(atts: ReadonlyArray<Pick<ChatAttachmentPart, 'name' | 'path'>>, header?: string): string;
495
+ /**
496
+ * History projection for a persisted message: `content` unchanged when it
497
+ * carries no attachment parts, else the block is appended once. The
498
+ * no-double-annotation guarantee holds under the invariant that the block is
499
+ * never persisted INTO `message.content` — it is appended only at read time,
500
+ * by this function and the current turn's dispatch, both sourcing from
501
+ * `attachmentPartsFromMessageParts` — never by content inspection. This
502
+ * function does not (and cannot) detect an already-embedded block by scanning
503
+ * `content` for its text: a message whose stored `content` happens to already
504
+ * contain the block's bytes, alongside attachment parts, still gets the block
505
+ * appended a second time. See the pinned test for that boundary.
506
+ */
507
+ declare function historyContentWithAttachments(message: {
508
+ content: string;
509
+ parts?: ReadonlyArray<Record<string, unknown>> | null;
510
+ }, header?: string): string;
367
511
 
368
- export { type ChatTurnRequestPayload as A, type ChatTurnPartInput as B, type ChatFilePart as C, type ChatTurnFilePartInput as D, ChatTurnInputError as E, type FileMention as F, type ChatTurnTextPartInput as G, type FileMentionsToPartsOptions as H, INLINE_PARTS_MAX_BYTES as I, type SandboxMentionPathCheck as J, assertPromptPartsWithinCap as K, buildMentionPromptBlock as L, MENTION_MAX_COUNT as M, chatTurnRequestInit as N, fileMentionsToParts as O, mediaTypeForMentionPath as P, mentionKindForPath as Q, parseChatTurnParts as R, type StorableHarnessPartKind as S, parseFileMentions as T, promptPartsByteSize as U, validateSandboxMentionPath as V, type ChatImagePart as a, type ChatInteractionPart as b, type ChatMentionKind as c, type ChatMentionPart as d, type ChatMessagePart as e, type ChatNoticePart as f, type ChatPartTime as g, type ChatPlanPart as h, type ChatReasoningPart as i, type ChatStepFinishPart as j, type ChatStepStartPart as k, type ChatSubtaskPart as l, type ChatTextPart as m, type ChatToolPart as n, type ChatToolState as o, type ChatToolStatus as p, type ChatUsageTokens as q, isChatInteractionPart as r, isChatMentionPart as s, isChatPlanPart as t, isChatStepFinishPart as u, isChatTextPart as v, isChatToolPart as w, mentionInputToPart as x, mentionPartsFromMessageParts as y, toChatMessageParts as z };
512
+ export { base64WireLen as $, isChatMentionPart as A, isChatPlanPart as B, type ChatAttachmentKind as C, DEFAULT_ATTACHMENT_PROMPT_HEADER as D, isChatStepFinishPart as E, isChatTextPart as F, isChatToolPart as G, mentionInputToPart as H, mentionPartsFromMessageParts as I, toChatMessageParts as J, type FileMention as K, type ChatTurnRequestPayload as L, type ChatTurnPartInput as M, type ChatTurnFilePartInput as N, type ChatAttachmentInput as O, ChatTurnInputError as P, type ChatTurnTextPartInput as Q, DISPATCH_MAX_MEDIA_PARTS as R, type StorableHarnessPartKind as S, DISPATCH_MAX_PARTS as T, DISPATCH_REQUEST_MAX_BYTES as U, DISPATCH_STRUCTURAL_RESERVE_BYTES as V, type FileMentionsToPartsOptions as W, INLINE_PARTS_MAX_BYTES as X, MENTION_MAX_COUNT as Y, type SandboxMentionPathCheck as Z, assertPromptPartsWithinCap as _, type ChatAttachmentPart as a, buildMentionPromptBlock as a0, chatTurnRequestInit as a1, fileMentionsToParts as a2, formatBytes as a3, mediaTypeForMentionPath as a4, mentionKindForPath as a5, parseChatTurnParts as a6, parseFileMentions as a7, promptPartsByteSize as a8, validateSandboxMentionPath as a9, type ChatFilePart as b, type ChatImagePart as c, type ChatInteractionPart as d, type ChatMentionKind as e, type ChatMentionPart as f, type ChatMessagePart as g, type ChatNoticePart as h, type ChatPartTime as i, type ChatPlanPart as j, type ChatReasoningPart as k, type ChatStepFinishPart as l, type ChatStepStartPart as m, type ChatSubtaskPart as n, type ChatTextPart as o, type ChatToolPart as p, type ChatToolState as q, type ChatToolStatus as r, type ChatUsageTokens as s, attachmentInputToPart as t, attachmentKindForMime as u, attachmentPartsFromMessageParts as v, buildAttachmentPromptBlock as w, historyContentWithAttachments as x, isChatAttachmentPart as y, isChatInteractionPart as z };
@@ -1,4 +1,4 @@
1
- import { AgentProfileMcpServer, ProvisionEvent, SandboxInstance, AgentProfileFileMount, AgentProfile, StorageConfig, ScopedTokenScope, TurnDriveResult, Sandbox } from '@tangle-network/sandbox';
1
+ import { SandboxInstance, AgentProfileMcpServer, ProvisionEvent, AgentProfileFileMount, AgentProfile, StorageConfig, ScopedTokenScope, TurnDriveResult, Sandbox } from '@tangle-network/sandbox';
2
2
  export { StorageConfig } from '@tangle-network/sandbox';
3
3
  import { a as ToolHeaderNames } from '../auth-DuptSkWh.js';
4
4
  import { f as AppToolName, c as AppToolContext } from '../types-BEOvc_ue.js';
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Recovery policy for a `ChatTurnLock` whose holder died.
3
+ *
4
+ * `createChatTurnRoutes` takes the lock as a seam (`acquire`/`release`) and a
5
+ * lock is a single-flight guard: while it is held, a second turn on the same
6
+ * scope is refused. Products give it a TTL measured in tens of minutes, so a
7
+ * turn that dies without releasing wedges chat for that whole window. Every
8
+ * app on the seam inherits that wedge, which is why the way OUT of it is
9
+ * policy this package owns rather than something each app rediscovers.
10
+ *
11
+ * The policy takes PROBES, not clients: it imports no sandbox SDK, opens no
12
+ * connection, and knows nothing about how a product finds its box or talks to
13
+ * a sidecar. That is what makes the rules testable and what keeps the concrete
14
+ * probes — which box key, which session id, which sidecar endpoint — in the
15
+ * product.
16
+ *
17
+ * The rules, in precedence order:
18
+ *
19
+ * 1. The session probe answered and the execution is TERMINAL ⇒ release, once
20
+ * the lock is past a short grace period. The authority on "is this turn
21
+ * still running" is whatever is actually running it; a terminal verdict is
22
+ * proof the lock outlived its turn — but only if the verdict is about THIS
23
+ * turn, which is what the grace buys (see
24
+ * {@link DEFAULT_TERMINAL_TURN_LOCK_GRACE_MS}).
25
+ * 2. The session probe answered and the execution is LIVE ⇒ hold, always.
26
+ * Nothing below may override this. The lock is doing exactly its job.
27
+ * 3. The probes could not reach that authority at all — the sandbox could not
28
+ * be listed, is gone, is not running, or its session probe failed ⇒ fall
29
+ * back on the physical argument: an execution runs INSIDE the box, so a box
30
+ * that is not there is running nothing, and the lock is releasable. Without
31
+ * this fallback the recovery would depend on the very subsystem whose
32
+ * failure produced the stale lock.
33
+ *
34
+ * Rule 3 is gated on a grace period because it is an inference, not an
35
+ * observation — see {@link DEFAULT_STALE_TURN_LOCK_GRACE_MS}.
36
+ */
37
+ /** Where the box is, as far as the caller can see. `state` on `not-running`
38
+ * is the platform's own status string, carried through for the log. */
39
+ type StaleTurnLockSandboxProbeResult = {
40
+ status: 'running';
41
+ } | {
42
+ status: 'absent';
43
+ } | {
44
+ status: 'not-running';
45
+ state?: string;
46
+ };
47
+ /** What the thing running the turn says about it. `terminal: false` means an
48
+ * execution is LIVE — the strongest signal in the policy. `diagnostics` rides
49
+ * through to the result and the logs unread. */
50
+ type StaleTurnLockSessionProbeResult = {
51
+ reachable: true;
52
+ terminal: boolean;
53
+ diagnostics?: Record<string, unknown>;
54
+ } | {
55
+ reachable: false;
56
+ reason?: string;
57
+ };
58
+ /**
59
+ * Minimum age a lock must reach before the "sandbox unreachable ⇒ nothing can
60
+ * be running" fallback may force-release it.
61
+ *
62
+ * The lock is acquired BEFORE the box is ensured, so during a cold workspace's
63
+ * first turn there is a real window in which the lock is held and no box exists
64
+ * yet — indistinguishable, from a peek, from a box that vanished. The grace
65
+ * period has to outlast that window (create + bootstrap + whatever the product
66
+ * hydrates) or a concurrent request steals the lock from a turn that is merely
67
+ * still provisioning. Five minutes clears observed cold starts with room to
68
+ * spare while cutting the worst case from a TTL-length wedge down to five
69
+ * minutes. Raising it makes recovery slower; lowering it risks stealing a lock
70
+ * mid-provision.
71
+ */
72
+ declare const DEFAULT_STALE_TURN_LOCK_GRACE_MS: number;
73
+ /**
74
+ * Minimum age a lock must reach before a TERMINAL session verdict may release
75
+ * it.
76
+ *
77
+ * The session probe is keyed on the THREAD, not on the execution the lock
78
+ * holds: a sidecar that has nothing running reports `terminal` with
79
+ * `activeExecutionId: null`, so there is no id to match the lock against. The
80
+ * lock, meanwhile, is acquired BEFORE the box is ensured and before the
81
+ * execution registers with the sidecar. Between those two moments a second
82
+ * request that reconciles the lock asks the sidecar about a turn it has not
83
+ * heard of yet and gets back the PREVIOUS turn's terminal state — proof about
84
+ * the wrong execution. Releasing on that verdict hands the second request a
85
+ * lock the first one is still using, which is two concurrent turns on a scope
86
+ * whose single-flight guard just voted for itself.
87
+ *
88
+ * One minute covers the acquire → box-ensure → sidecar-registration window on
89
+ * a warm box (the cold-box case is Rule 3's, and has its own, much longer
90
+ * grace). Deliberately NOT
91
+ * {@link DEFAULT_STALE_TURN_LOCK_GRACE_MS}: this branch has a positive
92
+ * observation behind it, so it should recover fast, and stretching it to five
93
+ * minutes would leave a genuinely dead turn wedged for the whole window that
94
+ * the session probe exists to shortcut. Raising it delays recovery from a
95
+ * crashed turn; lowering it narrows the registration window it protects.
96
+ */
97
+ declare const DEFAULT_TERMINAL_TURN_LOCK_GRACE_MS: number;
98
+ interface ReconcileStaleTurnLockOptions {
99
+ /** When the held lock was acquired (epoch ms). The grace period is measured
100
+ * from here, so it must be the LOCK's start, not the turn's. */
101
+ lockStartedAt: number;
102
+ /** Is the box there and running? Never provisions — a peek, not an ensure.
103
+ * A throw is treated as unreachable, same as `absent`. */
104
+ probeSandbox(): Promise<StaleTurnLockSandboxProbeResult>;
105
+ /** Ask the running box whether the execution is still live. Only called when
106
+ * `probeSandbox` reported `running`. A throw is treated as unreachable. */
107
+ probeSession(): Promise<StaleTurnLockSessionProbeResult>;
108
+ /** Release the lock, fenced by the instant the releasing evidence was
109
+ * observed. `fence.observedAt` is snapshotted BEFORE the probe that
110
+ * justified the release, so a store that can compare it against the held
111
+ * lock's start refuses to delete a SUCCESSOR lock acquired while the probe
112
+ * was in flight. A store that cannot make that comparison may ignore the
113
+ * fence, but must not substitute its own `Date.now()` — that timestamp is
114
+ * by construction newer than any successor and makes the check vacuous.
115
+ *
116
+ * Returns whether the release actually landed — `false` when the lock was
117
+ * already gone (someone else got there first), which is reported, never
118
+ * treated as a release. */
119
+ release(fence: {
120
+ observedAt: number;
121
+ }): boolean | Promise<boolean>;
122
+ /** Override {@link DEFAULT_STALE_TURN_LOCK_GRACE_MS} (Rule 3's fallback). */
123
+ graceMs?: number;
124
+ /** Override {@link DEFAULT_TERMINAL_TURN_LOCK_GRACE_MS} (Rule 1's release). */
125
+ terminalGraceMs?: number;
126
+ /** Identity fields merged into every log line (workspace, thread, execution
127
+ * id — whatever makes the entry findable in the product's logs). */
128
+ context?: Record<string, unknown>;
129
+ /** Defaults to `console.warn`. Both the withheld and the force-released
130
+ * branches log; a force-release is never silent. */
131
+ log?(message: string, meta: Record<string, unknown>): void;
132
+ /** Injectable clock, for tests. */
133
+ now?(): number;
134
+ }
135
+ interface ReconcileStaleTurnLockResult {
136
+ released: boolean;
137
+ /** Why the policy decided what it did — the probe's own diagnostics on the
138
+ * reachable path, the unreachable reason and lock age on the fallback. */
139
+ diagnostics: Record<string, unknown>;
140
+ }
141
+ /**
142
+ * Decide whether a held lock is stale and, if so, release it.
143
+ *
144
+ * Never provisions and never mutates anything but the lock: a reconciliation
145
+ * attempt on a cold workspace leaves it cold.
146
+ */
147
+ declare function reconcileStaleTurnLock(options: ReconcileStaleTurnLockOptions): Promise<ReconcileStaleTurnLockResult>;
148
+
149
+ export { DEFAULT_STALE_TURN_LOCK_GRACE_MS as D, type ReconcileStaleTurnLockOptions as R, type StaleTurnLockSandboxProbeResult as S, DEFAULT_TERMINAL_TURN_LOCK_GRACE_MS as a, type ReconcileStaleTurnLockResult as b, type StaleTurnLockSessionProbeResult as c, reconcileStaleTurnLock as r };