@tangle-network/agent-app 0.43.76 → 0.44.2

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 (153) hide show
  1. package/README.md +1 -1
  2. package/dist/DesignCanvas-Z362I3R3.js +10 -0
  3. package/dist/{DesignCanvasEditor-FJIVYOA2.js → DesignCanvasEditor-ZFE2W4OJ.js} +4 -4
  4. package/dist/assets/index.d.ts +4 -4
  5. package/dist/assets/index.js +223 -11
  6. package/dist/assets/index.js.map +1 -1
  7. package/dist/assistant/index.d.ts +7 -7
  8. package/dist/assistant/index.js +3 -3
  9. package/dist/assistant/index.js.map +1 -1
  10. package/dist/{attachment-validation-Dv1A_Puy.d.ts → attachment-validation-DRuLEjAE.d.ts} +1 -1
  11. package/dist/{auth-_FU8w01b.d.ts → auth-anc7mv2W.d.ts} +2 -2
  12. package/dist/chat-routes/index.d.ts +65 -14
  13. package/dist/chat-routes/index.js +61 -24
  14. package/dist/chat-routes/index.js.map +1 -1
  15. package/dist/chat-store/index.d.ts +26 -7
  16. package/dist/chat-store/index.js +14 -5
  17. package/dist/chat-store/index.js.map +1 -1
  18. package/dist/{chunk-ROLFDOMJ.js → chunk-4TI7QWLW.js} +3 -3
  19. package/dist/{chunk-3JUTOVUH.js → chunk-6KMAM7BL.js} +1 -1
  20. package/dist/chunk-6KMAM7BL.js.map +1 -0
  21. package/dist/{chunk-WL7XHLDK.js → chunk-ICOHEZK6.js} +77 -5
  22. package/dist/chunk-ICOHEZK6.js.map +1 -0
  23. package/dist/{chunk-22GLESKE.js → chunk-O63WWYET.js} +2 -4
  24. package/dist/chunk-O63WWYET.js.map +1 -0
  25. package/dist/{chunk-E7N67FYI.js → chunk-Q3FONVAK.js} +5 -5
  26. package/dist/{chunk-E7N67FYI.js.map → chunk-Q3FONVAK.js.map} +1 -1
  27. package/dist/{chunk-RXOTWZ4G.js → chunk-TKRI463Z.js} +4 -4
  28. package/dist/chunk-TKRI463Z.js.map +1 -0
  29. package/dist/config/index.d.ts +1 -1
  30. package/dist/config/index.js +123 -4
  31. package/dist/config/index.js.map +1 -1
  32. package/dist/{contract-B3h7peV3.d.ts → contract-CEewO6DI.d.ts} +1 -1
  33. package/dist/design-canvas/index.d.ts +4 -4
  34. package/dist/design-canvas-react/index.js +7 -7
  35. package/dist/design-canvas-react/lazy.js +1 -1
  36. package/dist/eval/index.d.ts +1 -1
  37. package/dist/eval/index.js +22 -8
  38. package/dist/eval/index.js.map +1 -1
  39. package/dist/{flow-types-CqomVAUN.d.ts → flow-types-CJxEmaRy.d.ts} +1 -1
  40. package/dist/integrations/index.js +67 -5
  41. package/dist/integrations/index.js.map +1 -1
  42. package/dist/interactions/index.d.ts +6 -4
  43. package/dist/interactions/index.js +1 -2
  44. package/dist/knowledge/index.js +63 -4
  45. package/dist/knowledge/index.js.map +1 -1
  46. package/dist/knowledge-loop/index.d.ts +1 -1
  47. package/dist/knowledge-loop/index.js +94 -4
  48. package/dist/knowledge-loop/index.js.map +1 -1
  49. package/dist/{mcp-BjPqQ-3C.d.ts → mcp-D3qVzbE1.d.ts} +2 -2
  50. package/dist/{mcp-rpc-BfUOsalw.d.ts → mcp-rpc-CzU5LWWT.d.ts} +1 -1
  51. package/dist/missions/index.js +1143 -23
  52. package/dist/missions/index.js.map +1 -1
  53. package/dist/{model-DmdkIteM.d.ts → model-CdCDfBA9.d.ts} +1 -1
  54. package/dist/object-store/index.js +113 -8
  55. package/dist/object-store/index.js.map +1 -1
  56. package/dist/{parts-2ymE5cs-.d.ts → parts-Co_lFgLI.d.ts} +3 -3
  57. package/dist/platform/index.d.ts +1 -1
  58. package/dist/preflight/cli.d.ts +13 -0
  59. package/dist/preflight/cli.js +50 -0
  60. package/dist/preflight/cli.js.map +1 -0
  61. package/dist/preset-cloudflare/index.d.ts +1 -1
  62. package/dist/preset-cloudflare/index.js +284 -11
  63. package/dist/preset-cloudflare/index.js.map +1 -1
  64. package/dist/{queue-C24V13h9.d.ts → queue-CD5-_VTX.d.ts} +1 -1
  65. package/dist/redact/index.js +116 -8
  66. package/dist/redact/index.js.map +1 -1
  67. package/dist/runtime/index.d.ts +19 -111
  68. package/dist/runtime/index.js +234 -14
  69. package/dist/runtime/index.js.map +1 -1
  70. package/dist/sandbox/index.d.ts +3 -3
  71. package/dist/sandbox/index.js +2 -3
  72. package/dist/sequences/index.d.ts +4 -4
  73. package/dist/stream/index.d.ts +4 -4
  74. package/dist/{stream-normalizer-QYUl4vnl.d.ts → stream-normalizer-DnuqkZvw.d.ts} +2 -2
  75. package/dist/tangle/index.js +42 -4
  76. package/dist/tangle/index.js.map +1 -1
  77. package/dist/teams/index.js +5 -5
  78. package/dist/teams/invitations-api.js +4 -4
  79. package/dist/teams-react/index.js +3 -3
  80. package/dist/theme/index.js +0 -1
  81. package/dist/tools/index.d.ts +6 -6
  82. package/dist/tools/index.js +5 -7
  83. package/dist/trace/index.d.ts +1 -1
  84. package/dist/trace/index.js +179 -10
  85. package/dist/trace/index.js.map +1 -1
  86. package/dist/{turn-buffer-BaSgxVmK.d.ts → turn-buffer-BcPfhr1_.d.ts} +1 -1
  87. package/dist/turn-stream/index.d.ts +1 -1
  88. package/dist/{types-CBRyqijY.d.ts → types-BCxK0wyS.d.ts} +1 -1
  89. package/dist/{types-CEchbvgz.d.ts → types-XIZqIdX1.d.ts} +1 -1
  90. package/dist/web-react/index.d.ts +10 -10
  91. package/dist/web-react/index.js +5 -5
  92. package/dist/work-product/index.d.ts +4 -4
  93. package/dist/work-product/index.js +735 -15
  94. package/dist/work-product/index.js.map +1 -1
  95. package/dist/work-product-react/index.d.ts +1 -1
  96. package/dist/work-product-react/index.js.map +1 -1
  97. package/package.json +4 -19
  98. package/dist/DesignCanvas-UNL34LS2.js +0 -12
  99. package/dist/chunk-22GLESKE.js.map +0 -1
  100. package/dist/chunk-3JUTOVUH.js.map +0 -1
  101. package/dist/chunk-5EQCITY3.js +0 -20
  102. package/dist/chunk-5EQCITY3.js.map +0 -1
  103. package/dist/chunk-5SD6HT2V.js +0 -236
  104. package/dist/chunk-5SD6HT2V.js.map +0 -1
  105. package/dist/chunk-5TESA4SN.js +0 -74
  106. package/dist/chunk-5TESA4SN.js.map +0 -1
  107. package/dist/chunk-6GQ5DKFK.js +0 -920
  108. package/dist/chunk-6GQ5DKFK.js.map +0 -1
  109. package/dist/chunk-7ESQUSAC.js +0 -343
  110. package/dist/chunk-7ESQUSAC.js.map +0 -1
  111. package/dist/chunk-7LNGJDNA.js +0 -1
  112. package/dist/chunk-7LNGJDNA.js.map +0 -1
  113. package/dist/chunk-AP2UXKUK.js +0 -69
  114. package/dist/chunk-AP2UXKUK.js.map +0 -1
  115. package/dist/chunk-FA4XR66Y.js +0 -32
  116. package/dist/chunk-FA4XR66Y.js.map +0 -1
  117. package/dist/chunk-FKCB5FTD.js +0 -126
  118. package/dist/chunk-FKCB5FTD.js.map +0 -1
  119. package/dist/chunk-GPBRL2XR.js +0 -102
  120. package/dist/chunk-GPBRL2XR.js.map +0 -1
  121. package/dist/chunk-HRH7ASAG.js +0 -759
  122. package/dist/chunk-HRH7ASAG.js.map +0 -1
  123. package/dist/chunk-HYTIHYNV.js +0 -297
  124. package/dist/chunk-HYTIHYNV.js.map +0 -1
  125. package/dist/chunk-LGBO24FL.js +0 -190
  126. package/dist/chunk-LGBO24FL.js.map +0 -1
  127. package/dist/chunk-NLSSFLLS.js +0 -1168
  128. package/dist/chunk-NLSSFLLS.js.map +0 -1
  129. package/dist/chunk-OSMNYPOG.js +0 -129
  130. package/dist/chunk-OSMNYPOG.js.map +0 -1
  131. package/dist/chunk-QYOD3K56.js +0 -124
  132. package/dist/chunk-QYOD3K56.js.map +0 -1
  133. package/dist/chunk-RXOTWZ4G.js.map +0 -1
  134. package/dist/chunk-UAKFCMWK.js +0 -1
  135. package/dist/chunk-UAKFCMWK.js.map +0 -1
  136. package/dist/chunk-UKTYKG57.js +0 -48
  137. package/dist/chunk-UKTYKG57.js.map +0 -1
  138. package/dist/chunk-UOAYS72M.js +0 -80
  139. package/dist/chunk-UOAYS72M.js.map +0 -1
  140. package/dist/chunk-WL7XHLDK.js.map +0 -1
  141. package/dist/composer/index.d.ts +0 -2
  142. package/dist/composer/index.js +0 -22
  143. package/dist/composer/index.js.map +0 -1
  144. package/dist/core-7qIM7svy.d.ts +0 -21
  145. package/dist/durable-chat/index.d.ts +0 -464
  146. package/dist/durable-chat/index.js +0 -59
  147. package/dist/durable-chat/index.js.map +0 -1
  148. package/dist/index.d.ts +0 -51
  149. package/dist/index.js +0 -827
  150. package/dist/index.js.map +0 -1
  151. /package/dist/{DesignCanvas-UNL34LS2.js.map → DesignCanvas-Z362I3R3.js.map} +0 -0
  152. /package/dist/{DesignCanvasEditor-FJIVYOA2.js.map → DesignCanvasEditor-ZFE2W4OJ.js.map} +0 -0
  153. /package/dist/{chunk-ROLFDOMJ.js.map → chunk-4TI7QWLW.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- import { M as FileMention } from './parts-2ymE5cs-.js';
1
+ import { M as FileMention } from './parts-Co_lFgLI.js';
2
2
 
3
3
  /**
4
4
  * `createSandboxFileIndexRoute` — server side of `@`-file-mentions
@@ -1,4 +1,4 @@
1
- import { c as AppToolContext } from './types-CBRyqijY.js';
1
+ import { a as AppToolContext } from './types-BCxK0wyS.js';
2
2
 
3
3
  /**
4
4
  * Header names carrying the server-set per-turn context + the capability token.
@@ -39,4 +39,4 @@ declare function authenticateToolRequest(request: Request, opts: AuthenticateOpt
39
39
  * aliases (`args` / `arguments`) or a bare body. Returns null on non-JSON. */
40
40
  declare function readToolArgs<T>(request: Request): Promise<T | null>;
41
41
 
42
- export { type AuthenticateOptions as A, DEFAULT_HEADER_NAMES as D, type ToolAuthResult as T, type ToolHeaderNames as a, authenticateToolRequest as b, readToolArgs as r };
42
+ export { type AuthenticateOptions as A, DEFAULT_HEADER_NAMES as D, type ToolHeaderNames as T, type ToolAuthResult as a, authenticateToolRequest as b, readToolArgs as r };
@@ -1,23 +1,23 @@
1
- import { g as ChatMessagePart, N as ChatTurnRequestPayload, O as ChatTurnPartInput, P as ChatTurnFilePartInput, a as ChatAttachmentPart, C as ChatAttachmentKind, f as ChatMentionPart } from '../parts-2ymE5cs-.js';
2
- export { Q as ChatAttachmentInput, e as ChatMentionKind, R as ChatTurnInputError, T as ChatTurnTextPartInput, U as DISPATCH_MAX_MEDIA_PARTS, V as DISPATCH_MAX_PARTS, W as DISPATCH_REQUEST_MAX_BYTES, X as DISPATCH_STRUCTURAL_RESERVE_BYTES, M as FileMention, Y as FileMentionsToPartsOptions, Z as INLINE_PARTS_MAX_BYTES, _ as MENTION_MAX_COUNT, $ as ProducerErrorEvent, a0 as ProducerNoticeEvent, a1 as ProducerPassthroughEvent, a2 as ProducerPassthroughEventType, a3 as ProducerReasoningEvent, a4 as ProducerTextEvent, a5 as ProducerToolCallEvent, a6 as ProducerToolResultEvent, a7 as ProducerUsageEvent, a8 as ProducerWireEvent, a9 as SandboxMentionPathCheck, aa as assertPromptPartsWithinCap, ab as base64WireLen, ac as buildMentionPromptBlock, ad as chatTurnRequestInit, ae as fileMentionsToParts, af as formatBytes, ag as mediaTypeForMentionPath, ah as mentionKindForPath, ai as parseChatTurnParts, aj as parseFileMentions, ak as promptPartsByteSize, al as validateSandboxMentionPath } from '../parts-2ymE5cs-.js';
3
- export { A as ALLOWED_ATTACHMENT_SNIFFED_MIMES, a as ATTACHMENT_ACCEPT, b as ATTACHMENT_MAX_COUNT, c as AttachmentTypeCheckResult, C as CreateSandboxFileIndexRouteOptions, F as FileIndexAuthorization, d as FileIndexCache, e as FileIndexReadyResponse, f as FileIndexResponse, g as FileIndexWarmingResponse, M as MAX_ATTACHMENT_TOTAL_BYTES, h as MAX_BINARY_ATTACHMENT_BYTES, i as MAX_TEXT_ATTACHMENT_BYTES, S as SandboxFileTreeSource, j as SandboxTreeFile, k as SandboxTreeResult, l as SniffResult, m as attachmentSizeErrorMessage, n as attachmentTotalSizeErrorMessage, o as checkAttachmentType, p as createSandboxFileIndexRoute, s as sanitizeAttachmentFileName, q as sniffBinary } from '../attachment-validation-Dv1A_Puy.js';
1
+ import { C as ChatMessagePart, N as ChatTurnRequestPayload, O as ChatTurnPartInput, P as ChatTurnFilePartInput, b as ChatAttachmentPart, a as ChatAttachmentKind, g as ChatMentionPart } from '../parts-Co_lFgLI.js';
2
+ export { Q as ChatAttachmentInput, f as ChatMentionKind, R as ChatTurnInputError, T as ChatTurnTextPartInput, U as DISPATCH_MAX_MEDIA_PARTS, V as DISPATCH_MAX_PARTS, W as DISPATCH_REQUEST_MAX_BYTES, X as DISPATCH_STRUCTURAL_RESERVE_BYTES, M as FileMention, Y as FileMentionsToPartsOptions, Z as INLINE_PARTS_MAX_BYTES, _ as MENTION_MAX_COUNT, $ as ProducerErrorEvent, a0 as ProducerNoticeEvent, a1 as ProducerPassthroughEvent, a2 as ProducerPassthroughEventType, a3 as ProducerReasoningEvent, a4 as ProducerTextEvent, a5 as ProducerToolCallEvent, a6 as ProducerToolResultEvent, a7 as ProducerUsageEvent, a8 as ProducerWireEvent, a9 as SandboxMentionPathCheck, aa as assertPromptPartsWithinCap, ab as base64WireLen, ac as buildMentionPromptBlock, ad as chatTurnRequestInit, ae as fileMentionsToParts, af as formatBytes, ag as mediaTypeForMentionPath, ah as mentionKindForPath, ai as parseChatTurnParts, aj as parseFileMentions, ak as promptPartsByteSize, al as validateSandboxMentionPath } from '../parts-Co_lFgLI.js';
3
+ export { A as ALLOWED_ATTACHMENT_SNIFFED_MIMES, a as ATTACHMENT_ACCEPT, b as ATTACHMENT_MAX_COUNT, c as AttachmentTypeCheckResult, C as CreateSandboxFileIndexRouteOptions, F as FileIndexAuthorization, d as FileIndexCache, e as FileIndexReadyResponse, f as FileIndexResponse, g as FileIndexWarmingResponse, M as MAX_ATTACHMENT_TOTAL_BYTES, h as MAX_BINARY_ATTACHMENT_BYTES, i as MAX_TEXT_ATTACHMENT_BYTES, S as SandboxFileTreeSource, j as SandboxTreeFile, k as SandboxTreeResult, l as SniffResult, m as attachmentSizeErrorMessage, n as attachmentTotalSizeErrorMessage, o as checkAttachmentType, p as createSandboxFileIndexRoute, s as sanitizeAttachmentFileName, q as sniffBinary } from '../attachment-validation-DRuLEjAE.js';
4
4
  import { ChatTurnIdentity, ChatTurnProducer } from '@tangle-network/agent-runtime';
5
5
  import { InteractionAnswerRoute, InteractionAnswerRouteOptions } from '../interactions/index.js';
6
6
  import { PersistedChatMessageForTurn } from '../stream/index.js';
7
- import { d as TurnEventStore } from '../turn-buffer-BaSgxVmK.js';
7
+ import { T as TurnEventStore } from '../turn-buffer-BcPfhr1_.js';
8
8
  import { M as ModelFailoverAttempt } from '../failover-H0x12kY3.js';
9
9
  export { D as DEFAULT_STALE_TURN_LOCK_GRACE_MS, a as DEFAULT_TERMINAL_TURN_LOCK_GRACE_MS, R as ReconcileStaleTurnLockOptions, b as ReconcileStaleTurnLockResult, S as StaleTurnLockSandboxProbeResult, c as StaleTurnLockSessionProbeResult, r as reconcileStaleTurnLock } from '../stale-turn-lock-DucQzvXu.js';
10
- import { J as JsonRecord } from '../stream-normalizer-QYUl4vnl.js';
10
+ import { J as JsonRecord } from '../stream-normalizer-DnuqkZvw.js';
11
11
  import { SandboxExecChannel, PromptInputPart } from '../sandbox/index.js';
12
12
  import '@tangle-network/agent-interface';
13
- import '../contract-B3h7peV3.js';
14
- import '../types-CEchbvgz.js';
13
+ import '../contract-CEewO6DI.js';
14
+ import '../types-XIZqIdX1.js';
15
15
  import '../plans/index.js';
16
16
  import '@tangle-network/sandbox';
17
- import '../auth-_FU8w01b.js';
18
- import '../types-CBRyqijY.js';
17
+ import '../auth-anc7mv2W.js';
18
+ import '../types-BCxK0wyS.js';
19
19
  import '../harness/index.js';
20
- import '../model-DmdkIteM.js';
20
+ import '../model-CdCDfBA9.js';
21
21
  import '../fingerprint-DbmOgy0n.js';
22
22
 
23
23
  /**
@@ -722,9 +722,14 @@ declare function createChatTurnRoutes<TContext = void>(options: CreateChatTurnRo
722
722
  * COMMITS rather than failing over — it surfaces to the user exactly as it
723
723
  * does today. Those fail identically on every model; walking the chain would
724
724
  * only multiply latency and spend to reach the same error.
725
- * - A clean stream that simply produced nothing is NOT retried. An empty answer
725
+ * - A clean stream that produced nothing NEVER walks the chain. An empty answer
726
726
  * is not evidence of a dead upstream, and a silent re-roll on another model is
727
- * precisely the unattributable downgrade this work exists to prevent.
727
+ * precisely the unattributable downgrade this work exists to prevent. Opt-in
728
+ * `emptyTurnRetries` re-runs the SAME model instead, which leaves attribution
729
+ * untouched — measured on production 2026-07-27, an empty turn is a transient
730
+ * platform flake that a same-model re-run recovers (8 hard cases: 7/8
731
+ * delivered on the first pass, 8/8 with one re-run, at a cost of 1 extra turn
732
+ * in 9). Default `0`, so the behavior is unchanged unless a product asks.
728
733
  * - A chain of length 1 costs nothing: one attempt, no extra call, no added
729
734
  * latency, byte-identical to no failover at all.
730
735
  */
@@ -774,8 +779,33 @@ interface ModelFailoverStreamOptions {
774
779
  /** Override the commit-point rule. Default {@link isCommittingSandboxEvent}. */
775
780
  isCommitting?: (event: unknown) => boolean;
776
781
  onFallback?: (info: ModelFallbackInfo) => void;
782
+ /**
783
+ * How many times to RE-RUN THE SAME MODEL when a turn completes having
784
+ * produced no assistant text at all. Default `0` — byte-identical to no
785
+ * retry.
786
+ *
787
+ * This is deliberately not a chain walk. Falling over to a different model
788
+ * on an empty answer is the unattributable downgrade this module refuses to
789
+ * do; re-running the SAME model changes nothing about attribution, because
790
+ * the model that serves is the model that was asked for.
791
+ *
792
+ * Bounded by the same commit rule as failover: only a turn whose ONLY
793
+ * committing event is a terminal receipt with no text is retried, so nothing
794
+ * that reached the user can ever be produced twice.
795
+ */
796
+ emptyTurnRetries?: number;
797
+ /** Fired when an empty turn is discarded and the same model re-run. */
798
+ onEmptyTurnRetry?: (info: EmptyTurnRetryInfo) => void;
777
799
  log?: (message: string, meta?: Record<string, unknown>) => void;
778
800
  }
801
+ /** One same-model re-run of a turn that completed with no assistant text. */
802
+ interface EmptyTurnRetryInfo {
803
+ model: string;
804
+ /** 1 for the first re-run. */
805
+ retry: number;
806
+ /** How many re-runs remain after this one. */
807
+ remaining: number;
808
+ }
779
809
  /** The failover-wrapped stream plus the attribution every consumer needs. */
780
810
  interface ModelFailoverStreamHandle {
781
811
  events: AsyncGenerator<unknown, void, unknown>;
@@ -786,6 +816,12 @@ interface ModelFailoverStreamHandle {
786
816
  /** True when the preferred model did not serve — the attributability signal. */
787
817
  usedFallback(): boolean;
788
818
  }
819
+ /**
820
+ * Hard ceiling on same-model re-runs. A turn that comes back blank three times
821
+ * running is not a flake this can retry away, and each pass costs a full
822
+ * sandbox turn — so the budget is capped rather than trusted.
823
+ */
824
+ declare const MAX_EMPTY_TURN_RETRIES = 3;
789
825
  /**
790
826
  * Wrap `open` in reactive model failover, streaming from the first model in
791
827
  * `models` that reaches its commit point.
@@ -881,6 +917,18 @@ interface SandboxChatProducerOptions {
881
917
  /** Fired when a model is abandoned mid-chain (telemetry/alerting). The user
882
918
  * already sees a transcript notice; this is for the operator. */
883
919
  onModelFallback?: (info: ModelFallbackInfo) => void;
920
+ /** Re-run the SAME model this many times when a turn completes with no
921
+ * assistant text at all. Default `0` (unchanged behavior). Requires
922
+ * {@link openEvents} — there is nothing to re-open on a fixed stream.
923
+ *
924
+ * Distinct from {@link fallbackModels} on purpose: this never changes which
925
+ * model answers, so it carries none of the attribution risk a downgrade
926
+ * does. Measured on production 2026-07-27 through gtm-agent's profile, a
927
+ * completed-but-blank turn is a transient platform flake — 8 hard cases went
928
+ * 7/8 delivered to 8/8 with one re-run, costing 1 extra turn in 9. */
929
+ emptyTurnRetries?: number;
930
+ /** Fired when a blank turn is discarded and the same model re-run. */
931
+ onEmptyTurnRetry?: (info: EmptyTurnRetryInfo) => void;
884
932
  /** Which ask kinds the product renders a card for. Anything else is
885
933
  * auto-declined (see `declineInteraction`) so the run never hangs in the
886
934
  * broker waiting on a card no client will show. Default: question/plan.
@@ -1109,7 +1157,10 @@ interface ChatRouteDurableProjection {
1109
1157
  /** Log chat route projection messages with optional metadata for durable processing */
1110
1158
  type ChatRouteDurableProjectionLogger = (message: string, meta?: Record<string, unknown>) => void;
1111
1159
  /** Adds durable lifecycle projection to any producer lane without moving its
1112
- * transport into agent-app. The projection is observed inline and its
1160
+ * transport into agent-app. Purely STRUCTURAL: agent-app ships no implementer
1161
+ * of {@link ChatRouteDurableProjection} and deliberately does not — the one it
1162
+ * used to ship (`/durable-chat`) was removed in 0.44.0 with zero fleet imports.
1163
+ * Pass any `{ observe, materialize }` object backed by your own store. The projection is observed inline and its
1113
1164
  * materialized parts replace same-key pending snapshots after the stream
1114
1165
  * drains. Projection persistence is best-effort for the live lane: a store
1115
1166
  * outage must not terminate an otherwise healthy sandbox stream. Failures are
@@ -1610,4 +1661,4 @@ interface PromoteAgentFilePartOptions {
1610
1661
  /** Promote a part of an agent file with optional byte limits and MIME type detection */
1611
1662
  declare function promoteAgentFilePart(options: PromoteAgentFilePartOptions): Promise<PromoteFilePartResult>;
1612
1663
 
1613
- export { type AssistantDraftSnapshot, type AssistantDraftStore, type AssistantDraftWriter, type AssistantDraftWriterOptions, type AssistantRowValues, type AttachmentPathArgs, type AttachmentPathCheck, type AttachmentReadResult, type AttachmentUploadAuthorization, type AttachmentWriteResult, type BuildDispatchPartsInput, ChatAttachmentKind, type ChatRouteDurableProjection, type ChatRouteDurableProjectionLogger, type ChatRouteEvent, type ChatTurnAuthorization, type ChatTurnAuthorizeArgs, type ChatTurnCompleteInput, ChatTurnFilePartInput, type ChatTurnGateResult, type ChatTurnHeartbeat, type ChatTurnInputPatch, type ChatTurnLifecycle, type ChatTurnLifecycleComplete, type ChatTurnLifecycleError, type ChatTurnLifecycleStart, type ChatTurnLock, type ChatTurnLockResult, type ChatTurnMessageStore, type ChatTurnModelFailover, ChatTurnPartInput, type ChatTurnProduceArgs, ChatTurnRequestPayload, type ChatTurnRouteProducer, type ChatTurnRoutes, type ChatTurnUsage, type CreateAttachmentUploadRouteOptions, type CreateChatTurnRoutesOptions, type CreateUploadRouteOptions, type DetachedTurnFinal, type DetachedTurnOptions, type DetachedTurnParts, type DetachedTurnResult, type DispatchPartsOutcome, type DraftPersistenceTuning, type DraftStoredMessage, type FilePartPromotionOutcome, type ModelFailoverStreamHandle, type ModelFailoverStreamOptions, type ModelFallbackInfo, type OpenModelStream, PROMOTE_MAX_FILE_BYTES, type PromoteAgentFilePartOptions, type PromoteFilePartResult, PromptInputPart, type RawAgentFilePart, type ReadAttachmentFn, type ReadSandboxMentionFn, type ResolveChatAttachmentsOptions, type ResolveChatAttachmentsResult, type SandboxChatProducerOptions, type SandboxUploadSink, UPLOAD_INLINE_MAX_BYTES, UPLOAD_MAX_FILE_BYTES, type UploadAuthorization, type UploadedChatFile, type WriteAttachmentFn, assistantRowIdForTurn, buildDispatchParts, bytesToBase64, classifyTerminalFailure, createAssistantDraftWriter, createAttachmentUploadRoute, createChatTurnRoutes, createSandboxChatProducer, createUploadRoute, defaultValidateAttachmentPath, isCommittingSandboxEvent, isDraftContentEvent, promoteAgentFilePart, resolveChatAttachments, rowIdOf, runDetachedTurn, sanitizeUploadFilename, sniffMimeFromName, storeSupportsDraftPersistence, streamWithModelFailover, withDurableChatProjection };
1664
+ export { type AssistantDraftSnapshot, type AssistantDraftStore, type AssistantDraftWriter, type AssistantDraftWriterOptions, type AssistantRowValues, type AttachmentPathArgs, type AttachmentPathCheck, type AttachmentReadResult, type AttachmentUploadAuthorization, type AttachmentWriteResult, type BuildDispatchPartsInput, ChatAttachmentKind, type ChatRouteDurableProjection, type ChatRouteDurableProjectionLogger, type ChatRouteEvent, type ChatTurnAuthorization, type ChatTurnAuthorizeArgs, type ChatTurnCompleteInput, ChatTurnFilePartInput, type ChatTurnGateResult, type ChatTurnHeartbeat, type ChatTurnInputPatch, type ChatTurnLifecycle, type ChatTurnLifecycleComplete, type ChatTurnLifecycleError, type ChatTurnLifecycleStart, type ChatTurnLock, type ChatTurnLockResult, type ChatTurnMessageStore, type ChatTurnModelFailover, ChatTurnPartInput, type ChatTurnProduceArgs, ChatTurnRequestPayload, type ChatTurnRouteProducer, type ChatTurnRoutes, type ChatTurnUsage, type CreateAttachmentUploadRouteOptions, type CreateChatTurnRoutesOptions, type CreateUploadRouteOptions, type DetachedTurnFinal, type DetachedTurnOptions, type DetachedTurnParts, type DetachedTurnResult, type DispatchPartsOutcome, type DraftPersistenceTuning, type DraftStoredMessage, type EmptyTurnRetryInfo, type FilePartPromotionOutcome, MAX_EMPTY_TURN_RETRIES, type ModelFailoverStreamHandle, type ModelFailoverStreamOptions, type ModelFallbackInfo, type OpenModelStream, PROMOTE_MAX_FILE_BYTES, type PromoteAgentFilePartOptions, type PromoteFilePartResult, PromptInputPart, type RawAgentFilePart, type ReadAttachmentFn, type ReadSandboxMentionFn, type ResolveChatAttachmentsOptions, type ResolveChatAttachmentsResult, type SandboxChatProducerOptions, type SandboxUploadSink, UPLOAD_INLINE_MAX_BYTES, UPLOAD_MAX_FILE_BYTES, type UploadAuthorization, type UploadedChatFile, type WriteAttachmentFn, assistantRowIdForTurn, buildDispatchParts, bytesToBase64, classifyTerminalFailure, createAssistantDraftWriter, createAttachmentUploadRoute, createChatTurnRoutes, createSandboxChatProducer, createUploadRoute, defaultValidateAttachmentPath, isCommittingSandboxEvent, isDraftContentEvent, promoteAgentFilePart, resolveChatAttachments, rowIdOf, runDetachedTurn, sanitizeUploadFilename, sniffMimeFromName, storeSupportsDraftPersistence, streamWithModelFailover, withDurableChatProjection };
@@ -12,19 +12,6 @@ import {
12
12
  sanitizeAttachmentFileName,
13
13
  sniffBinary
14
14
  } from "../chunk-V55WJSR4.js";
15
- import {
16
- DEFAULT_STALE_TURN_LOCK_GRACE_MS,
17
- DEFAULT_TERMINAL_TURN_LOCK_GRACE_MS,
18
- reconcileStaleTurnLock
19
- } from "../chunk-CCVWR33L.js";
20
- import {
21
- buildModelChain,
22
- isUpstreamUnavailable,
23
- runWithModelFailover
24
- } from "../chunk-KFTRTOT2.js";
25
- import {
26
- parseJsonObjectBody
27
- } from "../chunk-PTUMBMVH.js";
28
15
  import {
29
16
  coalesceDeltas,
30
17
  createBufferedTurnTap,
@@ -33,9 +20,17 @@ import {
33
20
  resolveChatTurn,
34
21
  stampReplaySeq
35
22
  } from "../chunk-2EJFIQUV.js";
23
+ import {
24
+ DEFAULT_STALE_TURN_LOCK_GRACE_MS,
25
+ DEFAULT_TERMINAL_TURN_LOCK_GRACE_MS,
26
+ reconcileStaleTurnLock
27
+ } from "../chunk-CCVWR33L.js";
36
28
  import {
37
29
  createInteractionAnswerRoute
38
- } from "../chunk-3JUTOVUH.js";
30
+ } from "../chunk-6KMAM7BL.js";
31
+ import {
32
+ parseJsonObjectBody
33
+ } from "../chunk-PTUMBMVH.js";
39
34
  import {
40
35
  ChatTurnInputError,
41
36
  DISPATCH_MAX_MEDIA_PARTS,
@@ -88,6 +83,11 @@ import {
88
83
  parsePlanSubmittedEvent,
89
84
  planToPersistedPart
90
85
  } from "../chunk-YJMCRXQQ.js";
86
+ import {
87
+ buildModelChain,
88
+ isUpstreamUnavailable,
89
+ runWithModelFailover
90
+ } from "../chunk-KFTRTOT2.js";
91
91
  import {
92
92
  flattenHistory,
93
93
  readSandboxBinaryBytes,
@@ -95,12 +95,11 @@ import {
95
95
  } from "../chunk-JHYJZSFX.js";
96
96
  import "../chunk-IVUN7FL7.js";
97
97
  import "../chunk-CQZSAR77.js";
98
- import "../chunk-WL7XHLDK.js";
98
+ import "../chunk-ICOHEZK6.js";
99
99
  import "../chunk-3EJ6SFJI.js";
100
+ import "../chunk-YEFFHORB.js";
100
101
  import "../chunk-S5SRJJQG.js";
101
102
  import "../chunk-JML7WKWU.js";
102
- import "../chunk-UOAYS72M.js";
103
- import "../chunk-YEFFHORB.js";
104
103
 
105
104
  // src/chat-routes/turn-routes.ts
106
105
  import { deriveExecutionId, handleChatTurn } from "@tangle-network/agent-runtime";
@@ -843,6 +842,22 @@ function classifyTerminalFailure(event) {
843
842
  const code = asString(data?.errorCode) ?? asString(data?.code);
844
843
  return { outage, reason, ...code ? { code } : {} };
845
844
  }
845
+ function isEmptyTerminalReceipt(event) {
846
+ const record = asRecord(event);
847
+ if (!record) return false;
848
+ const type = asString(record.type) ?? "";
849
+ if (type !== "result" && type !== "done") return false;
850
+ const data = asRecord(record.data);
851
+ const text = asString(data?.finalText) ?? asString(data?.text) ?? "";
852
+ return text.trim().length === 0;
853
+ }
854
+ var MAX_EMPTY_TURN_RETRIES = 3;
855
+ function resolveEmptyTurnRetries(value) {
856
+ if (typeof value !== "number" || !Number.isFinite(value)) return 0;
857
+ const truncated = Math.trunc(value);
858
+ if (truncated <= 0) return 0;
859
+ return Math.min(truncated, MAX_EMPTY_TURN_RETRIES);
860
+ }
846
861
  async function closeIterator(iterator, log) {
847
862
  try {
848
863
  await iterator.return?.();
@@ -854,11 +869,12 @@ async function closeIterator(iterator, log) {
854
869
  }
855
870
  function streamWithModelFailover(options) {
856
871
  const committing = options.isCommitting ?? isCommittingSandboxEvent;
872
+ const emptyTurnRetries = resolveEmptyTurnRetries(options.emptyTurnRetries);
857
873
  let serving;
858
874
  let trail = [];
859
875
  let fellBack = false;
860
876
  let attemptIndex = 0;
861
- const probe = async (model) => {
877
+ const drainOnce = async (model) => {
862
878
  attemptIndex += 1;
863
879
  const source = await options.open({ model, attempt: attemptIndex });
864
880
  const iterator = source[Symbol.asyncIterator]();
@@ -866,21 +882,39 @@ function streamWithModelFailover(options) {
866
882
  for (; ; ) {
867
883
  const next = await iterator.next();
868
884
  if (next.done) {
869
- return { committed: true, buffered, iterator: null };
885
+ return { outcome: { committed: true, buffered, iterator: null }, empty: true };
870
886
  }
871
887
  const event = next.value;
872
888
  const failure = classifyTerminalFailure(event);
873
889
  if (failure?.outage) {
874
890
  await closeIterator(iterator, options.log);
875
891
  return {
876
- committed: false,
877
- error: failure.reason,
878
- ...failure.code ? { errorCode: failure.code } : {}
892
+ outcome: {
893
+ committed: false,
894
+ error: failure.reason,
895
+ ...failure.code ? { errorCode: failure.code } : {}
896
+ },
897
+ empty: false
879
898
  };
880
899
  }
881
900
  buffered.push(event);
882
- if (failure) return { committed: true, buffered, iterator };
883
- if (committing(event)) return { committed: true, buffered, iterator };
901
+ if (failure) return { outcome: { committed: true, buffered, iterator }, empty: false };
902
+ if (committing(event)) {
903
+ return { outcome: { committed: true, buffered, iterator }, empty: isEmptyTerminalReceipt(event) };
904
+ }
905
+ }
906
+ };
907
+ const probe = async (model) => {
908
+ for (let retry = 0; ; retry += 1) {
909
+ const pass = await drainOnce(model);
910
+ if (!pass.empty || retry >= emptyTurnRetries) return pass.outcome;
911
+ const iterator = pass.outcome.committed ? pass.outcome.iterator : null;
912
+ if (iterator) await closeIterator(iterator, options.log);
913
+ const info = { model, retry: retry + 1, remaining: emptyTurnRetries - retry - 1 };
914
+ options.log?.("[chat-routes] turn completed with no assistant text; re-running the same model", {
915
+ ...info
916
+ });
917
+ options.onEmptyTurnRetry?.(info);
884
918
  }
885
919
  };
886
920
  const events = (async function* () {
@@ -1057,6 +1091,8 @@ function createSandboxChatProducer(options) {
1057
1091
  models: chain,
1058
1092
  open: options.openEvents,
1059
1093
  log,
1094
+ ...options.emptyTurnRetries !== void 0 ? { emptyTurnRetries: options.emptyTurnRetries } : {},
1095
+ ...options.onEmptyTurnRetry ? { onEmptyTurnRetry: options.onEmptyTurnRetry } : {},
1060
1096
  onFallback: (info) => {
1061
1097
  modelNoticeCount += 1;
1062
1098
  pendingModelNotices.push({
@@ -2269,6 +2305,7 @@ export {
2269
2305
  INLINE_PARTS_MAX_BYTES,
2270
2306
  MAX_ATTACHMENT_TOTAL_BYTES,
2271
2307
  MAX_BINARY_ATTACHMENT_BYTES,
2308
+ MAX_EMPTY_TURN_RETRIES,
2272
2309
  MAX_TEXT_ATTACHMENT_BYTES,
2273
2310
  MENTION_MAX_COUNT,
2274
2311
  PROMOTE_MAX_FILE_BYTES,