@tangle-network/agent-app 0.50.4 → 0.50.5

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.
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createChatTurnRoutes,
3
3
  streamChatRouteAsSandboxEvents
4
- } from "../chunk-KJEW23GR.js";
4
+ } from "../chunk-3MIQCPUX.js";
5
5
  import "../chunk-TZEEGDHS.js";
6
6
  import "../chunk-3NCPXNBZ.js";
7
7
  import "../chunk-ZSSCVT6H.js";
@@ -9,7 +9,7 @@ import "../chunk-RACQDXJ7.js";
9
9
  import "../chunk-X47R2IVO.js";
10
10
  import "../chunk-ZVEEWGDK.js";
11
11
  import "../chunk-TXD5HXLE.js";
12
- import "../chunk-3NM4GCAY.js";
12
+ import "../chunk-DPO7FGCN.js";
13
13
  import "../chunk-MX55JP7D.js";
14
14
  import "../chunk-YJMCRXQQ.js";
15
15
  import "../chunk-M3K2HVQD.js";
@@ -99,7 +99,7 @@ import {
99
99
  workspaceSandboxRecoveryMessage,
100
100
  workspaceSandboxRecoveryRecommendedActions,
101
101
  writeProfileFilesToBox
102
- } from "../chunk-TFW7OB4L.js";
102
+ } from "../chunk-P5ZJQKOI.js";
103
103
  import "../chunk-MCYJON3F.js";
104
104
  import "../chunk-LWSJK546.js";
105
105
  import "../chunk-FZOGDD2E.js";
@@ -205,6 +205,8 @@ export interface WorkspaceSandboxRecoveryManager<Snapshot extends WorkspaceSandb
205
205
  complete: (args: {
206
206
  workspaceId: string;
207
207
  replacementSandboxId: string;
208
+ /** The key used by this provisioning attempt, not a freshly read successor. */
209
+ replacementBoxKey?: string;
208
210
  }) => Promise<WorkspaceSandboxRecoveryState<Snapshot> | undefined>;
209
211
  }
210
212
  /** Bind canonical recovery policy to the application's existing storage. */
@@ -6,7 +6,7 @@ import {
6
6
  observeTurnEvent,
7
7
  parseTurnObservation,
8
8
  resolveChatTurn
9
- } from "../chunk-3NM4GCAY.js";
9
+ } from "../chunk-DPO7FGCN.js";
10
10
  import {
11
11
  MISSING_TOOL_TERMINAL_ERROR,
12
12
  MISSING_TOOL_TERMINAL_REASON,
@@ -1,16 +1,20 @@
1
1
  import type { JsonRecord } from './stream-normalizer';
2
- /** Define the structure of a chat message stored for a specific conversation turn */
3
- export interface PersistedChatMessageForTurn {
4
- id: string;
5
- role: 'user' | 'assistant' | 'system' | 'tool';
6
- content: string;
2
+ /** Minimum read-only shape; typed chat parts need no dictionary index signature. */
3
+ interface TurnIdentityMessage {
4
+ readonly id: string;
5
+ readonly role: 'user' | 'assistant' | 'system' | 'tool';
6
+ readonly content: string;
7
+ readonly parts: readonly object[] | null;
8
+ }
9
+ /** Retained compatibility shape for callers using unstructured message records. */
10
+ export interface PersistedChatMessageForTurn extends TurnIdentityMessage {
7
11
  parts: Array<Record<string, unknown>> | null;
8
12
  }
9
13
  /** Represent a chat turn with resolved user message insertion and prior message context */
10
- export interface ResolvedChatTurn {
14
+ export interface ResolvedChatTurn<Message extends TurnIdentityMessage = PersistedChatMessageForTurn> {
11
15
  turnIndex: number;
12
16
  shouldInsertUserMessage: boolean;
13
- priorMessages: PersistedChatMessageForTurn[];
17
+ priorMessages: Message[];
14
18
  userParts: JsonRecord[];
15
19
  /** The id of the user row this turn REUSES (retry dedup), when one was
16
20
  * found. Absent on the insert path, where no row exists yet.
@@ -25,10 +29,10 @@ export declare function normalizeClientTurnId(value: unknown): string | undefine
25
29
  /** Build an array of text parts with optional turn ID for user input */
26
30
  export declare function buildUserTextParts(text: string, turnId: string | undefined): JsonRecord[];
27
31
  /** Resolve whether a message contains any part with the specified turn ID */
28
- export declare function messageHasTurnId(message: PersistedChatMessageForTurn, turnId: string): boolean;
32
+ export declare function messageHasTurnId(message: Pick<TurnIdentityMessage, 'parts'>, turnId: string): boolean;
29
33
  /** Resolve a chat turn by determining message reuse and constructing user message parts */
30
- export declare function resolveChatTurn(input: {
31
- existingMessages: PersistedChatMessageForTurn[];
34
+ export declare function resolveChatTurn<Message extends TurnIdentityMessage>(input: {
35
+ existingMessages: readonly Message[];
32
36
  userContent: string;
33
37
  turnId?: string;
34
38
  /** True when the thread has a turn still RUNNING in the turn-event buffer
@@ -46,4 +50,5 @@ export declare function resolveChatTurn(input: {
46
50
  * assistant row trailing a SETTLED turn is a completed answer (stop — the
47
51
  * user genuinely repeated a message and deserves a new turn). */
48
52
  hasRunningTurn?: boolean;
49
- }): ResolvedChatTurn;
53
+ }): ResolvedChatTurn<Message>;
54
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/agent-app",
3
- "version": "0.50.4",
3
+ "version": "0.50.5",
4
4
  "packageManager": "pnpm@11.24.0",
5
5
  "description": "Build agent applications with typed chat, tools, sandboxes, integrations, billing, and evaluation.",
6
6
  "keywords": [
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/stream/turn-identity.ts","../src/stream/turn-observation.ts"],"sourcesContent":["import type { JsonRecord } from './stream-normalizer'\n\n/** Define the structure of a chat message stored for a specific conversation turn */\nexport interface PersistedChatMessageForTurn {\n id: string\n role: 'user' | 'assistant' | 'system' | 'tool'\n content: string\n parts: Array<Record<string, unknown>> | null\n}\n\n/** Represent a chat turn with resolved user message insertion and prior message context */\nexport interface ResolvedChatTurn {\n turnIndex: number\n shouldInsertUserMessage: boolean\n priorMessages: PersistedChatMessageForTurn[]\n userParts: JsonRecord[]\n /** The id of the user row this turn REUSES (retry dedup), when one was\n * found. Absent on the insert path, where no row exists yet.\n *\n * The reused row is deliberately EXCLUDED from `priorMessages` (it is this\n * turn's own user message, not prior context), so this field is the only\n * way a caller can name it. */\n reusedUserMessageId?: string\n}\n\n/** Normalize and validate a client turn ID string ensuring it meets format and length requirements */\nexport function normalizeClientTurnId(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined\n if (typeof value !== 'string') throw new Error('turnId must be a string')\n const trimmed = value.trim()\n if (!trimmed) throw new Error('turnId must not be blank')\n if (trimmed.length > 160) throw new Error('turnId is too long')\n if (!/^[A-Za-z0-9:_-]+$/.test(trimmed)) {\n throw new Error('turnId contains unsupported characters')\n }\n return trimmed\n}\n\n/** Build an array of text parts with optional turn ID for user input */\nexport function buildUserTextParts(text: string, turnId: string | undefined): JsonRecord[] {\n const part: JsonRecord = { type: 'text', text }\n if (turnId) part.turnId = turnId\n return [part]\n}\n\n/** Resolve whether a message contains any part with the specified turn ID */\nexport function messageHasTurnId(message: PersistedChatMessageForTurn, turnId: string): boolean {\n for (const part of message.parts ?? []) {\n if (part && typeof part === 'object' && String(part.turnId ?? '') === turnId) {\n return true\n }\n }\n return false\n}\n\n/** Resolve a chat turn by determining message reuse and constructing user message parts */\nexport function resolveChatTurn(input: {\n existingMessages: PersistedChatMessageForTurn[]\n userContent: string\n turnId?: string\n /** True when the thread has a turn still RUNNING in the turn-event buffer\n * (`turnStore.listRunning(threadId)`).\n *\n * Without incremental persistence the trailing row of a thread mid-turn is\n * always the user row, so the content fallback below could assume it. With\n * incremental persistence the assistant row lands seconds into the turn, so\n * a retry of that same turn finds an ASSISTANT row trailing and would\n * insert a duplicate user row.\n *\n * This flag is the discriminator that keeps both cases right, and it needs\n * no new state: an assistant row trailing a turn that is still running is\n * that turn's in-flight draft (walk past it — this is a retry), whereas an\n * assistant row trailing a SETTLED turn is a completed answer (stop — the\n * user genuinely repeated a message and deserves a new turn). */\n hasRunningTurn?: boolean\n}): ResolvedChatTurn {\n const { existingMessages, userContent, turnId } = input\n const reusableIndex = findReusableUserMessageIndex(\n existingMessages,\n userContent,\n turnId,\n input.hasRunningTurn === true,\n )\n if (reusableIndex >= 0) {\n // Guarded read: `id` is typed `string`, but these rows come from a product\n // store the shell does not validate, so an adapter that omits it must\n // surface as \"no id\" rather than as the string \"undefined\".\n const reusedId = existingMessages[reusableIndex]?.id\n return {\n turnIndex: countUserMessages(existingMessages.slice(0, reusableIndex)),\n shouldInsertUserMessage: false,\n priorMessages: existingMessages.slice(0, reusableIndex),\n userParts: buildUserTextParts(userContent, turnId),\n ...(typeof reusedId === 'string' && reusedId ? { reusedUserMessageId: reusedId } : {}),\n }\n }\n\n return {\n turnIndex: countUserMessages(existingMessages),\n shouldInsertUserMessage: true,\n priorMessages: existingMessages,\n userParts: buildUserTextParts(userContent, turnId),\n }\n}\n\nfunction findReusableUserMessageIndex(\n messages: PersistedChatMessageForTurn[],\n userContent: string,\n turnId: string | undefined,\n hasRunningTurn: boolean,\n): number {\n if (turnId) {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n const message = messages[index]\n if (message?.role === 'user' && messageHasTurnId(message, turnId)) return index\n }\n // A caller-supplied id is authoritative. A different id with identical\n // text is a deliberate new turn, while a transport retry reuses the same\n // id and takes the match above. Falling through to content dedup here lets\n // an unrelated abandoned running row swallow an intentional repeat.\n return -1\n }\n\n // Content fallback for a client that sends no turnId. Only the trailing rows\n // of a turn still RUNNING are walked past (they are that turn's incrementally\n // persisted assistant draft); a settled assistant row still ends the scan, so\n // a user who genuinely repeats a message gets a new turn exactly as before.\n let index = messages.length - 1\n if (hasRunningTurn) {\n while (index >= 0 && messages[index]?.role === 'assistant') index -= 1\n }\n const latest = index >= 0 ? messages[index] : undefined\n if (latest?.role === 'user' && latest.content === userContent) return index\n\n return -1\n}\n\nfunction countUserMessages(messages: PersistedChatMessageForTurn[]): number {\n return messages.filter((message) => message.role === 'user').length\n}\n","/** Read-side checkpoints for native chat NDJSON. This never submits or cancels work. */\nexport interface TurnObservation {\n schema: 'turn-observation-v1'\n streamId: string | null\n /** Replay ordinals only. Unsequenced live frames cannot advance this cursor. */\n lastSeq: number\n outcome: 'completed' | 'failed' | null\n replayStatus: string | null\n eventCount: number\n}\n\nexport function parseTurnObservation(value?: unknown): TurnObservation {\n if (value === undefined) return {\n schema: 'turn-observation-v1', streamId: null, lastSeq: 0,\n outcome: null, replayStatus: null, eventCount: 0,\n }\n if (!value || typeof value !== 'object' || Array.isArray(value)) throw new TypeError('Invalid turn observation')\n const v = value as Record<string, unknown>\n if (v.schema !== 'turn-observation-v1'\n || !(v.streamId === null || (typeof v.streamId === 'string' && /^[A-Za-z0-9_-]+$/.test(v.streamId)))\n || !Number.isSafeInteger(v.lastSeq) || Number(v.lastSeq) < 0\n || !Number.isSafeInteger(v.eventCount) || Number(v.eventCount) < 0\n || !(v.outcome === null || v.outcome === 'completed' || v.outcome === 'failed')\n || !(v.replayStatus === null || typeof v.replayStatus === 'string')\n || (v.streamId === null && Number(v.lastSeq) > 0)) throw new TypeError('Invalid turn observation')\n return {\n schema: 'turn-observation-v1', streamId: v.streamId as string | null,\n lastSeq: Number(v.lastSeq), outcome: v.outcome as TurnObservation['outcome'],\n replayStatus: v.replayStatus as string | null, eventCount: Number(v.eventCount),\n }\n}\n\nexport interface TurnObservationUpdate {\n checkpoint: TurnObservation\n /** False only for an already-checkpointed replay ordinal. */\n accepted: boolean\n event: Record<string, unknown>\n}\n\n/** Reduce an observed frame. Ordered replay gaps are errors, not silent lost work. */\nexport function observeTurnEvent(previous: TurnObservation, raw: unknown): TurnObservationUpdate {\n const checkpoint = parseTurnObservation(previous)\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) throw new TypeError('Turn frame must be an object')\n const outer = raw as Record<string, unknown>\n const inner = outer.kind === 'event' ? outer.event : outer\n if (!inner || typeof inner !== 'object' || Array.isArray(inner)) throw new TypeError('Invalid turn event envelope')\n const event = inner as Record<string, unknown>\n if (typeof event.type !== 'string' || !event.type) throw new TypeError('Turn frame requires a type')\n\n // Even a duplicate marker must not switch which execution we are observing.\n if (event.type === 'turn') {\n if (typeof event.turnId !== 'string' || !/^[A-Za-z0-9_-]+$/.test(event.turnId)) throw new TypeError('Invalid stream identity')\n if (checkpoint.streamId !== null && checkpoint.streamId !== event.turnId) throw new Error('Replay stream identity changed')\n checkpoint.streamId = event.turnId\n }\n const seq = outer.seq\n if (seq !== undefined && seq !== -1) {\n if (!Number.isSafeInteger(seq) || Number(seq) < 1) throw new TypeError('Invalid replay ordinal')\n if (checkpoint.streamId === null) throw new Error('Replay ordinal arrived before stream identity')\n if (Number(seq) <= checkpoint.lastSeq) return { checkpoint, accepted: false, event }\n if (Number(seq) !== checkpoint.lastSeq + 1) throw new Error('Replay has a gap; retain the checkpoint and inspect durable history')\n checkpoint.lastSeq = Number(seq)\n } else if (seq === -1 && event.type !== 'turn_status') {\n throw new TypeError('Only a turn-status sentinel may have ordinal -1')\n }\n\n if (event.type === 'error' || event.type === 'session.run.failed') checkpoint.outcome = 'failed'\n if (event.type === 'session.run.completed' && checkpoint.outcome !== 'failed') checkpoint.outcome = 'completed'\n if (event.type === 'turn_status') {\n if (typeof event.status !== 'string') throw new TypeError('Turn status requires a value')\n checkpoint.replayStatus = event.status\n if (['error', 'failed', 'aborted', 'cancelled'].includes(event.status)) checkpoint.outcome = 'failed'\n if (['complete', 'completed'].includes(event.status) && checkpoint.outcome !== 'failed') checkpoint.outcome = 'completed'\n }\n checkpoint.eventCount += 1\n return { checkpoint, accepted: true, event }\n}\n\nexport interface ConsumeTurnStreamOptions {\n checkpoint?: TurnObservation\n /** Commit evidence and its checkpoint durably before acknowledging this frame. */\n commit(update: TurnObservationUpdate): Promise<void>\n /** Bound untrusted frame memory, not total run duration or total transcript size. */\n maxFrameBytes?: number\n}\n\n/**\n * Consume one viewing connection. EOF without a terminal event stays incomplete.\n * A disconnect/abort propagates; the last committed checkpoint remains resumable.\n * The caller owns network observation windows separately from execution deadlines.\n */\nexport async function consumeTurnStream(\n body: AsyncIterable<Uint8Array>,\n options: ConsumeTurnStreamOptions,\n): Promise<TurnObservation> {\n const maxFrameBytes = options.maxFrameBytes ?? 4 * 1024 * 1024\n if (!Number.isSafeInteger(maxFrameBytes) || maxFrameBytes < 1) throw new RangeError('Frame byte limit must be positive')\n let state = parseTurnObservation(options.checkpoint)\n const decoder = new TextDecoder('utf-8', { fatal: true })\n let pending = ''\n let frameBytes = 0\n async function accept(line: string): Promise<void> {\n if (!line.trim()) return\n const update = observeTurnEvent(state, JSON.parse(line))\n if (update.accepted) await options.commit(update)\n state = update.checkpoint\n }\n for await (const chunk of body) {\n // Count bytes before decoding: a malicious unterminated frame cannot grow\n // without bound, and splitting UTF-8 characters across chunks stays valid.\n let start = 0\n for (let end = 0; end < chunk.length; end += 1) {\n if (chunk[end] !== 10) continue\n frameBytes += end - start\n if (frameBytes > maxFrameBytes) throw new RangeError('Turn frame exceeds byte limit')\n pending += decoder.decode(chunk.subarray(start, end + 1), { stream: true })\n await accept(pending)\n pending = ''; frameBytes = 0; start = end + 1\n }\n frameBytes += chunk.length - start\n if (frameBytes > maxFrameBytes) throw new RangeError('Turn frame exceeds byte limit')\n pending += decoder.decode(chunk.subarray(start), { stream: true })\n }\n pending += decoder.decode()\n await accept(pending)\n return state\n}\n"],"mappings":"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","names":["index"]}