@ziro-agent/core
Advanced tools
+70
-5
@@ -683,2 +683,28 @@ import { B as BudgetUsage, a as BudgetContext, b as BudgetSpec, c as BudgetResolution, C as ChatMessage, N as NormalizedMessage, L as LanguageModel, F as FinishReason, T as ToolDefinitionForModel, M as ModelCallOptions, d as ContentPart, e as ToolCallPart, f as CostEstimate, g as ModelStreamPart, h as ModelGenerateResult } from './model-rEpWFV9q.cjs'; | ||
| } | ||
| /** | ||
| * True when the model run for this `resumeKey` has emitted a terminal part | ||
| * (`finish` or `error`). Used for RFC 0017 continue-upstream and observability. | ||
| */ | ||
| declare function isTerminalModelStreamPart(part: ModelStreamPart): boolean; | ||
| /** Snapshot of a resumable stream log (see {@link ResumableStreamEventStore.getSessionMeta}). */ | ||
| interface ResumableStreamSessionMeta { | ||
| /** Monotonic; index of the next `append` for this key. */ | ||
| nextIndex: number; | ||
| /** True once a terminal part (`finish` or `error`) has been stored. */ | ||
| completed: boolean; | ||
| /** Milliseconds since epoch of the last successful `append`, if any. */ | ||
| updatedAt?: number; | ||
| } | ||
| interface ResumableStreamContinueLock { | ||
| resumeKey: string; | ||
| token: string; | ||
| } | ||
| /** | ||
| * Optional extension for stores that can coordinate single-writer continuation | ||
| * across processes (RFC 0017 phase C). | ||
| */ | ||
| interface ResumableStreamContinueLockStore { | ||
| acquireContinueLock(resumeKey: string): Promise<ResumableStreamContinueLock>; | ||
| releaseContinueLock(lock: ResumableStreamContinueLock): Promise<void>; | ||
| } | ||
| interface ResumableStreamEventStore { | ||
@@ -688,11 +714,30 @@ createResumeKey(): string; | ||
| getParts(resumeKey: string, fromIndex: number): Promise<ModelStreamPart[]>; | ||
| /** | ||
| * Returns session metadata for a known `resumeKey`, or `null` if the key was | ||
| * never created in this store (or no longer exists, e.g. evicted in Redis). | ||
| */ | ||
| getSessionMeta(resumeKey: string): Promise<ResumableStreamSessionMeta | null>; | ||
| } | ||
| interface InMemoryResumableStreamEventStoreOptions { | ||
| now?: () => number; | ||
| /** Optional cap on retained events for a single resume key. */ | ||
| maxEventsPerStream?: number; | ||
| /** Optional cap on approximate UTF-8 bytes retained per resume key. */ | ||
| maxBytesPerStream?: number; | ||
| /** | ||
| * Override byte accounting strategy for tests / custom sizing. | ||
| * Defaults to UTF-8 bytes of `JSON.stringify(part)`. | ||
| */ | ||
| measurePartBytes?: (part: ModelStreamPart) => number; | ||
| } | ||
| declare class InMemoryResumableStreamEventStore implements ResumableStreamEventStore { | ||
| private readonly sessions; | ||
| private readonly now; | ||
| constructor(opts?: { | ||
| now?: () => number; | ||
| }); | ||
| private readonly maxEventsPerStream; | ||
| private readonly maxBytesPerStream; | ||
| private readonly measurePartBytes; | ||
| constructor(opts?: InMemoryResumableStreamEventStoreOptions); | ||
| createResumeKey(): string; | ||
| append(resumeKey: string, index: number, part: ModelStreamPart): Promise<void>; | ||
| getSessionMeta(resumeKey: string): Promise<ResumableStreamSessionMeta | null>; | ||
| getParts(resumeKey: string, fromIndex: number): Promise<ModelStreamPart[]>; | ||
@@ -752,4 +797,13 @@ } | ||
| onError?: (err: unknown) => void; | ||
| continueUpstream?: false; | ||
| }; | ||
| type StreamTextOptions = StreamTextOptionsFromModel | StreamTextOptionsFromReplay; | ||
| type StreamTextOptionsFromReplayAndContinue = GenerateTextOptions & { | ||
| resumeKey: string; | ||
| resumeFromIndex?: number; | ||
| streamEventStore: ResumableStreamEventStore; | ||
| /** Called once per error event from replay/live stream. */ | ||
| onError?: (err: unknown) => void; | ||
| continueUpstream: true; | ||
| }; | ||
| type StreamTextOptions = StreamTextOptionsFromModel | StreamTextOptionsFromReplay | StreamTextOptionsFromReplayAndContinue; | ||
| /** | ||
@@ -780,2 +834,13 @@ * Streaming counterpart of `generateText`. Returns a result object with two | ||
| interface ResumableStreamEvent { | ||
| phase: 'replay_start' | 'replay_end' | 'continue_lock_acquired' | 'continue_lock_released' | 'continue_upstream_start' | 'continue_upstream_end' | 'continue_upstream_skipped_completed'; | ||
| resumeKey: string; | ||
| replayCount?: number; | ||
| } | ||
| interface ResumableStreamObserver { | ||
| onEvent?(event: ResumableStreamEvent): void | Promise<void>; | ||
| } | ||
| declare function setResumableStreamObserver(next: ResumableStreamObserver | null): void; | ||
| declare function fireResumableStreamEvent(event: ResumableStreamEvent): void; | ||
| /** | ||
@@ -943,2 +1008,2 @@ * Middleware contract for {@link LanguageModel}. Three composable hooks | ||
| export { APICallError, type ApprovalContext, type ApprovalDecision, type ApprovalObserver, type ApprovalRequest, type Approver, type AutoApproverOptions, type BrowserAdapter, type BrowserNavigateOptions, BudgetContext, BudgetExceededError, type BudgetExceededKind, type BudgetObserver, BudgetResolution, type BudgetScope, BudgetSpec, BudgetUsage, ChatMessage, ContentPart, type CoreAgentSnapshotFields, CostEstimate, type FallbackChainOptions, FinishReason, type GenerateObjectOptions, type GenerateObjectResult, type GenerateTextOptions, type GenerateTextResult, InMemoryResumableStreamEventStore, type InlineMediaBytes, InvalidArgumentError, InvalidPromptError, JSONParseError, LanguageModel, type LanguageModelMiddleware, type LanguageModelMiddlewareContext, ModelCallOptions, ModelGenerateResult, ModelStreamPart, NoTextGeneratedError, NormalizedMessage, ObjectValidationError, type PendingApproval, type PromptInput, type RemoteMediaUrl, type RequiresApproval, type ResolvedMedia, ResumableStreamError, type ResumableStreamEventStore, type SandboxAdapter, type SandboxExecuteOptions, type SandboxExecuteResult, type SandboxFileArtifact, type SandboxLanguage, type SerializableBudgetSpec, type StreamTextOptions, type StreamTextResult, type StubBrowserAdapterResult, type StubSandboxAdapterOptions, TimeoutError, TokenUsage, ToolCallPart, ToolDefinitionForModel, UnsupportedPartError, type WithBudgetOptions, type WrapGenerateContext, type WrapStreamContext, ZiroError, applyResolution, assertProviderMapsUserMultimodalParts, autoApprove, autoReject, autoSuspend, buildStreamTextResult, computeActualUsd, createAutoApprover, createStubBrowserAdapter, createStubSandboxAdapter, estimateTokensFromMessages, estimateTokensFromString, fireAgentResumed, fireAgentSuspended, fireApprovalRequested, fireApprovalResolved, generateObject, generateText, getCurrentBudget, getCurrentScope, intersectSpecs, isZiroError, normalizePrompt, resolveEstimate, resolveMediaInput, resolveOnExceed, setApprovalObserver, setBudgetObserver, streamText, withBudget, withFallbackChain, wrapModel }; | ||
| export { APICallError, type ApprovalContext, type ApprovalDecision, type ApprovalObserver, type ApprovalRequest, type Approver, type AutoApproverOptions, type BrowserAdapter, type BrowserNavigateOptions, BudgetContext, BudgetExceededError, type BudgetExceededKind, type BudgetObserver, BudgetResolution, type BudgetScope, BudgetSpec, BudgetUsage, ChatMessage, ContentPart, type CoreAgentSnapshotFields, CostEstimate, type FallbackChainOptions, FinishReason, type GenerateObjectOptions, type GenerateObjectResult, type GenerateTextOptions, type GenerateTextResult, InMemoryResumableStreamEventStore, type InMemoryResumableStreamEventStoreOptions, type InlineMediaBytes, InvalidArgumentError, InvalidPromptError, JSONParseError, LanguageModel, type LanguageModelMiddleware, type LanguageModelMiddlewareContext, ModelCallOptions, ModelGenerateResult, ModelStreamPart, NoTextGeneratedError, NormalizedMessage, ObjectValidationError, type PendingApproval, type PromptInput, type RemoteMediaUrl, type RequiresApproval, type ResolvedMedia, type ResumableStreamContinueLock, type ResumableStreamContinueLockStore, ResumableStreamError, type ResumableStreamEvent, type ResumableStreamEventStore, type ResumableStreamObserver, type ResumableStreamSessionMeta, type SandboxAdapter, type SandboxExecuteOptions, type SandboxExecuteResult, type SandboxFileArtifact, type SandboxLanguage, type SerializableBudgetSpec, type StreamTextOptions, type StreamTextResult, type StubBrowserAdapterResult, type StubSandboxAdapterOptions, TimeoutError, TokenUsage, ToolCallPart, ToolDefinitionForModel, UnsupportedPartError, type WithBudgetOptions, type WrapGenerateContext, type WrapStreamContext, ZiroError, applyResolution, assertProviderMapsUserMultimodalParts, autoApprove, autoReject, autoSuspend, buildStreamTextResult, computeActualUsd, createAutoApprover, createStubBrowserAdapter, createStubSandboxAdapter, estimateTokensFromMessages, estimateTokensFromString, fireAgentResumed, fireAgentSuspended, fireApprovalRequested, fireApprovalResolved, fireResumableStreamEvent, generateObject, generateText, getCurrentBudget, getCurrentScope, intersectSpecs, isTerminalModelStreamPart, isZiroError, normalizePrompt, resolveEstimate, resolveMediaInput, resolveOnExceed, setApprovalObserver, setBudgetObserver, setResumableStreamObserver, streamText, withBudget, withFallbackChain, wrapModel }; |
+70
-5
@@ -683,2 +683,28 @@ import { B as BudgetUsage, a as BudgetContext, b as BudgetSpec, c as BudgetResolution, C as ChatMessage, N as NormalizedMessage, L as LanguageModel, F as FinishReason, T as ToolDefinitionForModel, M as ModelCallOptions, d as ContentPart, e as ToolCallPart, f as CostEstimate, g as ModelStreamPart, h as ModelGenerateResult } from './model-cJsb66J7.js'; | ||
| } | ||
| /** | ||
| * True when the model run for this `resumeKey` has emitted a terminal part | ||
| * (`finish` or `error`). Used for RFC 0017 continue-upstream and observability. | ||
| */ | ||
| declare function isTerminalModelStreamPart(part: ModelStreamPart): boolean; | ||
| /** Snapshot of a resumable stream log (see {@link ResumableStreamEventStore.getSessionMeta}). */ | ||
| interface ResumableStreamSessionMeta { | ||
| /** Monotonic; index of the next `append` for this key. */ | ||
| nextIndex: number; | ||
| /** True once a terminal part (`finish` or `error`) has been stored. */ | ||
| completed: boolean; | ||
| /** Milliseconds since epoch of the last successful `append`, if any. */ | ||
| updatedAt?: number; | ||
| } | ||
| interface ResumableStreamContinueLock { | ||
| resumeKey: string; | ||
| token: string; | ||
| } | ||
| /** | ||
| * Optional extension for stores that can coordinate single-writer continuation | ||
| * across processes (RFC 0017 phase C). | ||
| */ | ||
| interface ResumableStreamContinueLockStore { | ||
| acquireContinueLock(resumeKey: string): Promise<ResumableStreamContinueLock>; | ||
| releaseContinueLock(lock: ResumableStreamContinueLock): Promise<void>; | ||
| } | ||
| interface ResumableStreamEventStore { | ||
@@ -688,11 +714,30 @@ createResumeKey(): string; | ||
| getParts(resumeKey: string, fromIndex: number): Promise<ModelStreamPart[]>; | ||
| /** | ||
| * Returns session metadata for a known `resumeKey`, or `null` if the key was | ||
| * never created in this store (or no longer exists, e.g. evicted in Redis). | ||
| */ | ||
| getSessionMeta(resumeKey: string): Promise<ResumableStreamSessionMeta | null>; | ||
| } | ||
| interface InMemoryResumableStreamEventStoreOptions { | ||
| now?: () => number; | ||
| /** Optional cap on retained events for a single resume key. */ | ||
| maxEventsPerStream?: number; | ||
| /** Optional cap on approximate UTF-8 bytes retained per resume key. */ | ||
| maxBytesPerStream?: number; | ||
| /** | ||
| * Override byte accounting strategy for tests / custom sizing. | ||
| * Defaults to UTF-8 bytes of `JSON.stringify(part)`. | ||
| */ | ||
| measurePartBytes?: (part: ModelStreamPart) => number; | ||
| } | ||
| declare class InMemoryResumableStreamEventStore implements ResumableStreamEventStore { | ||
| private readonly sessions; | ||
| private readonly now; | ||
| constructor(opts?: { | ||
| now?: () => number; | ||
| }); | ||
| private readonly maxEventsPerStream; | ||
| private readonly maxBytesPerStream; | ||
| private readonly measurePartBytes; | ||
| constructor(opts?: InMemoryResumableStreamEventStoreOptions); | ||
| createResumeKey(): string; | ||
| append(resumeKey: string, index: number, part: ModelStreamPart): Promise<void>; | ||
| getSessionMeta(resumeKey: string): Promise<ResumableStreamSessionMeta | null>; | ||
| getParts(resumeKey: string, fromIndex: number): Promise<ModelStreamPart[]>; | ||
@@ -752,4 +797,13 @@ } | ||
| onError?: (err: unknown) => void; | ||
| continueUpstream?: false; | ||
| }; | ||
| type StreamTextOptions = StreamTextOptionsFromModel | StreamTextOptionsFromReplay; | ||
| type StreamTextOptionsFromReplayAndContinue = GenerateTextOptions & { | ||
| resumeKey: string; | ||
| resumeFromIndex?: number; | ||
| streamEventStore: ResumableStreamEventStore; | ||
| /** Called once per error event from replay/live stream. */ | ||
| onError?: (err: unknown) => void; | ||
| continueUpstream: true; | ||
| }; | ||
| type StreamTextOptions = StreamTextOptionsFromModel | StreamTextOptionsFromReplay | StreamTextOptionsFromReplayAndContinue; | ||
| /** | ||
@@ -780,2 +834,13 @@ * Streaming counterpart of `generateText`. Returns a result object with two | ||
| interface ResumableStreamEvent { | ||
| phase: 'replay_start' | 'replay_end' | 'continue_lock_acquired' | 'continue_lock_released' | 'continue_upstream_start' | 'continue_upstream_end' | 'continue_upstream_skipped_completed'; | ||
| resumeKey: string; | ||
| replayCount?: number; | ||
| } | ||
| interface ResumableStreamObserver { | ||
| onEvent?(event: ResumableStreamEvent): void | Promise<void>; | ||
| } | ||
| declare function setResumableStreamObserver(next: ResumableStreamObserver | null): void; | ||
| declare function fireResumableStreamEvent(event: ResumableStreamEvent): void; | ||
| /** | ||
@@ -943,2 +1008,2 @@ * Middleware contract for {@link LanguageModel}. Three composable hooks | ||
| export { APICallError, type ApprovalContext, type ApprovalDecision, type ApprovalObserver, type ApprovalRequest, type Approver, type AutoApproverOptions, type BrowserAdapter, type BrowserNavigateOptions, BudgetContext, BudgetExceededError, type BudgetExceededKind, type BudgetObserver, BudgetResolution, type BudgetScope, BudgetSpec, BudgetUsage, ChatMessage, ContentPart, type CoreAgentSnapshotFields, CostEstimate, type FallbackChainOptions, FinishReason, type GenerateObjectOptions, type GenerateObjectResult, type GenerateTextOptions, type GenerateTextResult, InMemoryResumableStreamEventStore, type InlineMediaBytes, InvalidArgumentError, InvalidPromptError, JSONParseError, LanguageModel, type LanguageModelMiddleware, type LanguageModelMiddlewareContext, ModelCallOptions, ModelGenerateResult, ModelStreamPart, NoTextGeneratedError, NormalizedMessage, ObjectValidationError, type PendingApproval, type PromptInput, type RemoteMediaUrl, type RequiresApproval, type ResolvedMedia, ResumableStreamError, type ResumableStreamEventStore, type SandboxAdapter, type SandboxExecuteOptions, type SandboxExecuteResult, type SandboxFileArtifact, type SandboxLanguage, type SerializableBudgetSpec, type StreamTextOptions, type StreamTextResult, type StubBrowserAdapterResult, type StubSandboxAdapterOptions, TimeoutError, TokenUsage, ToolCallPart, ToolDefinitionForModel, UnsupportedPartError, type WithBudgetOptions, type WrapGenerateContext, type WrapStreamContext, ZiroError, applyResolution, assertProviderMapsUserMultimodalParts, autoApprove, autoReject, autoSuspend, buildStreamTextResult, computeActualUsd, createAutoApprover, createStubBrowserAdapter, createStubSandboxAdapter, estimateTokensFromMessages, estimateTokensFromString, fireAgentResumed, fireAgentSuspended, fireApprovalRequested, fireApprovalResolved, generateObject, generateText, getCurrentBudget, getCurrentScope, intersectSpecs, isZiroError, normalizePrompt, resolveEstimate, resolveMediaInput, resolveOnExceed, setApprovalObserver, setBudgetObserver, streamText, withBudget, withFallbackChain, wrapModel }; | ||
| export { APICallError, type ApprovalContext, type ApprovalDecision, type ApprovalObserver, type ApprovalRequest, type Approver, type AutoApproverOptions, type BrowserAdapter, type BrowserNavigateOptions, BudgetContext, BudgetExceededError, type BudgetExceededKind, type BudgetObserver, BudgetResolution, type BudgetScope, BudgetSpec, BudgetUsage, ChatMessage, ContentPart, type CoreAgentSnapshotFields, CostEstimate, type FallbackChainOptions, FinishReason, type GenerateObjectOptions, type GenerateObjectResult, type GenerateTextOptions, type GenerateTextResult, InMemoryResumableStreamEventStore, type InMemoryResumableStreamEventStoreOptions, type InlineMediaBytes, InvalidArgumentError, InvalidPromptError, JSONParseError, LanguageModel, type LanguageModelMiddleware, type LanguageModelMiddlewareContext, ModelCallOptions, ModelGenerateResult, ModelStreamPart, NoTextGeneratedError, NormalizedMessage, ObjectValidationError, type PendingApproval, type PromptInput, type RemoteMediaUrl, type RequiresApproval, type ResolvedMedia, type ResumableStreamContinueLock, type ResumableStreamContinueLockStore, ResumableStreamError, type ResumableStreamEvent, type ResumableStreamEventStore, type ResumableStreamObserver, type ResumableStreamSessionMeta, type SandboxAdapter, type SandboxExecuteOptions, type SandboxExecuteResult, type SandboxFileArtifact, type SandboxLanguage, type SerializableBudgetSpec, type StreamTextOptions, type StreamTextResult, type StubBrowserAdapterResult, type StubSandboxAdapterOptions, TimeoutError, TokenUsage, ToolCallPart, ToolDefinitionForModel, UnsupportedPartError, type WithBudgetOptions, type WrapGenerateContext, type WrapStreamContext, ZiroError, applyResolution, assertProviderMapsUserMultimodalParts, autoApprove, autoReject, autoSuspend, buildStreamTextResult, computeActualUsd, createAutoApprover, createStubBrowserAdapter, createStubSandboxAdapter, estimateTokensFromMessages, estimateTokensFromString, fireAgentResumed, fireAgentSuspended, fireApprovalRequested, fireApprovalResolved, fireResumableStreamEvent, generateObject, generateText, getCurrentBudget, getCurrentScope, intersectSpecs, isTerminalModelStreamPart, isZiroError, normalizePrompt, resolveEstimate, resolveMediaInput, resolveOnExceed, setApprovalObserver, setBudgetObserver, setResumableStreamObserver, streamText, withBudget, withFallbackChain, wrapModel }; |
+252
-13
@@ -1318,2 +1318,15 @@ import { AsyncLocalStorage } from 'async_hooks'; | ||
| // src/streaming/resumable-stream-observer.ts | ||
| var observer3 = null; | ||
| function setResumableStreamObserver(next) { | ||
| observer3 = next; | ||
| } | ||
| function fireResumableStreamEvent(event) { | ||
| if (!observer3?.onEvent) return; | ||
| try { | ||
| void observer3.onEvent(event); | ||
| } catch { | ||
| } | ||
| } | ||
| // src/streaming/text-stream.ts | ||
@@ -1489,13 +1502,111 @@ function buildStreamTextResult({ source, onError }) { | ||
| if ("resumeKey" in options) { | ||
| const replayStream = buildReplayStream({ | ||
| parts: await options.streamEventStore.getParts( | ||
| options.resumeKey, | ||
| options.resumeFromIndex ?? 0 | ||
| ) | ||
| const replayParts = await options.streamEventStore.getParts( | ||
| options.resumeKey, | ||
| options.resumeFromIndex ?? 0 | ||
| ); | ||
| fireResumableStreamEvent({ | ||
| phase: "replay_start", | ||
| resumeKey: options.resumeKey, | ||
| replayCount: replayParts.length | ||
| }); | ||
| const replay = buildStreamTextResult({ | ||
| source: replayStream, | ||
| ...options.onError ? { onError: options.onError } : {} | ||
| }); | ||
| return { ...replay, resumeKey: options.resumeKey }; | ||
| const replayStream = buildReplayStream({ parts: replayParts }); | ||
| if (!options.continueUpstream) { | ||
| fireResumableStreamEvent({ | ||
| phase: "replay_end", | ||
| resumeKey: options.resumeKey, | ||
| replayCount: replayParts.length | ||
| }); | ||
| const replay = buildStreamTextResult({ | ||
| source: replayStream, | ||
| ...options.onError ? { onError: options.onError } : {} | ||
| }); | ||
| return { ...replay, resumeKey: options.resumeKey }; | ||
| } | ||
| let lock = null; | ||
| try { | ||
| const maybeLockStore = asContinueLockStore(options.streamEventStore); | ||
| if (maybeLockStore) { | ||
| lock = await maybeLockStore.acquireContinueLock(options.resumeKey); | ||
| fireResumableStreamEvent({ | ||
| phase: "continue_lock_acquired", | ||
| resumeKey: options.resumeKey | ||
| }); | ||
| } | ||
| const meta = await options.streamEventStore.getSessionMeta(options.resumeKey); | ||
| if (meta?.completed) { | ||
| if (lock && maybeLockStore) { | ||
| await maybeLockStore.releaseContinueLock(lock); | ||
| fireResumableStreamEvent({ | ||
| phase: "continue_lock_released", | ||
| resumeKey: options.resumeKey | ||
| }); | ||
| lock = null; | ||
| } | ||
| fireResumableStreamEvent({ | ||
| phase: "continue_upstream_skipped_completed", | ||
| resumeKey: options.resumeKey, | ||
| replayCount: replayParts.length | ||
| }); | ||
| fireResumableStreamEvent({ | ||
| phase: "replay_end", | ||
| resumeKey: options.resumeKey, | ||
| replayCount: replayParts.length | ||
| }); | ||
| const replay2 = buildStreamTextResult({ | ||
| source: replayStream, | ||
| ...options.onError ? { onError: options.onError } : {} | ||
| }); | ||
| return { ...replay2, resumeKey: options.resumeKey }; | ||
| } | ||
| const { resumeKey, resumeFromIndex, streamEventStore: streamEventStore2, continueUpstream, onError: onError2, ...live } = options; | ||
| fireResumableStreamEvent({ | ||
| phase: "continue_upstream_start", | ||
| resumeKey: options.resumeKey | ||
| }); | ||
| const liveResult = await streamText({ | ||
| ...live, | ||
| ...onError2 ? { onError: onError2 } : {} | ||
| }); | ||
| const persistedLive = tapAndPersistStream(liveResult.fullStream, { | ||
| resumeKey: options.resumeKey, | ||
| store: options.streamEventStore, | ||
| startIndex: meta?.nextIndex ?? replayParts.length | ||
| }); | ||
| const liveWithUnlock = lock && maybeLockStore ? withFinally(persistedLive, async () => { | ||
| await maybeLockStore.releaseContinueLock(lock); | ||
| fireResumableStreamEvent({ | ||
| phase: "continue_lock_released", | ||
| resumeKey: options.resumeKey | ||
| }); | ||
| }) : persistedLive; | ||
| const combined = withFinally(concatStreams(replayStream, liveWithUnlock), async () => { | ||
| fireResumableStreamEvent({ | ||
| phase: "continue_upstream_end", | ||
| resumeKey: options.resumeKey | ||
| }); | ||
| fireResumableStreamEvent({ | ||
| phase: "replay_end", | ||
| resumeKey: options.resumeKey, | ||
| replayCount: replayParts.length | ||
| }); | ||
| }); | ||
| const replay = buildStreamTextResult({ | ||
| source: combined, | ||
| ...options.onError ? { onError: options.onError } : {} | ||
| }); | ||
| return { ...replay, resumeKey: options.resumeKey }; | ||
| } catch (err) { | ||
| if (lock) { | ||
| const maybeLockStore = asContinueLockStore(options.streamEventStore); | ||
| if (maybeLockStore) { | ||
| await maybeLockStore.releaseContinueLock(lock).catch(() => { | ||
| }); | ||
| fireResumableStreamEvent({ | ||
| phase: "continue_lock_released", | ||
| resumeKey: options.resumeKey | ||
| }); | ||
| } | ||
| } | ||
| throw err; | ||
| } | ||
| } | ||
@@ -1589,3 +1700,3 @@ const { model, tools, toolChoice, onError, budget, resumable, streamEventStore, ...rest } = options; | ||
| async start(controller) { | ||
| let index = 0; | ||
| let index = opts.startIndex ?? 0; | ||
| const reader = source.getReader(); | ||
@@ -1620,2 +1731,67 @@ try { | ||
| } | ||
| function concatStreams(first, second) { | ||
| return new ReadableStream({ | ||
| async start(controller) { | ||
| const firstReader = first.getReader(); | ||
| const secondReader = second.getReader(); | ||
| try { | ||
| while (true) { | ||
| const { done, value } = await firstReader.read(); | ||
| if (done) break; | ||
| controller.enqueue(value); | ||
| } | ||
| while (true) { | ||
| const { done, value } = await secondReader.read(); | ||
| if (done) break; | ||
| controller.enqueue(value); | ||
| } | ||
| controller.close(); | ||
| } catch (err) { | ||
| controller.error(err); | ||
| } finally { | ||
| firstReader.releaseLock(); | ||
| secondReader.releaseLock(); | ||
| } | ||
| }, | ||
| async cancel(reason) { | ||
| await Promise.allSettled([first.cancel(reason), second.cancel(reason)]); | ||
| } | ||
| }); | ||
| } | ||
| function asContinueLockStore(store) { | ||
| if ("acquireContinueLock" in store && typeof store.acquireContinueLock === "function" && "releaseContinueLock" in store && typeof store.releaseContinueLock === "function") { | ||
| return store; | ||
| } | ||
| return null; | ||
| } | ||
| function withFinally(source, onFinally) { | ||
| let finished = false; | ||
| const finalize = async () => { | ||
| if (finished) return; | ||
| finished = true; | ||
| await onFinally(); | ||
| }; | ||
| return new ReadableStream({ | ||
| async start(controller) { | ||
| const reader = source.getReader(); | ||
| try { | ||
| while (true) { | ||
| const { done, value } = await reader.read(); | ||
| if (done) break; | ||
| controller.enqueue(value); | ||
| } | ||
| controller.close(); | ||
| } catch (err) { | ||
| controller.error(err); | ||
| } finally { | ||
| reader.releaseLock(); | ||
| await finalize(); | ||
| } | ||
| }, | ||
| async cancel(reason) { | ||
| await source.cancel(reason); | ||
| await finalize(); | ||
| } | ||
| }); | ||
| } | ||
@@ -1629,11 +1805,20 @@ // src/streaming/resumable-stream-store.ts | ||
| }; | ||
| function isTerminalModelStreamPart(part) { | ||
| return part.type === "finish" || part.type === "error"; | ||
| } | ||
| var InMemoryResumableStreamEventStore = class { | ||
| sessions = /* @__PURE__ */ new Map(); | ||
| now; | ||
| maxEventsPerStream; | ||
| maxBytesPerStream; | ||
| measurePartBytes; | ||
| constructor(opts = {}) { | ||
| this.now = opts.now ?? Date.now; | ||
| this.maxEventsPerStream = opts.maxEventsPerStream; | ||
| this.maxBytesPerStream = opts.maxBytesPerStream; | ||
| this.measurePartBytes = opts.measurePartBytes ?? defaultMeasurePartBytes; | ||
| } | ||
| createResumeKey() { | ||
| const key = uuidv7(this.now()); | ||
| this.sessions.set(key, { parts: [] }); | ||
| this.sessions.set(key, { parts: [], sizeBytes: 0, completed: false }); | ||
| return key; | ||
@@ -1646,2 +1831,7 @@ } | ||
| } | ||
| if (session.completed) { | ||
| throw new ResumableStreamError( | ||
| `Resumable stream is already completed for ${resumeKey}; appends are not allowed.` | ||
| ); | ||
| } | ||
| if (!Number.isInteger(index) || index < 0) { | ||
@@ -1655,4 +1845,37 @@ throw new ResumableStreamError(`Invalid event index: ${index}`); | ||
| } | ||
| const partBytes = this.measurePartBytes(part); | ||
| if (!Number.isFinite(partBytes) || partBytes < 0) { | ||
| throw new ResumableStreamError(`Invalid measured part bytes: ${partBytes}`); | ||
| } | ||
| const nextCount = session.parts.length + 1; | ||
| if (this.maxEventsPerStream !== void 0 && nextCount > this.maxEventsPerStream) { | ||
| throw new ResumableStreamError( | ||
| `Resumable stream event cap exceeded for ${resumeKey}: ${nextCount} > ${this.maxEventsPerStream}.` | ||
| ); | ||
| } | ||
| const nextBytes = session.sizeBytes + partBytes; | ||
| if (this.maxBytesPerStream !== void 0 && nextBytes > this.maxBytesPerStream) { | ||
| throw new ResumableStreamError( | ||
| `Resumable stream byte cap exceeded for ${resumeKey}: ${nextBytes} > ${this.maxBytesPerStream}.` | ||
| ); | ||
| } | ||
| session.parts.push(part); | ||
| session.sizeBytes = nextBytes; | ||
| const t = this.now(); | ||
| session.updatedAt = t; | ||
| if (isTerminalModelStreamPart(part)) { | ||
| session.completed = true; | ||
| } | ||
| } | ||
| async getSessionMeta(resumeKey) { | ||
| const session = this.sessions.get(resumeKey); | ||
| if (!session) { | ||
| return null; | ||
| } | ||
| return { | ||
| nextIndex: session.parts.length, | ||
| completed: session.completed, | ||
| ...session.updatedAt !== void 0 ? { updatedAt: session.updatedAt } : {} | ||
| }; | ||
| } | ||
| async getParts(resumeKey, fromIndex) { | ||
@@ -1693,2 +1916,18 @@ const session = this.sessions.get(resumeKey); | ||
| } | ||
| function defaultMeasurePartBytes(part) { | ||
| return byteLength(JSON.stringify(part)); | ||
| } | ||
| function byteLength(s) { | ||
| let bytes = 0; | ||
| for (let i = 0; i < s.length; i++) { | ||
| const code = s.charCodeAt(i); | ||
| if (code < 128) bytes += 1; | ||
| else if (code < 2048) bytes += 2; | ||
| else if (code >= 55296 && code <= 56319) { | ||
| bytes += 4; | ||
| i++; | ||
| } else bytes += 3; | ||
| } | ||
| return bytes; | ||
| } | ||
@@ -1870,4 +2109,4 @@ // src/util/fallback-model.ts | ||
| export { APICallError, BudgetExceededError, InMemoryResumableStreamEventStore, InvalidArgumentError, InvalidPromptError, JSONParseError, NoTextGeneratedError, ObjectValidationError, ResumableStreamError, TimeoutError, UnsupportedPartError, ZiroError, addUsage, applyResolution, assertProviderMapsUserMultimodalParts, autoApprove, autoReject, autoSuspend, buildStreamTextResult, computeActualUsd, createAutoApprover, createStubBrowserAdapter, createStubSandboxAdapter, emptyUsage, estimateTokensFromMessages, estimateTokensFromString, fireAgentResumed, fireAgentSuspended, fireApprovalRequested, fireApprovalResolved, generateObject, generateText, getCurrentBudget, getCurrentScope, intersectSpecs, isZiroError, normalizePrompt, resolveEstimate, resolveMediaInput, resolveOnExceed, setApprovalObserver, setBudgetObserver, streamText, withBudget, withFallbackChain, wrapModel }; | ||
| export { APICallError, BudgetExceededError, InMemoryResumableStreamEventStore, InvalidArgumentError, InvalidPromptError, JSONParseError, NoTextGeneratedError, ObjectValidationError, ResumableStreamError, TimeoutError, UnsupportedPartError, ZiroError, addUsage, applyResolution, assertProviderMapsUserMultimodalParts, autoApprove, autoReject, autoSuspend, buildStreamTextResult, computeActualUsd, createAutoApprover, createStubBrowserAdapter, createStubSandboxAdapter, emptyUsage, estimateTokensFromMessages, estimateTokensFromString, fireAgentResumed, fireAgentSuspended, fireApprovalRequested, fireApprovalResolved, fireResumableStreamEvent, generateObject, generateText, getCurrentBudget, getCurrentScope, intersectSpecs, isTerminalModelStreamPart, isZiroError, normalizePrompt, resolveEstimate, resolveMediaInput, resolveOnExceed, setApprovalObserver, setBudgetObserver, setResumableStreamObserver, streamText, withBudget, withFallbackChain, wrapModel }; | ||
| //# sourceMappingURL=index.js.map | ||
| //# sourceMappingURL=index.js.map |
+1
-1
| { | ||
| "name": "@ziro-agent/core", | ||
| "version": "0.9.0", | ||
| "version": "0.10.0", | ||
| "description": "Type-safe core for ZiroAgent SDK: language model interface, generateText, streamText, message types.", | ||
@@ -5,0 +5,0 @@ "license": "Apache-2.0", |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
723490
9.31%6334
9.4%