@superblocksteam/vite-plugin-file-sync 2.0.59-next.2 → 2.0.59-next.4
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.
- package/dist/ai-service/agent/prompts/build-base-system-prompt.d.ts.map +1 -1
- package/dist/ai-service/agent/prompts/build-base-system-prompt.js +10 -1
- package/dist/ai-service/agent/prompts/build-base-system-prompt.js.map +1 -1
- package/dist/ai-service/agent/subagents/apis/examples.d.ts.map +1 -1
- package/dist/ai-service/agent/subagents/apis/examples.js +137 -10
- package/dist/ai-service/agent/subagents/apis/examples.js.map +1 -1
- package/dist/ai-service/agent/subagents/apis/static-analysis.d.ts.map +1 -1
- package/dist/ai-service/agent/subagents/apis/static-analysis.js +14 -7
- package/dist/ai-service/agent/subagents/apis/static-analysis.js.map +1 -1
- package/dist/ai-service/agent/tool-message-utils.d.ts.map +1 -1
- package/dist/ai-service/agent/tool-message-utils.js +6 -2
- package/dist/ai-service/agent/tool-message-utils.js.map +1 -1
- package/dist/ai-service/agent/tools/apis/analysis.d.ts +9 -0
- package/dist/ai-service/agent/tools/apis/analysis.d.ts.map +1 -0
- package/dist/ai-service/agent/tools/apis/analysis.js +357 -0
- package/dist/ai-service/agent/tools/apis/analysis.js.map +1 -0
- package/dist/ai-service/agent/{subagents → tools}/apis/api-executor.d.ts +35 -10
- package/dist/ai-service/agent/tools/apis/api-executor.d.ts.map +1 -0
- package/dist/ai-service/agent/{subagents → tools}/apis/api-executor.js +179 -94
- package/dist/ai-service/agent/tools/apis/api-executor.js.map +1 -0
- package/dist/ai-service/agent/tools/apis/api-source.d.ts +19 -0
- package/dist/ai-service/agent/tools/apis/api-source.d.ts.map +1 -0
- package/dist/ai-service/agent/tools/apis/api-source.js +73 -0
- package/dist/ai-service/agent/tools/apis/api-source.js.map +1 -0
- package/dist/ai-service/agent/tools/apis/api-validation-orchestrator.d.ts +51 -0
- package/dist/ai-service/agent/tools/apis/api-validation-orchestrator.d.ts.map +1 -0
- package/dist/ai-service/agent/tools/apis/api-validation-orchestrator.js +510 -0
- package/dist/ai-service/agent/tools/apis/api-validation-orchestrator.js.map +1 -0
- package/dist/ai-service/agent/tools/apis/build-api-artifact.d.ts +32 -0
- package/dist/ai-service/agent/tools/apis/build-api-artifact.d.ts.map +1 -0
- package/dist/ai-service/agent/tools/apis/build-api-artifact.js +313 -0
- package/dist/ai-service/agent/tools/apis/build-api-artifact.js.map +1 -0
- package/dist/ai-service/agent/tools/apis/build-api.d.ts +1 -10
- package/dist/ai-service/agent/tools/apis/build-api.d.ts.map +1 -1
- package/dist/ai-service/agent/tools/apis/build-api.js +26 -238
- package/dist/ai-service/agent/tools/apis/build-api.js.map +1 -1
- package/dist/ai-service/agent/tools/apis/get-api-docs.d.ts +11 -0
- package/dist/ai-service/agent/tools/apis/get-api-docs.d.ts.map +1 -0
- package/dist/ai-service/agent/tools/apis/get-api-docs.js +1809 -0
- package/dist/ai-service/agent/tools/apis/get-api-docs.js.map +1 -0
- package/dist/ai-service/agent/tools/apis/integration-types.d.ts +37 -0
- package/dist/ai-service/agent/tools/apis/integration-types.d.ts.map +1 -0
- package/dist/ai-service/agent/tools/apis/integration-types.js +697 -0
- package/dist/ai-service/agent/tools/apis/integration-types.js.map +1 -0
- package/dist/ai-service/agent/tools/apis/test-api.d.ts +25 -0
- package/dist/ai-service/agent/tools/apis/test-api.d.ts.map +1 -0
- package/dist/ai-service/agent/tools/apis/test-api.js +194 -0
- package/dist/ai-service/agent/tools/apis/test-api.js.map +1 -0
- package/dist/ai-service/agent/tools/apis/write-api.d.ts +11 -0
- package/dist/ai-service/agent/tools/apis/write-api.d.ts.map +1 -0
- package/dist/ai-service/agent/tools/apis/write-api.js +41 -0
- package/dist/ai-service/agent/tools/apis/write-api.js.map +1 -0
- package/dist/ai-service/agent/tools/build-read-files.js +2 -2
- package/dist/ai-service/agent/tools/build-read-files.js.map +1 -1
- package/dist/ai-service/agent/tools.d.ts +2 -5
- package/dist/ai-service/agent/tools.d.ts.map +1 -1
- package/dist/ai-service/agent/tools.js +51 -22
- package/dist/ai-service/agent/tools.js.map +1 -1
- package/dist/ai-service/agent/tools2/access-control.d.ts +1 -0
- package/dist/ai-service/agent/tools2/access-control.d.ts.map +1 -1
- package/dist/ai-service/agent/tools2/access-control.js +15 -13
- package/dist/ai-service/agent/tools2/access-control.js.map +1 -1
- package/dist/ai-service/agent/tools2/registry.d.ts +2 -1
- package/dist/ai-service/agent/tools2/registry.d.ts.map +1 -1
- package/dist/ai-service/agent/tools2/registry.js +4 -3
- package/dist/ai-service/agent/tools2/registry.js.map +1 -1
- package/dist/ai-service/agent/tools2/tools/exit-plan-mode.d.ts +2 -1
- package/dist/ai-service/agent/tools2/tools/exit-plan-mode.d.ts.map +1 -1
- package/dist/ai-service/agent/tools2/tools/exit-plan-mode.js +103 -88
- package/dist/ai-service/agent/tools2/tools/exit-plan-mode.js.map +1 -1
- package/dist/ai-service/agent/tools2/tools/grep-metadata.d.ts.map +1 -1
- package/dist/ai-service/agent/tools2/tools/grep-metadata.js +25 -4
- package/dist/ai-service/agent/tools2/tools/grep-metadata.js.map +1 -1
- package/dist/ai-service/agent/tools2/types.d.ts +1 -1
- package/dist/ai-service/agent/tools2/types.d.ts.map +1 -1
- package/dist/ai-service/agent/tools2/types.js.map +1 -1
- package/dist/ai-service/agent/tools2/utils.d.ts.map +1 -1
- package/dist/ai-service/agent/tools2/utils.js +4 -1
- package/dist/ai-service/agent/tools2/utils.js.map +1 -1
- package/dist/ai-service/agent/utils.d.ts +1 -3
- package/dist/ai-service/agent/utils.d.ts.map +1 -1
- package/dist/ai-service/agent/utils.js +44 -4
- package/dist/ai-service/agent/utils.js.map +1 -1
- package/dist/ai-service/app-interface/shell.d.ts +5 -0
- package/dist/ai-service/app-interface/shell.d.ts.map +1 -1
- package/dist/ai-service/app-interface/shell.js +17 -2
- package/dist/ai-service/app-interface/shell.js.map +1 -1
- package/dist/ai-service/chat/chat-session-store.d.ts +7 -0
- package/dist/ai-service/chat/chat-session-store.d.ts.map +1 -1
- package/dist/ai-service/chat/chat-session-store.js +26 -0
- package/dist/ai-service/chat/chat-session-store.js.map +1 -1
- package/dist/ai-service/const.d.ts +2 -1
- package/dist/ai-service/const.d.ts.map +1 -1
- package/dist/ai-service/const.js +1 -0
- package/dist/ai-service/const.js.map +1 -1
- package/dist/ai-service/index.d.ts +5 -1
- package/dist/ai-service/index.d.ts.map +1 -1
- package/dist/ai-service/index.js +55 -7
- package/dist/ai-service/index.js.map +1 -1
- package/dist/ai-service/integrations/metadata-storage/index.d.ts +10 -0
- package/dist/ai-service/integrations/metadata-storage/index.d.ts.map +1 -1
- package/dist/ai-service/integrations/metadata-storage/local.d.ts +4 -2
- package/dist/ai-service/integrations/metadata-storage/local.d.ts.map +1 -1
- package/dist/ai-service/integrations/metadata-storage/local.js +35 -9
- package/dist/ai-service/integrations/metadata-storage/local.js.map +1 -1
- package/dist/ai-service/integrations/store.d.ts +27 -2
- package/dist/ai-service/integrations/store.d.ts.map +1 -1
- package/dist/ai-service/integrations/store.js +129 -62
- package/dist/ai-service/integrations/store.js.map +1 -1
- package/dist/ai-service/llm/client.d.ts +123 -0
- package/dist/ai-service/llm/client.d.ts.map +1 -0
- package/dist/ai-service/llm/client.js +168 -0
- package/dist/ai-service/llm/client.js.map +1 -0
- package/dist/ai-service/llm/context/context-handle.d.ts +4 -4
- package/dist/ai-service/llm/context/context-handle.d.ts.map +1 -1
- package/dist/ai-service/llm/context/context-handle.js +7 -3
- package/dist/ai-service/llm/context/context-handle.js.map +1 -1
- package/dist/ai-service/llm/context/context.d.ts +28 -0
- package/dist/ai-service/llm/context/context.d.ts.map +1 -1
- package/dist/ai-service/llm/context/context.js +117 -0
- package/dist/ai-service/llm/context/context.js.map +1 -1
- package/dist/ai-service/llm/context/manager.d.ts +22 -2
- package/dist/ai-service/llm/context/manager.d.ts.map +1 -1
- package/dist/ai-service/llm/context/manager.js +86 -13
- package/dist/ai-service/llm/context/manager.js.map +1 -1
- package/dist/ai-service/llm/context/storage/index.d.ts +1 -0
- package/dist/ai-service/llm/context/storage/index.d.ts.map +1 -1
- package/dist/ai-service/llm/context/storage/local.d.ts +1 -0
- package/dist/ai-service/llm/context/storage/local.d.ts.map +1 -1
- package/dist/ai-service/llm/context/storage/local.js +13 -1
- package/dist/ai-service/llm/context/storage/local.js.map +1 -1
- package/dist/ai-service/llm/error.d.ts +14 -4
- package/dist/ai-service/llm/error.d.ts.map +1 -1
- package/dist/ai-service/llm/error.js +49 -4
- package/dist/ai-service/llm/error.js.map +1 -1
- package/dist/ai-service/llm/interaction/adapters/vercel.d.ts +67 -0
- package/dist/ai-service/llm/interaction/adapters/vercel.d.ts.map +1 -0
- package/dist/ai-service/llm/interaction/adapters/vercel.js +110 -0
- package/dist/ai-service/llm/interaction/adapters/vercel.js.map +1 -0
- package/dist/ai-service/llm/interaction/compose.d.ts +71 -0
- package/dist/ai-service/llm/interaction/compose.d.ts.map +1 -0
- package/dist/ai-service/llm/interaction/compose.js +88 -0
- package/dist/ai-service/llm/interaction/compose.js.map +1 -0
- package/dist/ai-service/llm/interaction/index.d.ts +68 -0
- package/dist/ai-service/llm/interaction/index.d.ts.map +1 -0
- package/dist/ai-service/llm/interaction/index.js +70 -0
- package/dist/ai-service/llm/interaction/index.js.map +1 -0
- package/dist/ai-service/llm/interaction/middleware.d.ts +52 -0
- package/dist/ai-service/llm/interaction/middleware.d.ts.map +1 -0
- package/dist/ai-service/llm/interaction/middleware.js +17 -0
- package/dist/ai-service/llm/interaction/middleware.js.map +1 -0
- package/dist/ai-service/llm/interaction/middlewares/llmobs.d.ts +45 -0
- package/dist/ai-service/llm/interaction/middlewares/llmobs.d.ts.map +1 -0
- package/dist/ai-service/llm/interaction/middlewares/llmobs.js +85 -0
- package/dist/ai-service/llm/interaction/middlewares/llmobs.js.map +1 -0
- package/dist/ai-service/llm/interaction/middlewares/logging.d.ts +88 -0
- package/dist/ai-service/llm/interaction/middlewares/logging.d.ts.map +1 -0
- package/dist/ai-service/llm/interaction/middlewares/logging.js +238 -0
- package/dist/ai-service/llm/interaction/middlewares/logging.js.map +1 -0
- package/dist/ai-service/llm/interaction/middlewares/profiler.d.ts +47 -0
- package/dist/ai-service/llm/interaction/middlewares/profiler.d.ts.map +1 -0
- package/dist/ai-service/llm/interaction/middlewares/profiler.js +183 -0
- package/dist/ai-service/llm/interaction/middlewares/profiler.js.map +1 -0
- package/dist/ai-service/llm/interaction/middlewares/stream-retry.d.ts +121 -0
- package/dist/ai-service/llm/interaction/middlewares/stream-retry.d.ts.map +1 -0
- package/dist/ai-service/llm/interaction/middlewares/stream-retry.js +291 -0
- package/dist/ai-service/llm/interaction/middlewares/stream-retry.js.map +1 -0
- package/dist/ai-service/llm/interaction/provider.d.ts +158 -0
- package/dist/ai-service/llm/interaction/provider.d.ts.map +1 -0
- package/dist/ai-service/llm/interaction/provider.js +15 -0
- package/dist/ai-service/llm/interaction/provider.js.map +1 -0
- package/dist/ai-service/llm/interaction/stream-lifecycle.d.ts +48 -0
- package/dist/ai-service/llm/interaction/stream-lifecycle.d.ts.map +1 -0
- package/dist/ai-service/llm/interaction/stream-lifecycle.js +131 -0
- package/dist/ai-service/llm/interaction/stream-lifecycle.js.map +1 -0
- package/dist/ai-service/llm/provider.d.ts +1 -2
- package/dist/ai-service/llm/provider.d.ts.map +1 -1
- package/dist/ai-service/llm/provider.js +3 -6
- package/dist/ai-service/llm/provider.js.map +1 -1
- package/dist/ai-service/llmobs/helpers.d.ts +7 -8
- package/dist/ai-service/llmobs/helpers.d.ts.map +1 -1
- package/dist/ai-service/llmobs/helpers.js +8 -48
- package/dist/ai-service/llmobs/helpers.js.map +1 -1
- package/dist/ai-service/llmobs/middleware/stream-text.d.ts +19 -21
- package/dist/ai-service/llmobs/middleware/stream-text.d.ts.map +1 -1
- package/dist/ai-service/llmobs/middleware/stream-text.js +98 -106
- package/dist/ai-service/llmobs/middleware/stream-text.js.map +1 -1
- package/dist/ai-service/llmobs/types.d.ts +14 -1
- package/dist/ai-service/llmobs/types.d.ts.map +1 -1
- package/dist/ai-service/state-machine/clark-fsm.d.ts +75 -5
- package/dist/ai-service/state-machine/clark-fsm.d.ts.map +1 -1
- package/dist/ai-service/state-machine/clark-fsm.js +100 -0
- package/dist/ai-service/state-machine/clark-fsm.js.map +1 -1
- package/dist/ai-service/state-machine/handlers/agent-planning.d.ts.map +1 -1
- package/dist/ai-service/state-machine/handlers/agent-planning.js +4 -0
- package/dist/ai-service/state-machine/handlers/agent-planning.js.map +1 -1
- package/dist/ai-service/state-machine/handlers/llm-generating.d.ts.map +1 -1
- package/dist/ai-service/state-machine/handlers/llm-generating.js +91 -456
- package/dist/ai-service/state-machine/handlers/llm-generating.js.map +1 -1
- package/dist/ai-service/state-machine/handlers/runtime-reviewing.js +1 -1
- package/dist/ai-service/state-machine/handlers/runtime-reviewing.js.map +1 -1
- package/dist/ai-service/state-machine/helpers/peer.d.ts.map +1 -1
- package/dist/ai-service/state-machine/helpers/peer.js +15 -0
- package/dist/ai-service/state-machine/helpers/peer.js.map +1 -1
- package/dist/ai-service/state-machine/mocks.d.ts.map +1 -1
- package/dist/ai-service/state-machine/mocks.js +1 -0
- package/dist/ai-service/state-machine/mocks.js.map +1 -1
- package/dist/ai-service/types.d.ts +30 -0
- package/dist/ai-service/types.d.ts.map +1 -1
- package/dist/binding-extraction/extract-identifiers.d.ts +14 -0
- package/dist/binding-extraction/extract-identifiers.d.ts.map +1 -1
- package/dist/binding-extraction/extract-identifiers.js +46 -1
- package/dist/binding-extraction/extract-identifiers.js.map +1 -1
- package/dist/binding-extraction/js-identifiers.d.ts +14 -0
- package/dist/binding-extraction/js-identifiers.d.ts.map +1 -1
- package/dist/binding-extraction/js-identifiers.js +168 -0
- package/dist/binding-extraction/js-identifiers.js.map +1 -1
- package/dist/binding-extraction/python-identifiers.d.ts +5 -0
- package/dist/binding-extraction/python-identifiers.d.ts.map +1 -1
- package/dist/binding-extraction/python-identifiers.js +76 -7
- package/dist/binding-extraction/python-identifiers.js.map +1 -1
- package/dist/file-sync-vite-plugin.d.ts.map +1 -1
- package/dist/file-sync-vite-plugin.js +73 -3
- package/dist/file-sync-vite-plugin.js.map +1 -1
- package/dist/file-system-manager.d.ts.map +1 -1
- package/dist/file-system-manager.js +6 -4
- package/dist/file-system-manager.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lock-service/activity-tracker.d.ts +14 -2
- package/dist/lock-service/activity-tracker.d.ts.map +1 -1
- package/dist/lock-service/activity-tracker.js +43 -6
- package/dist/lock-service/activity-tracker.js.map +1 -1
- package/dist/lock-service/index.d.ts +13 -2
- package/dist/lock-service/index.d.ts.map +1 -1
- package/dist/lock-service/index.js +130 -44
- package/dist/lock-service/index.js.map +1 -1
- package/dist/parsing/jsx.d.ts.map +1 -1
- package/dist/parsing/jsx.js +78 -66
- package/dist/parsing/jsx.js.map +1 -1
- package/dist/socket-manager.js +1 -1
- package/dist/socket-manager.js.map +1 -1
- package/dist/sync-service/list-dir.d.ts.map +1 -1
- package/dist/sync-service/list-dir.js +41 -18
- package/dist/sync-service/list-dir.js.map +1 -1
- package/dist/vite-plugin-yaml-types.d.ts.map +1 -1
- package/dist/vite-plugin-yaml-types.js +2 -4
- package/dist/vite-plugin-yaml-types.js.map +1 -1
- package/package.json +7 -7
- package/dist/ai-service/agent/subagents/apis/api-executor.d.ts.map +0 -1
- package/dist/ai-service/agent/subagents/apis/api-executor.js.map +0 -1
- package/dist/ai-service/agent/subagents/apis/context.d.ts +0 -12
- package/dist/ai-service/agent/subagents/apis/context.d.ts.map +0 -1
- package/dist/ai-service/agent/subagents/apis/context.js +0 -18
- package/dist/ai-service/agent/subagents/apis/context.js.map +0 -1
- package/dist/ai-service/agent/subagents/apis/generate-api-source.d.ts +0 -40
- package/dist/ai-service/agent/subagents/apis/generate-api-source.d.ts.map +0 -1
- package/dist/ai-service/agent/subagents/apis/generate-api-source.js +0 -516
- package/dist/ai-service/agent/subagents/apis/generate-api-source.js.map +0 -1
- package/dist/ai-service/agent/subagents/apis/state.d.ts +0 -49
- package/dist/ai-service/agent/subagents/apis/state.d.ts.map +0 -1
- package/dist/ai-service/agent/subagents/apis/state.js +0 -25
- package/dist/ai-service/agent/subagents/apis/state.js.map +0 -1
- package/dist/ai-service/agent/subagents/apis/system-prompt.d.ts +0 -3
- package/dist/ai-service/agent/subagents/apis/system-prompt.d.ts.map +0 -1
- package/dist/ai-service/agent/subagents/apis/system-prompt.js +0 -1704
- package/dist/ai-service/agent/subagents/apis/system-prompt.js.map +0 -1
- package/dist/ai-service/agent/tools/apis/finalize-api.d.ts +0 -11
- package/dist/ai-service/agent/tools/apis/finalize-api.d.ts.map +0 -1
- package/dist/ai-service/agent/tools/apis/finalize-api.js +0 -133
- package/dist/ai-service/agent/tools/apis/finalize-api.js.map +0 -1
- package/dist/ai-service/llm/middleware/retry.d.ts +0 -112
- package/dist/ai-service/llm/middleware/retry.d.ts.map +0 -1
- package/dist/ai-service/llm/middleware/retry.js +0 -239
- package/dist/ai-service/llm/middleware/retry.js.map +0 -1
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry middleware for StreamText operations.
|
|
3
|
+
*
|
|
4
|
+
* This middleware wraps entire streamText() calls to handle failures during
|
|
5
|
+
* stream consumption. When a stream fails mid-consumption (e.g., network timeout),
|
|
6
|
+
* this middleware retries the entire streamText call with accumulated messages
|
|
7
|
+
* from successful steps preserved via Context.
|
|
8
|
+
*
|
|
9
|
+
* **Two-phase retry architecture:**
|
|
10
|
+
* 1. **Initial call retry**: Retries errors when calling streamText() to get metadata
|
|
11
|
+
* 2. **Stream consumption retry**: Retries mid-stream errors during stream consumption
|
|
12
|
+
*
|
|
13
|
+
* **Separate retry budgets:**
|
|
14
|
+
* Each phase has its own independent retry budget. For example, with maxRetries: 3:
|
|
15
|
+
* - Phase 1 can retry up to 3 times (4 total attempts to get initial metadata)
|
|
16
|
+
* - Phase 2 can retry up to 3 times (4 total attempts to consume stream)
|
|
17
|
+
* - Maximum total attempts: 4 (phase 1) + 4 (phase 2) = 8
|
|
18
|
+
*
|
|
19
|
+
* This design ensures that failures in one phase don't prevent retries in the other phase.
|
|
20
|
+
*
|
|
21
|
+
* ## Why at StreamText Level?
|
|
22
|
+
*
|
|
23
|
+
* Retrying at the streamText level (vs model.doStream level) ensures:
|
|
24
|
+
* 1. **Fresh Vercel SDK state**: Each retry gets a new eventProcessor with no
|
|
25
|
+
* partial chunk pollution from failed attempts
|
|
26
|
+
* 2. **Correct message sequences**: No orphaned content IDs or invalid message structures
|
|
27
|
+
* 3. **Natural continuation**: Vercel SDK's built-in logic handles multi-step resumption
|
|
28
|
+
*
|
|
29
|
+
* ## How It Works with Context
|
|
30
|
+
*
|
|
31
|
+
* The Context system provides the accumulated messages for retry:
|
|
32
|
+
* - Step 1 succeeds → Context.endStep() records messages
|
|
33
|
+
* - Step 2 fails → No endStep() call, empty step array remains
|
|
34
|
+
* - Retry → Context.getMessages() provides Step 1's messages
|
|
35
|
+
* - Fresh streamText() call receives those messages and continues from Step 2 Context.startStep() is idempotent → reuses empty step array
|
|
36
|
+
*
|
|
37
|
+
* ## Multi-Step Scenarios
|
|
38
|
+
*
|
|
39
|
+
* For multi-step flows (e.g., tool calling):
|
|
40
|
+
* - Step 1 (tool call) succeeds
|
|
41
|
+
* - Step 2 (continuation) fails
|
|
42
|
+
* - Retry receives Step 1's messages (including tool-results)
|
|
43
|
+
* - Vercel SDK sees tool-results and continues to Step 2
|
|
44
|
+
* - Does NOT re-execute Step 1's tools (already have results)
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* const middleware = createStreamRetryMiddleware({
|
|
49
|
+
* maxRetries: 3,
|
|
50
|
+
* maxTotalRetryTimeMs: 120000,
|
|
51
|
+
* isRetryable: (error) => isNetworkError(error)
|
|
52
|
+
* });
|
|
53
|
+
*
|
|
54
|
+
* const provider = applyMiddleware(baseProvider, middleware);
|
|
55
|
+
* const result = await provider.streamText({ model, messages, tools });
|
|
56
|
+
* // Automatically retries on stream consumption failures
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
import { type Logger } from "../../../../util/logger.js";
|
|
60
|
+
import { type BackoffStrategy } from "../../../util/backoff-strategy.js";
|
|
61
|
+
import type { StreamTextMiddleware } from "../middleware.js";
|
|
62
|
+
export interface StreamRetryOptions {
|
|
63
|
+
/**
|
|
64
|
+
* Maximum number of retry attempts per phase (not including the initial attempt).
|
|
65
|
+
* Each phase (initial call, stream consumption) gets its own retry budget.
|
|
66
|
+
* Default: Infinity (unlimited)
|
|
67
|
+
*/
|
|
68
|
+
maxRetries?: number;
|
|
69
|
+
/**
|
|
70
|
+
* Custom backoff strategy for calculating retry delays.
|
|
71
|
+
* If not provided, uses ExponentialBackoff.
|
|
72
|
+
*/
|
|
73
|
+
backoffStrategy?: BackoffStrategy;
|
|
74
|
+
/**
|
|
75
|
+
* Initial delay in milliseconds before the first retry.
|
|
76
|
+
* Default: 500 (0.5 seconds)
|
|
77
|
+
*/
|
|
78
|
+
initialDelayMs?: number;
|
|
79
|
+
/**
|
|
80
|
+
* Maximum delay in milliseconds for exponential backoff.
|
|
81
|
+
* Default: 5000 (5 seconds)
|
|
82
|
+
*/
|
|
83
|
+
maxDelayMs?: number;
|
|
84
|
+
/**
|
|
85
|
+
* Backoff multiplier for exponential backoff.
|
|
86
|
+
* Default: 2
|
|
87
|
+
*/
|
|
88
|
+
backoffMultiplier?: number;
|
|
89
|
+
/**
|
|
90
|
+
* Maximum total time in milliseconds for all retry attempts.
|
|
91
|
+
* Default: undefined (no time limit)
|
|
92
|
+
*/
|
|
93
|
+
maxTotalRetryTimeMs?: number;
|
|
94
|
+
/**
|
|
95
|
+
* Function to determine if an error is retryable.
|
|
96
|
+
* Default: checks for timeout and connection errors
|
|
97
|
+
*/
|
|
98
|
+
isRetryable?: (error: unknown) => boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Callback invoked before each retry attempt.
|
|
101
|
+
*/
|
|
102
|
+
onRetry?: (error: unknown, attempt: number, delayMs: number, totalRetryTimeMs: number) => void | Promise<void>;
|
|
103
|
+
/**
|
|
104
|
+
* Optional abort signal to cancel retry attempts.
|
|
105
|
+
* When the signal is aborted, no further retries will be attempted.
|
|
106
|
+
*/
|
|
107
|
+
abortSignal?: AbortSignal;
|
|
108
|
+
/** Logger instance for retry operations */
|
|
109
|
+
logger?: Logger;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Creates a middleware that retries streamText calls on failure.
|
|
113
|
+
*
|
|
114
|
+
* This middleware wraps the entire streamText operation, catching errors during
|
|
115
|
+
* both the initial call and stream consumption. Retries with accumulated messages from Context.
|
|
116
|
+
*
|
|
117
|
+
* @param options - Configuration for retry behavior
|
|
118
|
+
* @returns A StreamTextMiddleware
|
|
119
|
+
*/
|
|
120
|
+
export declare function createStreamRetryMiddleware(options?: StreamRetryOptions): StreamTextMiddleware;
|
|
121
|
+
//# sourceMappingURL=stream-retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-retry.d.ts","sourceRoot":"","sources":["../../../../../src/ai-service/llm/interaction/middlewares/stream-retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AAEH,OAAO,EACL,KAAK,MAAM,EAGZ,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,mCAAmC,CAAC;AAI3C,OAAO,KAAK,EACV,oBAAoB,EAIrB,MAAM,kBAAkB,CAAC;AAG1B,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;IAElC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;IAE1C;;OAEG;IACH,OAAO,CAAC,EAAE,CACR,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,KACrB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1B;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAE1B,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,GAAE,kBAAuB,GAC/B,oBAAoB,CAgHtB"}
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry middleware for StreamText operations.
|
|
3
|
+
*
|
|
4
|
+
* This middleware wraps entire streamText() calls to handle failures during
|
|
5
|
+
* stream consumption. When a stream fails mid-consumption (e.g., network timeout),
|
|
6
|
+
* this middleware retries the entire streamText call with accumulated messages
|
|
7
|
+
* from successful steps preserved via Context.
|
|
8
|
+
*
|
|
9
|
+
* **Two-phase retry architecture:**
|
|
10
|
+
* 1. **Initial call retry**: Retries errors when calling streamText() to get metadata
|
|
11
|
+
* 2. **Stream consumption retry**: Retries mid-stream errors during stream consumption
|
|
12
|
+
*
|
|
13
|
+
* **Separate retry budgets:**
|
|
14
|
+
* Each phase has its own independent retry budget. For example, with maxRetries: 3:
|
|
15
|
+
* - Phase 1 can retry up to 3 times (4 total attempts to get initial metadata)
|
|
16
|
+
* - Phase 2 can retry up to 3 times (4 total attempts to consume stream)
|
|
17
|
+
* - Maximum total attempts: 4 (phase 1) + 4 (phase 2) = 8
|
|
18
|
+
*
|
|
19
|
+
* This design ensures that failures in one phase don't prevent retries in the other phase.
|
|
20
|
+
*
|
|
21
|
+
* ## Why at StreamText Level?
|
|
22
|
+
*
|
|
23
|
+
* Retrying at the streamText level (vs model.doStream level) ensures:
|
|
24
|
+
* 1. **Fresh Vercel SDK state**: Each retry gets a new eventProcessor with no
|
|
25
|
+
* partial chunk pollution from failed attempts
|
|
26
|
+
* 2. **Correct message sequences**: No orphaned content IDs or invalid message structures
|
|
27
|
+
* 3. **Natural continuation**: Vercel SDK's built-in logic handles multi-step resumption
|
|
28
|
+
*
|
|
29
|
+
* ## How It Works with Context
|
|
30
|
+
*
|
|
31
|
+
* The Context system provides the accumulated messages for retry:
|
|
32
|
+
* - Step 1 succeeds → Context.endStep() records messages
|
|
33
|
+
* - Step 2 fails → No endStep() call, empty step array remains
|
|
34
|
+
* - Retry → Context.getMessages() provides Step 1's messages
|
|
35
|
+
* - Fresh streamText() call receives those messages and continues from Step 2 Context.startStep() is idempotent → reuses empty step array
|
|
36
|
+
*
|
|
37
|
+
* ## Multi-Step Scenarios
|
|
38
|
+
*
|
|
39
|
+
* For multi-step flows (e.g., tool calling):
|
|
40
|
+
* - Step 1 (tool call) succeeds
|
|
41
|
+
* - Step 2 (continuation) fails
|
|
42
|
+
* - Retry receives Step 1's messages (including tool-results)
|
|
43
|
+
* - Vercel SDK sees tool-results and continues to Step 2
|
|
44
|
+
* - Does NOT re-execute Step 1's tools (already have results)
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* const middleware = createStreamRetryMiddleware({
|
|
49
|
+
* maxRetries: 3,
|
|
50
|
+
* maxTotalRetryTimeMs: 120000,
|
|
51
|
+
* isRetryable: (error) => isNetworkError(error)
|
|
52
|
+
* });
|
|
53
|
+
*
|
|
54
|
+
* const provider = applyMiddleware(baseProvider, middleware);
|
|
55
|
+
* const result = await provider.streamText({ model, messages, tools });
|
|
56
|
+
* // Automatically retries on stream consumption failures
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
import { getErrorMeta, getPrefixedLogger, } from "../../../../util/logger.js";
|
|
60
|
+
import { ExponentialBackoff, } from "../../../util/backoff-strategy.js";
|
|
61
|
+
import { LLMProviderError } from "../../error.js";
|
|
62
|
+
import { isProviderErrorRetryable } from "../../util/provider-errors.js";
|
|
63
|
+
/**
|
|
64
|
+
* Creates a middleware that retries streamText calls on failure.
|
|
65
|
+
*
|
|
66
|
+
* This middleware wraps the entire streamText operation, catching errors during
|
|
67
|
+
* both the initial call and stream consumption. Retries with accumulated messages from Context.
|
|
68
|
+
*
|
|
69
|
+
* @param options - Configuration for retry behavior
|
|
70
|
+
* @returns A StreamTextMiddleware
|
|
71
|
+
*/
|
|
72
|
+
export function createStreamRetryMiddleware(options = {}) {
|
|
73
|
+
const { maxRetries = Infinity, initialDelayMs = 500, maxDelayMs = 5000, backoffMultiplier = 2, maxTotalRetryTimeMs, isRetryable = isProviderErrorRetryable, onRetry, abortSignal, logger = getPrefixedLogger("[StreamRetry]"), } = options;
|
|
74
|
+
const backoffStrategy = options.backoffStrategy ??
|
|
75
|
+
new ExponentialBackoff({
|
|
76
|
+
initialDelayMs,
|
|
77
|
+
maxDelayMs,
|
|
78
|
+
backoffMultiplier,
|
|
79
|
+
});
|
|
80
|
+
const maxRetriesDisplay = maxRetries === Infinity ? "unlimited" : String(maxRetries);
|
|
81
|
+
return {
|
|
82
|
+
wrap(provider) {
|
|
83
|
+
return {
|
|
84
|
+
async streamText(streamOptions) {
|
|
85
|
+
// Phase 1: Retry initial streamText call
|
|
86
|
+
let httpAttempt = 0;
|
|
87
|
+
let totalRetryTime = 0;
|
|
88
|
+
const overallStartTime = Date.now();
|
|
89
|
+
let initialResult;
|
|
90
|
+
while (true) {
|
|
91
|
+
try {
|
|
92
|
+
initialResult = await provider.streamText(streamOptions);
|
|
93
|
+
break; // Success!
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
httpAttempt++;
|
|
97
|
+
const error = wrapError(err);
|
|
98
|
+
const delay = await handleRetryAttempt(error, httpAttempt, totalRetryTime, {
|
|
99
|
+
maxRetries,
|
|
100
|
+
maxRetriesDisplay,
|
|
101
|
+
maxTotalRetryTimeMs,
|
|
102
|
+
overallStartTime,
|
|
103
|
+
backoffStrategy,
|
|
104
|
+
isRetryable,
|
|
105
|
+
onRetry,
|
|
106
|
+
abortSignal,
|
|
107
|
+
logger,
|
|
108
|
+
errorContext: "HTTP error",
|
|
109
|
+
});
|
|
110
|
+
totalRetryTime += delay;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// Phase 2: Wrap streams to handle consumption errors
|
|
114
|
+
const retryingFullStream = createRetryingAsyncIterable(provider, streamOptions, () => initialResult.fullStream, {
|
|
115
|
+
maxRetries,
|
|
116
|
+
maxRetriesDisplay,
|
|
117
|
+
maxTotalRetryTimeMs,
|
|
118
|
+
overallStartTime,
|
|
119
|
+
backoffStrategy,
|
|
120
|
+
isRetryable,
|
|
121
|
+
onRetry,
|
|
122
|
+
abortSignal,
|
|
123
|
+
logger,
|
|
124
|
+
});
|
|
125
|
+
const retryingTextStream = createRetryingAsyncIterable(provider, streamOptions, () => initialResult.textStream, {
|
|
126
|
+
maxRetries,
|
|
127
|
+
maxRetriesDisplay,
|
|
128
|
+
maxTotalRetryTimeMs,
|
|
129
|
+
overallStartTime,
|
|
130
|
+
backoffStrategy,
|
|
131
|
+
isRetryable,
|
|
132
|
+
onRetry,
|
|
133
|
+
abortSignal,
|
|
134
|
+
logger,
|
|
135
|
+
});
|
|
136
|
+
// Return result with retrying streams
|
|
137
|
+
return {
|
|
138
|
+
...initialResult,
|
|
139
|
+
fullStream: retryingFullStream,
|
|
140
|
+
textStream: retryingTextStream,
|
|
141
|
+
};
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Creates an AsyncIterableStream that retries on consumption errors.
|
|
149
|
+
*/
|
|
150
|
+
function createRetryingAsyncIterable(provider, streamOptions, getInitialStream, config) {
|
|
151
|
+
// Create an AsyncIterable that implements the retry logic
|
|
152
|
+
const retryingIterable = {
|
|
153
|
+
async *[Symbol.asyncIterator]() {
|
|
154
|
+
let consumptionAttempt = 0;
|
|
155
|
+
let isFirstAttempt = true;
|
|
156
|
+
while (true) {
|
|
157
|
+
try {
|
|
158
|
+
// Get stream for current attempt
|
|
159
|
+
const iterator = isFirstAttempt
|
|
160
|
+
? getInitialStream()[Symbol.asyncIterator]()
|
|
161
|
+
: await (async () => {
|
|
162
|
+
const streamResult = await provider.streamText(streamOptions);
|
|
163
|
+
// Use fullStream for retries (contains all chunk types)
|
|
164
|
+
return streamResult.fullStream[Symbol.asyncIterator]();
|
|
165
|
+
})();
|
|
166
|
+
isFirstAttempt = false;
|
|
167
|
+
// Iterate through chunks
|
|
168
|
+
while (true) {
|
|
169
|
+
const { value: chunk, done } = await iterator.next();
|
|
170
|
+
if (done) {
|
|
171
|
+
return; // Success!
|
|
172
|
+
}
|
|
173
|
+
// Check for error chunks
|
|
174
|
+
if (typeof chunk === "object" &&
|
|
175
|
+
chunk !== null &&
|
|
176
|
+
"type" in chunk &&
|
|
177
|
+
chunk.type === "error") {
|
|
178
|
+
throw wrapError(chunk.error);
|
|
179
|
+
}
|
|
180
|
+
// Normal chunk - yield it
|
|
181
|
+
yield chunk;
|
|
182
|
+
// Reset consumption attempt on successful chunk
|
|
183
|
+
consumptionAttempt = 0;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
catch (err) {
|
|
187
|
+
const error = wrapError(err);
|
|
188
|
+
// Handle error - check if we should retry
|
|
189
|
+
consumptionAttempt++;
|
|
190
|
+
const totalElapsed = Date.now() - config.overallStartTime;
|
|
191
|
+
try {
|
|
192
|
+
await handleRetryAttempt(error, consumptionAttempt, totalElapsed, {
|
|
193
|
+
...config,
|
|
194
|
+
errorContext: "Stream error",
|
|
195
|
+
});
|
|
196
|
+
// Loop continues - will try again with fresh stream
|
|
197
|
+
}
|
|
198
|
+
catch (finalError) {
|
|
199
|
+
// Exhausted or non-retryable - yield error and exit
|
|
200
|
+
yield {
|
|
201
|
+
type: "error",
|
|
202
|
+
error: finalError,
|
|
203
|
+
};
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
// Convert AsyncIterable to ReadableStream
|
|
211
|
+
const readableStream = new ReadableStream({
|
|
212
|
+
async start(controller) {
|
|
213
|
+
try {
|
|
214
|
+
for await (const chunk of retryingIterable) {
|
|
215
|
+
controller.enqueue(chunk);
|
|
216
|
+
}
|
|
217
|
+
controller.close();
|
|
218
|
+
}
|
|
219
|
+
catch (error) {
|
|
220
|
+
controller.error(error);
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
// Return as AsyncIterableStream (ReadableStream with async iteration support)
|
|
225
|
+
return readableStream;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Wraps an error in LLMProviderError if it isn't already.
|
|
229
|
+
*/
|
|
230
|
+
function wrapError(err, provider) {
|
|
231
|
+
if (err instanceof LLMProviderError) {
|
|
232
|
+
return err;
|
|
233
|
+
}
|
|
234
|
+
// Provider is optional here since we may not know it at this level
|
|
235
|
+
return new LLMProviderError({
|
|
236
|
+
provider: provider,
|
|
237
|
+
cause: err,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Checks if retry is allowed and executes retry logic.
|
|
242
|
+
* Returns the delay in milliseconds if a retry should be attempted.
|
|
243
|
+
* Throws if no retry is possible.
|
|
244
|
+
*/
|
|
245
|
+
async function handleRetryAttempt(error, attempt, totalRetryTime, config) {
|
|
246
|
+
// Check abort signal
|
|
247
|
+
if (config.abortSignal?.aborted) {
|
|
248
|
+
const abortError = new LLMProviderError({
|
|
249
|
+
provider: error.provider,
|
|
250
|
+
message: "Request aborted",
|
|
251
|
+
type: "aborted",
|
|
252
|
+
isRetryable: false,
|
|
253
|
+
});
|
|
254
|
+
config.logger.info("Request aborted, stopping retry attempts");
|
|
255
|
+
throw abortError;
|
|
256
|
+
}
|
|
257
|
+
// Check retry conditions
|
|
258
|
+
const withinMaxRetries = attempt <= config.maxRetries;
|
|
259
|
+
const withinTimeLimit = !config.maxTotalRetryTimeMs ||
|
|
260
|
+
Date.now() - config.overallStartTime < config.maxTotalRetryTimeMs;
|
|
261
|
+
const errorIsRetryable = config.isRetryable(error);
|
|
262
|
+
const canRetry = errorIsRetryable && withinMaxRetries && withinTimeLimit;
|
|
263
|
+
if (!canRetry) {
|
|
264
|
+
if (errorIsRetryable) {
|
|
265
|
+
const reason = !withinMaxRetries
|
|
266
|
+
? `after ${config.maxRetriesDisplay} retries`
|
|
267
|
+
: `total retry time exceeded ${config.maxTotalRetryTimeMs}ms`;
|
|
268
|
+
config.logger.error(`Exceeded retry limits: ${reason}`, getErrorMeta(error.cause));
|
|
269
|
+
throw new LLMProviderError({
|
|
270
|
+
provider: error.provider,
|
|
271
|
+
message: `${config.errorContext} ${reason}`,
|
|
272
|
+
type: "retries_exhausted",
|
|
273
|
+
isRetryable: false,
|
|
274
|
+
cause: error,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
config.logger.error("Non-retryable error encountered", getErrorMeta(error.cause));
|
|
278
|
+
throw error;
|
|
279
|
+
}
|
|
280
|
+
// Calculate backoff delay
|
|
281
|
+
const delay = config.backoffStrategy.getNextDelay(attempt);
|
|
282
|
+
config.logger.warn(`${config.errorContext} (type: ${error.type}). Attempt ${attempt}/${config.maxRetriesDisplay}. Retrying in ${delay}ms...`);
|
|
283
|
+
// Call onRetry callback
|
|
284
|
+
if (config.onRetry) {
|
|
285
|
+
await config.onRetry(error, attempt, delay, totalRetryTime);
|
|
286
|
+
}
|
|
287
|
+
// Wait before retry
|
|
288
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
289
|
+
return delay;
|
|
290
|
+
}
|
|
291
|
+
//# sourceMappingURL=stream-retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-retry.js","sourceRoot":"","sources":["../../../../../src/ai-service/llm/interaction/middlewares/stream-retry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* High-level provider interface for LLM streaming interactions.
|
|
3
|
+
*
|
|
4
|
+
* This interface defines a complete, SDK-agnostic contract for multi-step
|
|
5
|
+
* LLM streaming, including all lifecycle hooks. Concrete implementations
|
|
6
|
+
* (adapters) bridge this interface to specific SDKs (Vercel AI, Anthropic, etc.).
|
|
7
|
+
*
|
|
8
|
+
* Key features:
|
|
9
|
+
* - Complete lifecycle: prepareStep → onChunk → onStepFinish → onFinish → onFinally
|
|
10
|
+
* - onFinally: Guaranteed to run after stream consumption (our addition!)
|
|
11
|
+
* - SDK-agnostic: Could be implemented with any LLM SDK
|
|
12
|
+
* - Testable: Easy to mock for testing
|
|
13
|
+
*/
|
|
14
|
+
import type { Tool } from "../../agent/tools2/types.js";
|
|
15
|
+
import type { StopCondition } from "../../util/stop-condition.js";
|
|
16
|
+
import type { ProviderOptions } from "@ai-sdk/provider-utils";
|
|
17
|
+
import type { LanguageModel, TextStreamPart, LanguageModelUsage, ModelMessage, UserModelMessage } from "ai";
|
|
18
|
+
/**
|
|
19
|
+
* Provider interface for LLM streaming interactions.
|
|
20
|
+
*
|
|
21
|
+
* Implementations of this interface wrap specific SDKs and provide
|
|
22
|
+
* a consistent, high-level API with complete lifecycle management.
|
|
23
|
+
*/
|
|
24
|
+
export interface StreamTextProvider {
|
|
25
|
+
/**
|
|
26
|
+
* Streams text from an LLM with multi-step tool calling support.
|
|
27
|
+
*
|
|
28
|
+
* @param options - Configuration and lifecycle hooks
|
|
29
|
+
* @returns Promise resolving to stream result with text/full streams
|
|
30
|
+
*/
|
|
31
|
+
streamText<TOOLS extends Record<string, Tool> = Record<string, Tool>>(options: StreamTextOptions<TOOLS>): Promise<StreamTextResult<TOOLS>>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Options for a streamText call.
|
|
35
|
+
*
|
|
36
|
+
* Includes model configuration, messages, tools, and comprehensive
|
|
37
|
+
* lifecycle hooks including onFinally (runs after stream consumption).
|
|
38
|
+
*/
|
|
39
|
+
export interface StreamTextOptions<TOOLS extends Record<string, Tool>> {
|
|
40
|
+
/** The language model to use */
|
|
41
|
+
model: LanguageModel;
|
|
42
|
+
/**
|
|
43
|
+
* Conversation messages.
|
|
44
|
+
* Note: When using context middleware, this will be populated automatically
|
|
45
|
+
* from context history. You typically provide user instead.
|
|
46
|
+
*/
|
|
47
|
+
messages?: ModelMessage[];
|
|
48
|
+
/**
|
|
49
|
+
* User message for this interaction.
|
|
50
|
+
* When using context middleware, this is added to the conversation history
|
|
51
|
+
* and messages are populated automatically from context.
|
|
52
|
+
*/
|
|
53
|
+
user?: UserModelMessage;
|
|
54
|
+
/** Available tools the model can call */
|
|
55
|
+
tools?: TOOLS;
|
|
56
|
+
/**
|
|
57
|
+
* System prompt.
|
|
58
|
+
* When using context middleware, this is set on the context.
|
|
59
|
+
*/
|
|
60
|
+
system?: string;
|
|
61
|
+
/** Maximum number of automatic tool call steps */
|
|
62
|
+
maxSteps?: number;
|
|
63
|
+
/** Abort signal for cancellation */
|
|
64
|
+
abortSignal?: AbortSignal;
|
|
65
|
+
/** Custom headers for the request */
|
|
66
|
+
headers?: Record<string, string | undefined>;
|
|
67
|
+
/** Provider-specific options */
|
|
68
|
+
providerOptions?: ProviderOptions;
|
|
69
|
+
/**
|
|
70
|
+
* Vercel AI SDK specific: Condition to stop generation early.
|
|
71
|
+
* Pass through to the underlying SDK.
|
|
72
|
+
*/
|
|
73
|
+
stopWhen?: StopCondition<any> | StopCondition<any>[];
|
|
74
|
+
/**
|
|
75
|
+
* Vercel AI SDK specific: Transformation stream for the output.
|
|
76
|
+
* Pass through to the underlying SDK.
|
|
77
|
+
*/
|
|
78
|
+
experimental_transform?: any;
|
|
79
|
+
/**
|
|
80
|
+
* Called before each LLM step.
|
|
81
|
+
* Can transform the step parameters before execution.
|
|
82
|
+
*/
|
|
83
|
+
prepareStep?: (step: StepParameters) => Promise<StepParameters> | StepParameters;
|
|
84
|
+
/**
|
|
85
|
+
* Called for each chunk in the stream during generation.
|
|
86
|
+
*/
|
|
87
|
+
onChunk?: (event: {
|
|
88
|
+
chunk: StreamChunk;
|
|
89
|
+
}) => Promise<void> | void;
|
|
90
|
+
/**
|
|
91
|
+
* Called after each step completes (after tool execution).
|
|
92
|
+
*/
|
|
93
|
+
onStepFinish?: (step: StepResult) => Promise<void> | void;
|
|
94
|
+
/**
|
|
95
|
+
* Called when the entire multi-step interaction finishes.
|
|
96
|
+
* This fires after generation completes, before stream consumption.
|
|
97
|
+
*/
|
|
98
|
+
onFinish?: (result: FinalResult) => Promise<void> | void;
|
|
99
|
+
/**
|
|
100
|
+
* Called after stream consumption completes.
|
|
101
|
+
*
|
|
102
|
+
* This is the key lifecycle hook for cleanup operations:
|
|
103
|
+
* - Releasing locks (context handles)
|
|
104
|
+
* - Finishing tracing spans
|
|
105
|
+
* - Closing database connections
|
|
106
|
+
* - Saving final artifacts
|
|
107
|
+
*
|
|
108
|
+
* Guarantees:
|
|
109
|
+
* - Runs exactly once, even if multiple stream accessors are used
|
|
110
|
+
* - Runs after the stream is fully consumed OR abandoned
|
|
111
|
+
* - Runs in error cases as well (usage may be partial)
|
|
112
|
+
* - Idempotent and safe to call multiple times
|
|
113
|
+
*
|
|
114
|
+
*/
|
|
115
|
+
onFinally?: () => Promise<void> | void;
|
|
116
|
+
/**
|
|
117
|
+
* Called if an error occurs during generation or consumption.
|
|
118
|
+
*/
|
|
119
|
+
onError?: (error: Error) => Promise<void> | void;
|
|
120
|
+
/**
|
|
121
|
+
* Called if the operation is aborted via the abortSignal.
|
|
122
|
+
*/
|
|
123
|
+
onAbort?: () => Promise<void> | void;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Parameters for a single LLM step.
|
|
127
|
+
*/
|
|
128
|
+
export interface StepParameters {
|
|
129
|
+
messages: ModelMessage[];
|
|
130
|
+
stepNumber: number;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* A chunk from the streaming response.
|
|
134
|
+
* This is a direct re-export of Vercel AI SDK's TextStreamPart.
|
|
135
|
+
*/
|
|
136
|
+
export type StreamChunk = TextStreamPart<Record<string, Tool>>;
|
|
137
|
+
import type { StepResult as VercelStepResult } from "ai";
|
|
138
|
+
/**
|
|
139
|
+
* Result of a single LLM step.
|
|
140
|
+
* Re-exported from Vercel AI SDK to avoid type incompatibilities.
|
|
141
|
+
*/
|
|
142
|
+
export type StepResult = VercelStepResult<any>;
|
|
143
|
+
/**
|
|
144
|
+
* Final result of the entire multi-step interaction.
|
|
145
|
+
* This is the result passed to onFinish callback.
|
|
146
|
+
* Re-exported from Vercel AI SDK's internal type.
|
|
147
|
+
*/
|
|
148
|
+
export type FinalResult = StepResult & {
|
|
149
|
+
readonly steps: StepResult[];
|
|
150
|
+
readonly totalUsage: LanguageModelUsage;
|
|
151
|
+
};
|
|
152
|
+
import type { StreamTextResult as VercelStreamTextResult } from "ai";
|
|
153
|
+
/**
|
|
154
|
+
* Result of a streamText call.
|
|
155
|
+
* Re-exported from Vercel AI SDK with default for PARTIAL_OUTPUT.
|
|
156
|
+
*/
|
|
157
|
+
export type StreamTextResult<TOOLS extends Record<string, Tool> = Record<string, Tool>> = VercelStreamTextResult<TOOLS, any>;
|
|
158
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../../src/ai-service/llm/interaction/provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* High-level provider interface for LLM streaming interactions.
|
|
3
|
+
*
|
|
4
|
+
* This interface defines a complete, SDK-agnostic contract for multi-step
|
|
5
|
+
* LLM streaming, including all lifecycle hooks. Concrete implementations
|
|
6
|
+
* (adapters) bridge this interface to specific SDKs (Vercel AI, Anthropic, etc.).
|
|
7
|
+
*
|
|
8
|
+
* Key features:
|
|
9
|
+
* - Complete lifecycle: prepareStep → onChunk → onStepFinish → onFinish → onFinally
|
|
10
|
+
* - onFinally: Guaranteed to run after stream consumption (our addition!)
|
|
11
|
+
* - SDK-agnostic: Could be implemented with any LLM SDK
|
|
12
|
+
* - Testable: Easy to mock for testing
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../../src/ai-service/llm/interaction/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stream lifecycle management utilities.
|
|
3
|
+
*
|
|
4
|
+
* Provides utilities for wrapping streams with lifecycle hooks, particularly
|
|
5
|
+
* `onFinally` which runs after stream consumption completes.
|
|
6
|
+
*
|
|
7
|
+
* Key challenge: The `streamText()` function returns immediately, but the
|
|
8
|
+
* streams are consumed asynchronously later. We need to track when consumption
|
|
9
|
+
* actually completes to run cleanup logic.
|
|
10
|
+
*
|
|
11
|
+
* Solution: Wrap streams with `TransformStream` that tracks consumption via
|
|
12
|
+
* the `flush()` method, which runs when the input stream closes.
|
|
13
|
+
*/
|
|
14
|
+
import type { StreamTextResult } from "./provider.js";
|
|
15
|
+
import type { Tool } from "../../agent/tools2/types.js";
|
|
16
|
+
/**
|
|
17
|
+
* Wraps a StreamTextResult to add onFinally lifecycle hook.
|
|
18
|
+
*
|
|
19
|
+
* The onFinally callback runs after stream consumption completes, handling:
|
|
20
|
+
* - Normal completion (stream exhausted)
|
|
21
|
+
* - Errors during consumption
|
|
22
|
+
* - Stream cancellation/abandonment
|
|
23
|
+
*
|
|
24
|
+
* Guarantees:
|
|
25
|
+
* - Runs exactly once, even if multiple stream accessors are used
|
|
26
|
+
* - Idempotent (safe to call multiple times)
|
|
27
|
+
* - Works with all consumption patterns (iteration, promises, piping)
|
|
28
|
+
*
|
|
29
|
+
* @param result - The stream result to wrap
|
|
30
|
+
* @param onFinally - Callback to run after consumption
|
|
31
|
+
* @returns Wrapped result with lifecycle tracking
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* const result = await streamText({ model, messages });
|
|
36
|
+
* const wrapped = withStreamLifecycle(result, async () => {
|
|
37
|
+
* console.log('Stream consumed!');
|
|
38
|
+
* await cleanup();
|
|
39
|
+
* });
|
|
40
|
+
*
|
|
41
|
+
* for await (const text of wrapped.textStream) {
|
|
42
|
+
* console.log(text);
|
|
43
|
+
* }
|
|
44
|
+
* // onFinally runs here ^
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare function withStreamLifecycle<TOOLS extends Record<string, Tool> = Record<string, Tool>>(result: StreamTextResult<TOOLS>, onFinally: () => Promise<void> | void): StreamTextResult<TOOLS>;
|
|
48
|
+
//# sourceMappingURL=stream-lifecycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-lifecycle.d.ts","sourceRoot":"","sources":["../../../../src/ai-service/llm/interaction/stream-lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAC;AAGxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,EAEzD,MAAM,EAAE,gBAAgB,CAAC,KAAK,CAAC,EAC/B,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GACpC,gBAAgB,CAAC,KAAK,CAAC,CAmCzB"}
|