@tangle-network/agent-app 0.43.70 → 0.43.72

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.
@@ -18,6 +18,7 @@ import '../auth-_FU8w01b.js';
18
18
  import '../types-CBRyqijY.js';
19
19
  import '../harness/index.js';
20
20
  import '../model-DmdkIteM.js';
21
+ import '../fingerprint-DbmOgy0n.js';
21
22
 
22
23
  /**
23
24
  * Incremental ("draft") persistence of the assistant row WHILE a turn streams.
@@ -185,6 +186,15 @@ declare function createAssistantDraftWriter(options: AssistantDraftWriterOptions
185
186
  * `updateMessage` a draft row could never be patched, so the caller keeps
186
187
  * today's exact single-write behavior. */
187
188
  declare function storeSupportsDraftPersistence(store: AssistantDraftStore): boolean;
189
+ /** The row id an `appendMessage` actually returned, or `null` when the store
190
+ * returned nothing usable. `ChatTurnMessageStore.appendMessage` is typed
191
+ * `Promise<unknown>` so a product adapter is free to resolve `void`; every
192
+ * caller that wants to NAME the row it just wrote has to read defensively.
193
+ *
194
+ * Deliberately no fallback to a caller-assigned id — see `writeOnce`, which
195
+ * adds its own. A caller that let the store mint the id has nothing to fall
196
+ * back TO, and guessing one would report a row that may not exist. */
197
+ declare function rowIdOf(inserted: unknown): string | null;
188
198
  /** The default deterministic assistant-row id for a turn. Readable on purpose
189
199
  * (an operator grepping a transcript row id finds the run), and stable across
190
200
  * re-entries because every input already is. */
@@ -359,6 +369,20 @@ interface ChatTurnProduceArgs<TContext> {
359
369
  /** The turn-buffer id announced to the client for replay. */
360
370
  turnStreamId: string;
361
371
  priorMessages: PersistedChatMessageForTurn[];
372
+ /** The durable `role:'user'` row this turn is anchored to — the row the
373
+ * factory just inserted, or the one retry-dedup REUSED. Products anchor
374
+ * optimistic-bubble swaps, retry targeting, and stop-polling to it, and it
375
+ * is the only way to name a REUSED row (which `priorMessages` excludes).
376
+ *
377
+ * Three states, all meaningful:
378
+ * - `undefined` — not resolved yet. `turnLock.acquire` is the one seam that
379
+ * sees this: it runs before any side effect by contract, so the row does
380
+ * not exist when it reads the args.
381
+ * - `null` — resolved, no row: `authorize` returned `insertUserMessage:
382
+ * false` on a turn with nothing to reuse, or the store's `appendMessage`
383
+ * resolved without a usable id.
384
+ * - a string — the row id, for `contextGate`, `beforeTurn`, and `produce`. */
385
+ userMessageId?: string | null;
362
386
  }
363
387
  /** One event as it crosses the route: the producer's own vocabulary, or an
364
388
  * injected keepalive. Same shape the engine forwards verbatim. */
@@ -433,6 +457,11 @@ interface ChatTurnLifecycleComplete<TContext> extends ChatTurnLifecycleBase<TCon
433
457
  /** Attribution for a downgrade: which models were tried and why each failed.
434
458
  * `undefined` when the producer reports no failover support. */
435
459
  modelFailover?: ChatTurnModelFailover;
460
+ /** The durable `role:'assistant'` row this turn wrote, or `null` when it
461
+ * wrote none (an empty turn leaves no row — a draft started mid-stream is
462
+ * retracted). The detached lane surfaces the same id as
463
+ * `DetachedTurnResult.messageId`; one contract, two lanes. */
464
+ assistantMessageId: string | null;
436
465
  }
437
466
  /** Represent an error occurring during a chat turn lifecycle with context and duration information */
438
467
  interface ChatTurnLifecycleError<TContext> extends ChatTurnLifecycleBase<TContext> {
@@ -450,6 +479,31 @@ interface ChatTurnLifecycle<TContext> {
450
479
  onTurnComplete?(info: ChatTurnLifecycleComplete<TContext>): void | Promise<void>;
451
480
  onTurnError?(info: ChatTurnLifecycleError<TContext>): void | Promise<void>;
452
481
  }
482
+ /** What a settled turn reports to `onTurnComplete` — the product's
483
+ * post-processing seam (billing, titles, audit). */
484
+ interface ChatTurnCompleteInput<TContext> {
485
+ identity: ChatTurnIdentity;
486
+ finalText: string;
487
+ context: TContext;
488
+ failed: boolean;
489
+ failureReason?: string;
490
+ /** The model that SERVED this turn. With failover wired it may differ from
491
+ * the requested one, so a product that bills or scores per model MUST read
492
+ * it here rather than assuming the model it asked for. */
493
+ model?: string;
494
+ /** Present when the producer supports failover: the full attempt trail, and
495
+ * `usedFallback` — the flag that makes a silent downgrade impossible. */
496
+ modelFailover?: ChatTurnModelFailover;
497
+ /** The durable `role:'assistant'` row this turn wrote, or `null` when it
498
+ * wrote none (an empty turn leaves no row).
499
+ *
500
+ * Populated even when `failed` is true — a terminal error event still
501
+ * persists whatever partial answer arrived, and that pairing is exactly
502
+ * what lets a product render an error row against a REAL message instead of
503
+ * hunting for the newest row in the thread. The detached lane surfaces the
504
+ * same id as `DetachedTurnResult.messageId`. */
505
+ assistantMessageId: string | null;
506
+ }
453
507
  /** Define options to configure chat turn routes including authorization, storage, and event buffering */
454
508
  interface CreateChatTurnRoutesOptions<TContext = void> {
455
509
  /** Names the product in `deriveExecutionId` so retries land on the same
@@ -533,20 +587,7 @@ interface CreateChatTurnRoutesOptions<TContext = void> {
533
587
  * than billing an empty turn and marking it done. A turn that THROWS never
534
588
  * reaches this hook (the engine skips it on a producer throw). Errors are
535
589
  * swallowed by the engine — they never fail a streamed turn. */
536
- onTurnComplete?(input: {
537
- identity: ChatTurnIdentity;
538
- finalText: string;
539
- context: TContext;
540
- failed: boolean;
541
- failureReason?: string;
542
- /** The model that SERVED this turn. With failover wired it may differ from
543
- * the requested one, so a product that bills or scores per model MUST read
544
- * it here rather than assuming the model it asked for. */
545
- model?: string;
546
- /** Present when the producer supports failover: the full attempt trail, and
547
- * `usedFallback` — the flag that makes a silent downgrade impossible. */
548
- modelFailover?: ChatTurnModelFailover;
549
- }): Promise<void>;
590
+ onTurnComplete?(input: ChatTurnCompleteInput<TContext>): Promise<void>;
550
591
  /** Per-event side channel (product broadcast). The turn-buffer tap is
551
592
  * already wired; this runs in addition. */
552
593
  onEvent?(event: {
@@ -1516,4 +1557,4 @@ interface PromoteAgentFilePartOptions {
1516
1557
  /** Promote a part of an agent file with optional byte limits and MIME type detection */
1517
1558
  declare function promoteAgentFilePart(options: PromoteAgentFilePartOptions): Promise<PromoteFilePartResult>;
1518
1559
 
1519
- 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 ChatTurnAuthorization, type ChatTurnAuthorizeArgs, 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, runDetachedTurn, sanitizeUploadFilename, sniffMimeFromName, storeSupportsDraftPersistence, streamWithModelFailover, withDurableChatProjection };
1560
+ 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 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 };
@@ -31,7 +31,7 @@ import {
31
31
  normalizeClientTurnId,
32
32
  replayTurnEvents,
33
33
  resolveChatTurn
34
- } from "../chunk-YN7QR7MJ.js";
34
+ } from "../chunk-RK2MKLBT.js";
35
35
  import {
36
36
  createInteractionAnswerRoute
37
37
  } from "../chunk-3JUTOVUH.js";
@@ -91,7 +91,8 @@ import {
91
91
  flattenHistory,
92
92
  readSandboxBinaryBytes,
93
93
  statSandboxFileSize
94
- } from "../chunk-3ALFBTIW.js";
94
+ } from "../chunk-NWYIACBB.js";
95
+ import "../chunk-IVUN7FL7.js";
95
96
  import "../chunk-CQZSAR77.js";
96
97
  import "../chunk-WL7XHLDK.js";
97
98
  import "../chunk-3EJ6SFJI.js";
@@ -215,8 +216,7 @@ function createAssistantDraftWriter(options) {
215
216
  role: "assistant",
216
217
  ...values
217
218
  });
218
- const insertedId = inserted?.id;
219
- rowId = typeof insertedId === "string" && insertedId ? insertedId : options.messageId;
219
+ rowId = rowIdOf(inserted) ?? options.messageId;
220
220
  writes += 1;
221
221
  }
222
222
  function trigger() {
@@ -283,6 +283,10 @@ function createAssistantDraftWriter(options) {
283
283
  function storeSupportsDraftPersistence(store) {
284
284
  return typeof store.updateMessage === "function";
285
285
  }
286
+ function rowIdOf(inserted) {
287
+ const id = inserted?.id;
288
+ return typeof id === "string" && id ? id : null;
289
+ }
286
290
  function assistantRowIdForTurn(turnKey) {
287
291
  return `assistant:${turnKey}`;
288
292
  }
@@ -463,6 +467,8 @@ function createChatTurnRoutes(options) {
463
467
  }
464
468
  let producer;
465
469
  let draft;
470
+ let assistantMessageId;
471
+ const assistantRowId = () => assistantMessageId ?? draft?.rowId() ?? null;
466
472
  let runFailed = false;
467
473
  let lastFailureData;
468
474
  let turnStartedAtMs = 0;
@@ -494,6 +500,7 @@ function createChatTurnRoutes(options) {
494
500
  durationMs,
495
501
  finalText: producer?.finalText() ?? "",
496
502
  usage: producer?.usage?.() ?? {},
503
+ assistantMessageId: assistantRowId(),
497
504
  ...producer?.model ? { model: producer.model } : {},
498
505
  ...failoverInfo ? { modelFailover: failoverInfo } : {}
499
506
  });
@@ -507,14 +514,18 @@ function createChatTurnRoutes(options) {
507
514
  };
508
515
  try {
509
516
  const insertUserMessage = chatTurn.shouldInsertUserMessage && (auth.insertUserMessage ?? true);
517
+ let userMessageId = chatTurn.reusedUserMessageId ?? null;
510
518
  if (insertUserMessage) {
511
- await options.store.appendMessage({
512
- threadId: payload.threadId,
513
- role: "user",
514
- content,
515
- parts: userPartsWithFiles(chatTurn.userParts, fileParts, mentions)
516
- });
519
+ userMessageId = rowIdOf(
520
+ await options.store.appendMessage({
521
+ threadId: payload.threadId,
522
+ role: "user",
523
+ content,
524
+ parts: userPartsWithFiles(chatTurn.userParts, fileParts, mentions)
525
+ })
526
+ );
517
527
  }
528
+ produceArgs = { ...produceArgs, userMessageId };
518
529
  if (options.contextGate) {
519
530
  const gate = await options.contextGate(produceArgs);
520
531
  if (!gate.proceed) {
@@ -612,6 +623,7 @@ function createChatTurnRoutes(options) {
612
623
  const parts = projected ? toChatMessageParts(projected) : void 0;
613
624
  if (!finalText.trim() && (!parts || parts.length === 0)) {
614
625
  await draft?.discard();
626
+ assistantMessageId = draft?.rowId() ?? null;
615
627
  return;
616
628
  }
617
629
  const usage = producer?.usage?.() ?? {};
@@ -628,13 +640,16 @@ function createChatTurnRoutes(options) {
628
640
  };
629
641
  if (draft) {
630
642
  await draft.finalize(values);
643
+ assistantMessageId = draft.rowId() ?? null;
631
644
  return;
632
645
  }
633
- await options.store.appendMessage({
634
- threadId: payload.threadId,
635
- role: "assistant",
636
- ...values
637
- });
646
+ assistantMessageId = rowIdOf(
647
+ await options.store.appendMessage({
648
+ threadId: payload.threadId,
649
+ role: "assistant",
650
+ ...values
651
+ })
652
+ );
638
653
  },
639
654
  ...options.onTurnComplete ? {
640
655
  // Wired into the engine's completion hook, which fires only when
@@ -649,6 +664,7 @@ function createChatTurnRoutes(options) {
649
664
  finalText,
650
665
  context,
651
666
  failed: runFailed,
667
+ assistantMessageId: assistantRowId(),
652
668
  ...runFailed ? { failureReason: failureReasonOf(lastFailureData) } : {},
653
669
  ...producer?.model ? { model: producer.model } : {},
654
670
  ...failoverInfo ? { modelFailover: failoverInfo } : {}
@@ -2287,6 +2303,7 @@ export {
2287
2303
  promptPartsByteSize,
2288
2304
  reconcileStaleTurnLock,
2289
2305
  resolveChatAttachments,
2306
+ rowIdOf,
2290
2307
  runDetachedTurn,
2291
2308
  sanitizeAttachmentFileName,
2292
2309
  sanitizeUploadFilename,