@midscene/core 1.13.1 → 1.13.2-beta-20260923031905.0
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/es/agent/task-builder.mjs +1 -1
- package/dist/es/agent/task-builder.mjs.map +1 -1
- package/dist/es/agent/tasks.mjs +4 -4
- package/dist/es/agent/tasks.mjs.map +1 -1
- package/dist/es/agent/utils.mjs +1 -1
- package/dist/es/ai-model/connectivity/run-connectivity-test.mjs +2 -5
- package/dist/es/ai-model/connectivity/run-connectivity-test.mjs.map +1 -1
- package/dist/es/ai-model/model-adapter/chat-completion.mjs +8 -11
- package/dist/es/ai-model/model-adapter/chat-completion.mjs.map +1 -1
- package/dist/es/ai-model/model-adapter/resolve.mjs +10 -0
- package/dist/es/ai-model/model-adapter/resolve.mjs.map +1 -1
- package/dist/es/ai-model/model-adapter/responses.mjs +38 -0
- package/dist/es/ai-model/model-adapter/responses.mjs.map +1 -0
- package/dist/es/ai-model/model-adapter/temperature-with-semantic-retry.mjs +7 -0
- package/dist/es/ai-model/model-adapter/temperature-with-semantic-retry.mjs.map +1 -0
- package/dist/es/ai-model/models/gpt.mjs +73 -9
- package/dist/es/ai-model/models/gpt.mjs.map +1 -1
- package/dist/es/ai-model/models/registry.mjs +2 -2
- package/dist/es/ai-model/models/registry.mjs.map +1 -1
- package/dist/es/ai-model/service-caller/call-ai.mjs +22 -13
- package/dist/es/ai-model/service-caller/call-ai.mjs.map +1 -1
- package/dist/es/ai-model/service-caller/codex/call-codex.mjs +10 -8
- package/dist/es/ai-model/service-caller/codex/call-codex.mjs.map +1 -1
- package/dist/es/ai-model/service-caller/codex/codex-app-server.mjs +29 -28
- package/dist/es/ai-model/service-caller/codex/codex-app-server.mjs.map +1 -1
- package/dist/es/ai-model/service-caller/index.mjs +1 -2
- package/dist/es/ai-model/service-caller/model-call.mjs +4 -4
- package/dist/es/ai-model/service-caller/model-call.mjs.map +1 -1
- package/dist/es/ai-model/service-caller/openai/call-openai.mjs +13 -8
- package/dist/es/ai-model/service-caller/openai/call-openai.mjs.map +1 -1
- package/dist/es/ai-model/service-caller/openai/chat-completion/chat-completion.mjs +11 -7
- package/dist/es/ai-model/service-caller/openai/chat-completion/chat-completion.mjs.map +1 -1
- package/dist/es/ai-model/service-caller/openai/chat-completion/non-stream.mjs +9 -9
- package/dist/es/ai-model/service-caller/openai/chat-completion/non-stream.mjs.map +1 -1
- package/dist/es/ai-model/service-caller/openai/chat-completion/stream.mjs +4 -8
- package/dist/es/ai-model/service-caller/openai/chat-completion/stream.mjs.map +1 -1
- package/dist/es/ai-model/service-caller/openai/chat-completion/utils.mjs +28 -1
- package/dist/es/ai-model/service-caller/openai/chat-completion/utils.mjs.map +1 -1
- package/dist/es/ai-model/service-caller/openai/openai-client.mjs +3 -3
- package/dist/es/ai-model/service-caller/openai/openai-client.mjs.map +1 -1
- package/dist/es/ai-model/service-caller/openai/responses/non-stream.mjs +21 -0
- package/dist/es/ai-model/service-caller/openai/responses/non-stream.mjs.map +1 -0
- package/dist/es/ai-model/service-caller/openai/responses/responses.mjs +57 -0
- package/dist/es/ai-model/service-caller/openai/responses/responses.mjs.map +1 -0
- package/dist/es/ai-model/service-caller/openai/responses/stream.mjs +56 -0
- package/dist/es/ai-model/service-caller/openai/responses/stream.mjs.map +1 -0
- package/dist/es/ai-model/service-caller/openai/responses/types.mjs +0 -0
- package/dist/es/ai-model/service-caller/openai/responses/utils.mjs +72 -0
- package/dist/es/ai-model/service-caller/openai/responses/utils.mjs.map +1 -0
- package/dist/es/ai-model/service-caller/semantic-retry.mjs.map +1 -1
- package/dist/es/ai-model/service-caller/utils.mjs +6 -25
- package/dist/es/ai-model/service-caller/utils.mjs.map +1 -1
- package/dist/es/ai-model/shared/multimodal-prompt.mjs +5 -8
- package/dist/es/ai-model/shared/multimodal-prompt.mjs.map +1 -1
- package/dist/es/ai-model/workflows/grounding/locate.mjs +6 -6
- package/dist/es/ai-model/workflows/grounding/locate.mjs.map +1 -1
- package/dist/es/ai-model/workflows/grounding/planning-action-locate.mjs +5 -5
- package/dist/es/ai-model/workflows/grounding/planning-action-locate.mjs.map +1 -1
- package/dist/es/ai-model/workflows/grounding/section-locate.mjs +5 -5
- package/dist/es/ai-model/workflows/grounding/section-locate.mjs.map +1 -1
- package/dist/es/ai-model/workflows/grounding/utils.mjs +4 -7
- package/dist/es/ai-model/workflows/grounding/utils.mjs.map +1 -1
- package/dist/es/ai-model/workflows/insight/extraction.mjs +9 -15
- package/dist/es/ai-model/workflows/insight/extraction.mjs.map +1 -1
- package/dist/es/ai-model/workflows/insight/order-sensitive.mjs.map +1 -1
- package/dist/es/ai-model/workflows/planning/conversation-history.mjs +17 -9
- package/dist/es/ai-model/workflows/planning/conversation-history.mjs.map +1 -1
- package/dist/es/ai-model/workflows/planning/custom-planning.mjs +11 -12
- package/dist/es/ai-model/workflows/planning/custom-planning.mjs.map +1 -1
- package/dist/es/ai-model/workflows/planning/standard-planning.mjs +24 -26
- package/dist/es/ai-model/workflows/planning/standard-planning.mjs.map +1 -1
- package/dist/es/ai-model/workflows/recorder-generation/common.mjs +2 -4
- package/dist/es/ai-model/workflows/recorder-generation/common.mjs.map +1 -1
- package/dist/es/ai-model/workflows/recorder-generation/markdown.mjs +3 -5
- package/dist/es/ai-model/workflows/recorder-generation/markdown.mjs.map +1 -1
- package/dist/es/ai-model/workflows/recorder-generation/metadata.mjs +2 -4
- package/dist/es/ai-model/workflows/recorder-generation/metadata.mjs.map +1 -1
- package/dist/es/ai-model/workflows/recorder-generation/playwright.mjs.map +1 -1
- package/dist/es/ai-model/workflows/recorder-generation/yaml.mjs +2 -4
- package/dist/es/ai-model/workflows/recorder-generation/yaml.mjs.map +1 -1
- package/dist/es/report-html-template.mjs +1 -1
- package/dist/es/service/index.mjs +17 -26
- package/dist/es/service/index.mjs.map +1 -1
- package/dist/es/types.mjs.map +1 -1
- package/dist/es/utils.mjs +1 -1
- package/dist/lib/agent/task-builder.js +1 -1
- package/dist/lib/agent/task-builder.js.map +1 -1
- package/dist/lib/agent/tasks.js +4 -4
- package/dist/lib/agent/tasks.js.map +1 -1
- package/dist/lib/agent/utils.js +1 -1
- package/dist/lib/ai-model/connectivity/run-connectivity-test.js +2 -5
- package/dist/lib/ai-model/connectivity/run-connectivity-test.js.map +1 -1
- package/dist/lib/ai-model/model-adapter/chat-completion.js +8 -11
- package/dist/lib/ai-model/model-adapter/chat-completion.js.map +1 -1
- package/dist/lib/ai-model/model-adapter/resolve.js +10 -0
- package/dist/lib/ai-model/model-adapter/resolve.js.map +1 -1
- package/dist/lib/ai-model/model-adapter/responses.js +75 -0
- package/dist/lib/ai-model/model-adapter/responses.js.map +1 -0
- package/dist/lib/ai-model/model-adapter/temperature-with-semantic-retry.js +41 -0
- package/dist/lib/ai-model/model-adapter/temperature-with-semantic-retry.js.map +1 -0
- package/dist/lib/ai-model/models/gpt.js +73 -9
- package/dist/lib/ai-model/models/gpt.js.map +1 -1
- package/dist/lib/ai-model/models/registry.js +2 -2
- package/dist/lib/ai-model/models/registry.js.map +1 -1
- package/dist/lib/ai-model/service-caller/call-ai.js +22 -13
- package/dist/lib/ai-model/service-caller/call-ai.js.map +1 -1
- package/dist/lib/ai-model/service-caller/codex/call-codex.js +10 -8
- package/dist/lib/ai-model/service-caller/codex/call-codex.js.map +1 -1
- package/dist/lib/ai-model/service-caller/codex/codex-app-server.js +29 -28
- package/dist/lib/ai-model/service-caller/codex/codex-app-server.js.map +1 -1
- package/dist/lib/ai-model/service-caller/index.js +0 -4
- package/dist/lib/ai-model/service-caller/model-call.js +4 -4
- package/dist/lib/ai-model/service-caller/model-call.js.map +1 -1
- package/dist/lib/ai-model/service-caller/openai/call-openai.js +12 -7
- package/dist/lib/ai-model/service-caller/openai/call-openai.js.map +1 -1
- package/dist/lib/ai-model/service-caller/openai/chat-completion/chat-completion.js +10 -6
- package/dist/lib/ai-model/service-caller/openai/chat-completion/chat-completion.js.map +1 -1
- package/dist/lib/ai-model/service-caller/openai/chat-completion/non-stream.js +9 -9
- package/dist/lib/ai-model/service-caller/openai/chat-completion/non-stream.js.map +1 -1
- package/dist/lib/ai-model/service-caller/openai/chat-completion/stream.js +4 -8
- package/dist/lib/ai-model/service-caller/openai/chat-completion/stream.js.map +1 -1
- package/dist/lib/ai-model/service-caller/openai/chat-completion/utils.js +32 -2
- package/dist/lib/ai-model/service-caller/openai/chat-completion/utils.js.map +1 -1
- package/dist/lib/ai-model/service-caller/openai/openai-client.js +5 -5
- package/dist/lib/ai-model/service-caller/openai/openai-client.js.map +1 -1
- package/dist/lib/ai-model/service-caller/openai/responses/non-stream.js +55 -0
- package/dist/lib/ai-model/service-caller/openai/responses/non-stream.js.map +1 -0
- package/dist/lib/ai-model/service-caller/openai/responses/responses.js +94 -0
- package/dist/lib/ai-model/service-caller/openai/responses/responses.js.map +1 -0
- package/dist/lib/ai-model/service-caller/openai/responses/stream.js +90 -0
- package/dist/lib/ai-model/service-caller/openai/responses/stream.js.map +1 -0
- package/dist/lib/ai-model/service-caller/openai/responses/types.js +20 -0
- package/dist/lib/ai-model/service-caller/openai/responses/types.js.map +1 -0
- package/dist/lib/ai-model/service-caller/openai/responses/utils.js +112 -0
- package/dist/lib/ai-model/service-caller/openai/responses/utils.js.map +1 -0
- package/dist/lib/ai-model/service-caller/semantic-retry.js.map +1 -1
- package/dist/lib/ai-model/service-caller/utils.js +5 -27
- package/dist/lib/ai-model/service-caller/utils.js.map +1 -1
- package/dist/lib/ai-model/shared/multimodal-prompt.js +11 -14
- package/dist/lib/ai-model/shared/multimodal-prompt.js.map +1 -1
- package/dist/lib/ai-model/workflows/grounding/locate.js +6 -6
- package/dist/lib/ai-model/workflows/grounding/locate.js.map +1 -1
- package/dist/lib/ai-model/workflows/grounding/planning-action-locate.js +5 -5
- package/dist/lib/ai-model/workflows/grounding/planning-action-locate.js.map +1 -1
- package/dist/lib/ai-model/workflows/grounding/section-locate.js +5 -5
- package/dist/lib/ai-model/workflows/grounding/section-locate.js.map +1 -1
- package/dist/lib/ai-model/workflows/grounding/utils.js +3 -6
- package/dist/lib/ai-model/workflows/grounding/utils.js.map +1 -1
- package/dist/lib/ai-model/workflows/insight/extraction.js +8 -14
- package/dist/lib/ai-model/workflows/insight/extraction.js.map +1 -1
- package/dist/lib/ai-model/workflows/insight/order-sensitive.js.map +1 -1
- package/dist/lib/ai-model/workflows/planning/conversation-history.js +17 -9
- package/dist/lib/ai-model/workflows/planning/conversation-history.js.map +1 -1
- package/dist/lib/ai-model/workflows/planning/custom-planning.js +10 -11
- package/dist/lib/ai-model/workflows/planning/custom-planning.js.map +1 -1
- package/dist/lib/ai-model/workflows/planning/standard-planning.js +23 -25
- package/dist/lib/ai-model/workflows/planning/standard-planning.js.map +1 -1
- package/dist/lib/ai-model/workflows/recorder-generation/common.js +2 -4
- package/dist/lib/ai-model/workflows/recorder-generation/common.js.map +1 -1
- package/dist/lib/ai-model/workflows/recorder-generation/markdown.js +3 -5
- package/dist/lib/ai-model/workflows/recorder-generation/markdown.js.map +1 -1
- package/dist/lib/ai-model/workflows/recorder-generation/metadata.js +2 -4
- package/dist/lib/ai-model/workflows/recorder-generation/metadata.js.map +1 -1
- package/dist/lib/ai-model/workflows/recorder-generation/playwright.js.map +1 -1
- package/dist/lib/ai-model/workflows/recorder-generation/yaml.js +2 -4
- package/dist/lib/ai-model/workflows/recorder-generation/yaml.js.map +1 -1
- package/dist/lib/report-html-template.js +1 -1
- package/dist/lib/service/index.js +17 -26
- package/dist/lib/service/index.js.map +1 -1
- package/dist/lib/types.js.map +1 -1
- package/dist/lib/utils.js +1 -1
- package/dist/types/ai-model/connectivity/run-connectivity-test.d.ts.map +1 -1
- package/dist/types/ai-model/index.d.ts +1 -1
- package/dist/types/ai-model/index.d.ts.map +1 -1
- package/dist/types/ai-model/model-adapter/chat-completion.d.ts.map +1 -1
- package/dist/types/ai-model/model-adapter/resolve.d.ts +4 -1
- package/dist/types/ai-model/model-adapter/resolve.d.ts.map +1 -1
- package/dist/types/ai-model/model-adapter/responses.d.ts +4 -0
- package/dist/types/ai-model/model-adapter/responses.d.ts.map +1 -0
- package/dist/types/ai-model/model-adapter/temperature-with-semantic-retry.d.ts +6 -0
- package/dist/types/ai-model/model-adapter/temperature-with-semantic-retry.d.ts.map +1 -0
- package/dist/types/ai-model/model-adapter/types.d.ts +42 -13
- package/dist/types/ai-model/model-adapter/types.d.ts.map +1 -1
- package/dist/types/ai-model/models/gpt.d.ts +15 -3
- package/dist/types/ai-model/models/gpt.d.ts.map +1 -1
- package/dist/types/ai-model/models/registry.d.ts +14 -2
- package/dist/types/ai-model/models/registry.d.ts.map +1 -1
- package/dist/types/ai-model/service-caller/call-ai.d.ts +2 -2
- package/dist/types/ai-model/service-caller/call-ai.d.ts.map +1 -1
- package/dist/types/ai-model/service-caller/codex/call-codex.d.ts +4 -2
- package/dist/types/ai-model/service-caller/codex/call-codex.d.ts.map +1 -1
- package/dist/types/ai-model/service-caller/codex/codex-app-server.d.ts +5 -4
- package/dist/types/ai-model/service-caller/codex/codex-app-server.d.ts.map +1 -1
- package/dist/types/ai-model/service-caller/index.d.ts +0 -1
- package/dist/types/ai-model/service-caller/index.d.ts.map +1 -1
- package/dist/types/ai-model/service-caller/model-call.d.ts +6 -6
- package/dist/types/ai-model/service-caller/model-call.d.ts.map +1 -1
- package/dist/types/ai-model/service-caller/openai/call-openai.d.ts +9 -1
- package/dist/types/ai-model/service-caller/openai/call-openai.d.ts.map +1 -1
- package/dist/types/ai-model/service-caller/openai/chat-completion/chat-completion.d.ts +3 -4
- package/dist/types/ai-model/service-caller/openai/chat-completion/chat-completion.d.ts.map +1 -1
- package/dist/types/ai-model/service-caller/openai/chat-completion/non-stream.d.ts +1 -1
- package/dist/types/ai-model/service-caller/openai/chat-completion/non-stream.d.ts.map +1 -1
- package/dist/types/ai-model/service-caller/openai/chat-completion/stream.d.ts +1 -1
- package/dist/types/ai-model/service-caller/openai/chat-completion/stream.d.ts.map +1 -1
- package/dist/types/ai-model/service-caller/openai/chat-completion/types.d.ts +5 -5
- package/dist/types/ai-model/service-caller/openai/chat-completion/types.d.ts.map +1 -1
- package/dist/types/ai-model/service-caller/openai/chat-completion/utils.d.ts +5 -0
- package/dist/types/ai-model/service-caller/openai/chat-completion/utils.d.ts.map +1 -1
- package/dist/types/ai-model/service-caller/openai/openai-client.d.ts +2 -2
- package/dist/types/ai-model/service-caller/openai/openai-client.d.ts.map +1 -1
- package/dist/types/ai-model/service-caller/openai/responses/non-stream.d.ts +4 -0
- package/dist/types/ai-model/service-caller/openai/responses/non-stream.d.ts.map +1 -0
- package/dist/types/ai-model/service-caller/openai/responses/responses.d.ts +8 -0
- package/dist/types/ai-model/service-caller/openai/responses/responses.d.ts.map +1 -0
- package/dist/types/ai-model/service-caller/openai/responses/stream.d.ts +4 -0
- package/dist/types/ai-model/service-caller/openai/responses/stream.d.ts.map +1 -0
- package/dist/types/ai-model/service-caller/openai/responses/types.d.ts +8 -0
- package/dist/types/ai-model/service-caller/openai/responses/types.d.ts.map +1 -0
- package/dist/types/ai-model/service-caller/openai/responses/utils.d.ts +8 -0
- package/dist/types/ai-model/service-caller/openai/responses/utils.d.ts.map +1 -0
- package/dist/types/ai-model/service-caller/semantic-retry.d.ts +2 -2
- package/dist/types/ai-model/service-caller/semantic-retry.d.ts.map +1 -1
- package/dist/types/ai-model/service-caller/types.d.ts +35 -5
- package/dist/types/ai-model/service-caller/types.d.ts.map +1 -1
- package/dist/types/ai-model/service-caller/utils.d.ts +5 -9
- package/dist/types/ai-model/service-caller/utils.d.ts.map +1 -1
- package/dist/types/ai-model/shared/multimodal-prompt.d.ts +3 -3
- package/dist/types/ai-model/shared/multimodal-prompt.d.ts.map +1 -1
- package/dist/types/ai-model/workflows/grounding/planning-action-locate.d.ts.map +1 -1
- package/dist/types/ai-model/workflows/grounding/section-locate.d.ts +2 -1
- package/dist/types/ai-model/workflows/grounding/section-locate.d.ts.map +1 -1
- package/dist/types/ai-model/workflows/grounding/types.d.ts +3 -2
- package/dist/types/ai-model/workflows/grounding/types.d.ts.map +1 -1
- package/dist/types/ai-model/workflows/grounding/utils.d.ts +3 -3
- package/dist/types/ai-model/workflows/grounding/utils.d.ts.map +1 -1
- package/dist/types/ai-model/workflows/insight/extraction.d.ts +1 -1
- package/dist/types/ai-model/workflows/insight/extraction.d.ts.map +1 -1
- package/dist/types/ai-model/workflows/insight/order-sensitive.d.ts.map +1 -1
- package/dist/types/ai-model/workflows/planning/conversation-history.d.ts +10 -8
- package/dist/types/ai-model/workflows/planning/conversation-history.d.ts.map +1 -1
- package/dist/types/ai-model/workflows/planning/custom-planning.d.ts +2 -2
- package/dist/types/ai-model/workflows/planning/custom-planning.d.ts.map +1 -1
- package/dist/types/ai-model/workflows/planning/standard-planning.d.ts.map +1 -1
- package/dist/types/ai-model/workflows/recorder-generation/common.d.ts +2 -1
- package/dist/types/ai-model/workflows/recorder-generation/common.d.ts.map +1 -1
- package/dist/types/ai-model/workflows/recorder-generation/markdown.d.ts +2 -2
- package/dist/types/ai-model/workflows/recorder-generation/markdown.d.ts.map +1 -1
- package/dist/types/ai-model/workflows/recorder-generation/metadata.d.ts.map +1 -1
- package/dist/types/ai-model/workflows/recorder-generation/playwright.d.ts.map +1 -1
- package/dist/types/ai-model/workflows/recorder-generation/yaml.d.ts.map +1 -1
- package/dist/types/service/index.d.ts.map +1 -1
- package/dist/types/types.d.ts +11 -2
- package/dist/types/types.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { AIResponseParseError, hasUsableText } from "../../utils.mjs";
|
|
2
2
|
import { resolveContentWithReasoningFallback } from "./utils.mjs";
|
|
3
|
-
const callChatCompletionNonStreaming = async ({ completion, openAIRequestContext,
|
|
4
|
-
const { config: { modelName }, adapter } = modelRuntime;
|
|
3
|
+
const callChatCompletionNonStreaming = async ({ completion, openAIRequestContext, extractContentAndReasoning, useReasoningAsContentFallback, requestBodyParams, requestSignal })=>{
|
|
5
4
|
requestSignal.throwIfAborted();
|
|
6
5
|
const result = await completion.create({
|
|
7
|
-
model: modelName,
|
|
8
|
-
messages,
|
|
9
6
|
...requestBodyParams,
|
|
10
7
|
stream: false
|
|
11
8
|
}, {
|
|
@@ -14,19 +11,22 @@ const callChatCompletionNonStreaming = async ({ completion, openAIRequestContext
|
|
|
14
11
|
requestSignal.throwIfAborted();
|
|
15
12
|
const requestId = result._request_id ?? openAIRequestContext.responseRequestId?.requestId;
|
|
16
13
|
if (!result.choices) throw new Error(`invalid response from LLM service: ${JSON.stringify(result)}`);
|
|
17
|
-
const
|
|
18
|
-
|
|
14
|
+
const rawAssistantOutput = {
|
|
15
|
+
type: 'chat-completion',
|
|
16
|
+
rawValue: result.choices[0].message
|
|
17
|
+
};
|
|
18
|
+
const parsedMessage = extractContentAndReasoning(result.choices[0].message);
|
|
19
19
|
const reasoningContent = parsedMessage.reasoning_content;
|
|
20
20
|
const content = resolveContentWithReasoningFallback({
|
|
21
21
|
content: parsedMessage.content,
|
|
22
22
|
reasoningContent,
|
|
23
|
-
useReasoningAsContentFallback
|
|
23
|
+
useReasoningAsContentFallback
|
|
24
24
|
});
|
|
25
|
-
if (!hasUsableText(content)) throw new AIResponseParseError('empty content from AI model', content || '', void 0,
|
|
25
|
+
if (!hasUsableText(content)) throw new AIResponseParseError('empty content from AI model', content || '', void 0, rawAssistantOutput);
|
|
26
26
|
return {
|
|
27
27
|
content,
|
|
28
28
|
reasoningContent,
|
|
29
|
-
|
|
29
|
+
rawAssistantOutput,
|
|
30
30
|
rawUsage: result.usage,
|
|
31
31
|
requestId,
|
|
32
32
|
responseModelName: result.model
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-model/service-caller/openai/chat-completion/non-stream.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/chat-completion/non-stream.ts"],"sourcesContent":["import type { OpenAIProtocolCallResult } from '../../types';\nimport { AIResponseParseError, hasUsableText } from '../../utils';\nimport type { ChatCompletionCallOptions } from './types';\nimport { resolveContentWithReasoningFallback } from './utils';\n\nexport const callChatCompletionNonStreaming = async ({\n completion,\n openAIRequestContext,\n
|
|
1
|
+
{"version":3,"file":"ai-model/service-caller/openai/chat-completion/non-stream.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/chat-completion/non-stream.ts"],"sourcesContent":["import type { RawAssistantOutput } from '@/types';\nimport type { OpenAIProtocolCallResult } from '../../types';\nimport { AIResponseParseError, hasUsableText } from '../../utils';\nimport type { ChatCompletionCallOptions } from './types';\nimport { resolveContentWithReasoningFallback } from './utils';\n\nexport const callChatCompletionNonStreaming = async ({\n completion,\n openAIRequestContext,\n extractContentAndReasoning,\n useReasoningAsContentFallback,\n requestBodyParams,\n requestSignal,\n}: ChatCompletionCallOptions): Promise<OpenAIProtocolCallResult> => {\n requestSignal.throwIfAborted();\n const result = await completion.create(\n {\n ...requestBodyParams,\n stream: false,\n },\n { signal: requestSignal },\n );\n\n requestSignal.throwIfAborted();\n\n const requestId =\n result._request_id ?? openAIRequestContext.responseRequestId?.requestId;\n\n if (!result.choices) {\n throw new Error(\n `invalid response from LLM service: ${JSON.stringify(result)}`,\n );\n }\n\n const rawAssistantOutput: RawAssistantOutput = {\n type: 'chat-completion',\n rawValue: result.choices[0].message,\n };\n const parsedMessage = extractContentAndReasoning(result.choices[0].message);\n const reasoningContent = parsedMessage.reasoning_content;\n const content = resolveContentWithReasoningFallback({\n content: parsedMessage.content,\n reasoningContent,\n useReasoningAsContentFallback,\n });\n\n if (!hasUsableText(content)) {\n throw new AIResponseParseError(\n 'empty content from AI model',\n content || '',\n undefined,\n rawAssistantOutput,\n );\n }\n\n return {\n content,\n reasoningContent,\n rawAssistantOutput,\n rawUsage: result.usage,\n requestId,\n responseModelName: result.model,\n };\n};\n"],"names":["callChatCompletionNonStreaming","completion","openAIRequestContext","extractContentAndReasoning","useReasoningAsContentFallback","requestBodyParams","requestSignal","result","requestId","Error","JSON","rawAssistantOutput","parsedMessage","reasoningContent","content","resolveContentWithReasoningFallback","hasUsableText","AIResponseParseError","undefined"],"mappings":";;AAMO,MAAMA,iCAAiC,OAAO,EACnDC,UAAU,EACVC,oBAAoB,EACpBC,0BAA0B,EAC1BC,6BAA6B,EAC7BC,iBAAiB,EACjBC,aAAa,EACa;IAC1BA,cAAc,cAAc;IAC5B,MAAMC,SAAS,MAAMN,WAAW,MAAM,CACpC;QACE,GAAGI,iBAAiB;QACpB,QAAQ;IACV,GACA;QAAE,QAAQC;IAAc;IAG1BA,cAAc,cAAc;IAE5B,MAAME,YACJD,OAAO,WAAW,IAAIL,qBAAqB,iBAAiB,EAAE;IAEhE,IAAI,CAACK,OAAO,OAAO,EACjB,MAAM,IAAIE,MACR,CAAC,mCAAmC,EAAEC,KAAK,SAAS,CAACH,SAAS;IAIlE,MAAMI,qBAAyC;QAC7C,MAAM;QACN,UAAUJ,OAAO,OAAO,CAAC,EAAE,CAAC,OAAO;IACrC;IACA,MAAMK,gBAAgBT,2BAA2BI,OAAO,OAAO,CAAC,EAAE,CAAC,OAAO;IAC1E,MAAMM,mBAAmBD,cAAc,iBAAiB;IACxD,MAAME,UAAUC,oCAAoC;QAClD,SAASH,cAAc,OAAO;QAC9BC;QACAT;IACF;IAEA,IAAI,CAACY,cAAcF,UACjB,MAAM,IAAIG,qBACR,+BACAH,WAAW,IACXI,QACAP;IAIJ,OAAO;QACLG;QACAD;QACAF;QACA,UAAUJ,OAAO,KAAK;QACtBC;QACA,mBAAmBD,OAAO,KAAK;IACjC;AACF"}
|
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
import { assert } from "@midscene/shared/utils";
|
|
2
2
|
import { resolveContentWithReasoningFallback } from "./utils.mjs";
|
|
3
|
-
const callChatCompletionStream = async ({ completion, openAIRequestContext,
|
|
3
|
+
const callChatCompletionStream = async ({ completion, openAIRequestContext, extractContentAndReasoning, useReasoningAsContentFallback, requestBodyParams, requestSignal, onChunk, recordEvent })=>{
|
|
4
4
|
assert('function' == typeof onChunk, 'onChunk is required when stream is true');
|
|
5
|
-
const { adapter } = modelRuntime;
|
|
6
|
-
const { modelName } = modelRuntime.config;
|
|
7
5
|
let accumulated = '';
|
|
8
6
|
let accumulatedReasoning = '';
|
|
9
7
|
let usage;
|
|
10
8
|
let responseModelName;
|
|
11
9
|
requestSignal.throwIfAborted();
|
|
12
10
|
const stream = await completion.create({
|
|
13
|
-
model: modelName,
|
|
14
|
-
messages,
|
|
15
11
|
...requestBodyParams,
|
|
16
12
|
stream: true,
|
|
17
13
|
stream_options: {
|
|
@@ -32,7 +28,7 @@ const callChatCompletionStream = async ({ completion, openAIRequestContext, mode
|
|
|
32
28
|
sequence: chunkSequence,
|
|
33
29
|
chunk
|
|
34
30
|
});
|
|
35
|
-
const parsedChunk =
|
|
31
|
+
const parsedChunk = extractContentAndReasoning(chunk.choices?.[0]?.delta);
|
|
36
32
|
const content = parsedChunk.content || '';
|
|
37
33
|
const reasoning_content = parsedChunk.reasoning_content || '';
|
|
38
34
|
if (chunk.usage) usage = chunk.usage;
|
|
@@ -53,7 +49,7 @@ const callChatCompletionStream = async ({ completion, openAIRequestContext, mode
|
|
|
53
49
|
const finalAccumulated = resolveContentWithReasoningFallback({
|
|
54
50
|
content: accumulated,
|
|
55
51
|
reasoningContent: accumulatedReasoning,
|
|
56
|
-
useReasoningAsContentFallback
|
|
52
|
+
useReasoningAsContentFallback
|
|
57
53
|
});
|
|
58
54
|
accumulated = finalAccumulated || '';
|
|
59
55
|
const finalChunk = {
|
|
@@ -67,7 +63,7 @@ const callChatCompletionStream = async ({ completion, openAIRequestContext, mode
|
|
|
67
63
|
return {
|
|
68
64
|
content: accumulated,
|
|
69
65
|
reasoningContent: accumulatedReasoning,
|
|
70
|
-
|
|
66
|
+
rawAssistantOutput: void 0,
|
|
71
67
|
rawUsage: usage,
|
|
72
68
|
requestId,
|
|
73
69
|
responseModelName
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-model/service-caller/openai/chat-completion/stream.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/chat-completion/stream.ts"],"sourcesContent":["import type { CodeGenerationChunk } from '@/types';\nimport { assert } from '@midscene/shared/utils';\nimport type OpenAI from 'openai';\nimport type { Stream } from 'openai/streaming';\nimport type { OpenAIProtocolCallResult } from '../../types';\nimport type { ChatCompletionCallOptions } from './types';\nimport { resolveContentWithReasoningFallback } from './utils';\n\nexport const callChatCompletionStream = async ({\n completion,\n openAIRequestContext,\n
|
|
1
|
+
{"version":3,"file":"ai-model/service-caller/openai/chat-completion/stream.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/chat-completion/stream.ts"],"sourcesContent":["import type { CodeGenerationChunk } from '@/types';\nimport { assert } from '@midscene/shared/utils';\nimport type OpenAI from 'openai';\nimport type { Stream } from 'openai/streaming';\nimport type { OpenAIProtocolCallResult } from '../../types';\nimport type { ChatCompletionCallOptions } from './types';\nimport { resolveContentWithReasoningFallback } from './utils';\n\nexport const callChatCompletionStream = async ({\n completion,\n openAIRequestContext,\n extractContentAndReasoning,\n useReasoningAsContentFallback,\n requestBodyParams,\n requestSignal,\n onChunk,\n recordEvent,\n}: ChatCompletionCallOptions): Promise<OpenAIProtocolCallResult> => {\n assert(\n typeof onChunk === 'function',\n 'onChunk is required when stream is true',\n );\n let accumulated = '';\n let accumulatedReasoning = '';\n let usage: OpenAI.CompletionUsage | undefined;\n let responseModelName: string | undefined;\n requestSignal.throwIfAborted();\n const stream = (await completion.create(\n {\n ...requestBodyParams,\n stream: true,\n stream_options: {\n ...requestBodyParams.stream_options,\n include_usage: true,\n },\n },\n {\n stream: true,\n signal: requestSignal,\n },\n )) as Stream<OpenAI.Chat.Completions.ChatCompletionChunk> & {\n _request_id?: string | null;\n };\n\n const requestId =\n stream._request_id ?? openAIRequestContext.responseRequestId?.requestId;\n\n let chunkSequence = 0;\n for await (const chunk of stream) {\n requestSignal.throwIfAborted();\n chunkSequence += 1;\n recordEvent?.({\n type: 'chunk',\n sequence: chunkSequence,\n chunk,\n });\n const parsedChunk = extractContentAndReasoning(chunk.choices?.[0]?.delta);\n const content = parsedChunk.content || '';\n const reasoning_content = parsedChunk.reasoning_content || '';\n\n // Check for usage info in any chunk (OpenAI provides usage in separate chunks)\n if (chunk.usage) {\n usage = chunk.usage;\n }\n if (chunk.model) {\n responseModelName = chunk.model;\n }\n\n if (content || reasoning_content) {\n accumulated += content;\n accumulatedReasoning += reasoning_content;\n const chunkData: CodeGenerationChunk = {\n content,\n reasoning_content,\n accumulated,\n isComplete: false,\n usage: undefined,\n };\n onChunk(chunkData);\n }\n }\n\n const finalAccumulated = resolveContentWithReasoningFallback({\n content: accumulated,\n reasoningContent: accumulatedReasoning,\n useReasoningAsContentFallback,\n });\n accumulated = finalAccumulated || '';\n\n // Send final chunk\n const finalChunk: CodeGenerationChunk = {\n content: '',\n accumulated,\n reasoning_content: '',\n isComplete: true,\n usage,\n };\n onChunk(finalChunk);\n return {\n content: accumulated,\n reasoningContent: accumulatedReasoning,\n rawAssistantOutput: undefined,\n rawUsage: usage,\n requestId,\n responseModelName,\n };\n};\n"],"names":["callChatCompletionStream","completion","openAIRequestContext","extractContentAndReasoning","useReasoningAsContentFallback","requestBodyParams","requestSignal","onChunk","recordEvent","assert","accumulated","accumulatedReasoning","usage","responseModelName","stream","requestId","chunkSequence","chunk","parsedChunk","content","reasoning_content","chunkData","undefined","finalAccumulated","resolveContentWithReasoningFallback","finalChunk"],"mappings":";;AAQO,MAAMA,2BAA2B,OAAO,EAC7CC,UAAU,EACVC,oBAAoB,EACpBC,0BAA0B,EAC1BC,6BAA6B,EAC7BC,iBAAiB,EACjBC,aAAa,EACbC,OAAO,EACPC,WAAW,EACe;IAC1BC,OACE,AAAmB,cAAnB,OAAOF,SACP;IAEF,IAAIG,cAAc;IAClB,IAAIC,uBAAuB;IAC3B,IAAIC;IACJ,IAAIC;IACJP,cAAc,cAAc;IAC5B,MAAMQ,SAAU,MAAMb,WAAW,MAAM,CACrC;QACE,GAAGI,iBAAiB;QACpB,QAAQ;QACR,gBAAgB;YACd,GAAGA,kBAAkB,cAAc;YACnC,eAAe;QACjB;IACF,GACA;QACE,QAAQ;QACR,QAAQC;IACV;IAKF,MAAMS,YACJD,OAAO,WAAW,IAAIZ,qBAAqB,iBAAiB,EAAE;IAEhE,IAAIc,gBAAgB;IACpB,WAAW,MAAMC,SAASH,OAAQ;QAChCR,cAAc,cAAc;QAC5BU,iBAAiB;QACjBR,cAAc;YACZ,MAAM;YACN,UAAUQ;YACVC;QACF;QACA,MAAMC,cAAcf,2BAA2Bc,MAAM,OAAO,EAAE,CAAC,EAAE,EAAE;QACnE,MAAME,UAAUD,YAAY,OAAO,IAAI;QACvC,MAAME,oBAAoBF,YAAY,iBAAiB,IAAI;QAG3D,IAAID,MAAM,KAAK,EACbL,QAAQK,MAAM,KAAK;QAErB,IAAIA,MAAM,KAAK,EACbJ,oBAAoBI,MAAM,KAAK;QAGjC,IAAIE,WAAWC,mBAAmB;YAChCV,eAAeS;YACfR,wBAAwBS;YACxB,MAAMC,YAAiC;gBACrCF;gBACAC;gBACAV;gBACA,YAAY;gBACZ,OAAOY;YACT;YACAf,QAAQc;QACV;IACF;IAEA,MAAME,mBAAmBC,oCAAoC;QAC3D,SAASd;QACT,kBAAkBC;QAClBP;IACF;IACAM,cAAca,oBAAoB;IAGlC,MAAME,aAAkC;QACtC,SAAS;QACTf;QACA,mBAAmB;QACnB,YAAY;QACZE;IACF;IACAL,QAAQkB;IACR,OAAO;QACL,SAASf;QACT,kBAAkBC;QAClB,oBAAoBW;QACpB,UAAUV;QACVG;QACAF;IACF;AACF"}
|
|
@@ -10,6 +10,33 @@ const resolveContentWithReasoningFallback = ({ content, reasoningContent, useRea
|
|
|
10
10
|
}
|
|
11
11
|
return content;
|
|
12
12
|
};
|
|
13
|
-
|
|
13
|
+
function toChatMessages(messages, resolveImageDetail) {
|
|
14
|
+
return messages.map((entry)=>{
|
|
15
|
+
if ('type' in entry && 'model-output' === entry.type) {
|
|
16
|
+
if ('chat-completion' !== entry.output.type) throw new Error('Cannot replay Responses output in a Chat Completions conversation');
|
|
17
|
+
return entry.output.rawValue;
|
|
18
|
+
}
|
|
19
|
+
const message = 'role' in entry ? entry : entry.message;
|
|
20
|
+
return {
|
|
21
|
+
role: message.role,
|
|
22
|
+
content: 'string' == typeof message.content ? message.content : message.content.map((part)=>{
|
|
23
|
+
if ('text' === part.type) return {
|
|
24
|
+
type: 'text',
|
|
25
|
+
text: part.text
|
|
26
|
+
};
|
|
27
|
+
return {
|
|
28
|
+
type: 'image_url',
|
|
29
|
+
image_url: {
|
|
30
|
+
url: part.url,
|
|
31
|
+
detail: resolveImageDetail({
|
|
32
|
+
imageDetail: part.detail
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
})
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
export { resolveContentWithReasoningFallback, toChatMessages };
|
|
14
41
|
|
|
15
42
|
//# sourceMappingURL=utils.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-model/service-caller/openai/chat-completion/utils.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/chat-completion/utils.ts"],"sourcesContent":["import { getDebug } from '@midscene/shared/logger';\nimport { hasUsableText } from '../../utils';\n\nexport const resolveContentWithReasoningFallback = ({\n content,\n reasoningContent,\n useReasoningAsContentFallback,\n}: {\n content: string | undefined;\n reasoningContent: string;\n useReasoningAsContentFallback: boolean;\n}): string | undefined => {\n if (\n !hasUsableText(content) &&\n useReasoningAsContentFallback &&\n hasUsableText(reasoningContent)\n ) {\n const warnCall = getDebug('ai:call', { console: true });\n warnCall('empty content from AI model, using reasoning content');\n return reasoningContent;\n }\n\n return content;\n};\n"],"names":["resolveContentWithReasoningFallback","content","reasoningContent","useReasoningAsContentFallback","hasUsableText","warnCall","getDebug"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"ai-model/service-caller/openai/chat-completion/utils.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/chat-completion/utils.ts"],"sourcesContent":["import { getDebug } from '@midscene/shared/logger';\nimport type { ChatCompletionMessageParam } from 'openai/resources/index';\nimport type { ResolveImageDetail } from '../../../model-adapter/types';\nimport type { ModelCallMessages } from '../../types';\nimport { hasUsableText } from '../../utils';\n\nexport const resolveContentWithReasoningFallback = ({\n content,\n reasoningContent,\n useReasoningAsContentFallback,\n}: {\n content: string | undefined;\n reasoningContent: string;\n useReasoningAsContentFallback: boolean;\n}): string | undefined => {\n if (\n !hasUsableText(content) &&\n useReasoningAsContentFallback &&\n hasUsableText(reasoningContent)\n ) {\n const warnCall = getDebug('ai:call', { console: true });\n warnCall('empty content from AI model, using reasoning content');\n return reasoningContent;\n }\n\n return content;\n};\n\n/** Chat Completions cannot replay Responses output items as messages. */\nexport function toChatMessages(\n messages: ModelCallMessages,\n resolveImageDetail: ResolveImageDetail,\n): ChatCompletionMessageParam[] {\n // The installed SDK does not yet include the supported `original` image detail.\n return messages.map((entry) => {\n if ('type' in entry && entry.type === 'model-output') {\n if (entry.output.type !== 'chat-completion') {\n throw new Error(\n 'Cannot replay Responses output in a Chat Completions conversation',\n );\n }\n return entry.output.rawValue;\n }\n const message = 'role' in entry ? entry : entry.message;\n return {\n role: message.role,\n content:\n typeof message.content === 'string'\n ? message.content\n : message.content.map((part) => {\n if (part.type === 'text') {\n return { type: 'text', text: part.text };\n }\n return {\n type: 'image_url',\n image_url: {\n url: part.url,\n detail: resolveImageDetail({ imageDetail: part.detail }),\n },\n };\n }),\n };\n }) as ChatCompletionMessageParam[];\n}\n"],"names":["resolveContentWithReasoningFallback","content","reasoningContent","useReasoningAsContentFallback","hasUsableText","warnCall","getDebug","toChatMessages","messages","resolveImageDetail","entry","Error","message","part"],"mappings":";;AAMO,MAAMA,sCAAsC,CAAC,EAClDC,OAAO,EACPC,gBAAgB,EAChBC,6BAA6B,EAK9B;IACC,IACE,CAACC,cAAcH,YACfE,iCACAC,cAAcF,mBACd;QACA,MAAMG,WAAWC,SAAS,WAAW;YAAE,SAAS;QAAK;QACrDD,SAAS;QACT,OAAOH;IACT;IAEA,OAAOD;AACT;AAGO,SAASM,eACdC,QAA2B,EAC3BC,kBAAsC;IAGtC,OAAOD,SAAS,GAAG,CAAC,CAACE;QACnB,IAAI,UAAUA,SAASA,AAAe,mBAAfA,MAAM,IAAI,EAAqB;YACpD,IAAIA,AAAsB,sBAAtBA,MAAM,MAAM,CAAC,IAAI,EACnB,MAAM,IAAIC,MACR;YAGJ,OAAOD,MAAM,MAAM,CAAC,QAAQ;QAC9B;QACA,MAAME,UAAU,UAAUF,QAAQA,QAAQA,MAAM,OAAO;QACvD,OAAO;YACL,MAAME,QAAQ,IAAI;YAClB,SACE,AAA2B,YAA3B,OAAOA,QAAQ,OAAO,GAClBA,QAAQ,OAAO,GACfA,QAAQ,OAAO,CAAC,GAAG,CAAC,CAACC;gBACnB,IAAIA,AAAc,WAAdA,KAAK,IAAI,EACX,OAAO;oBAAE,MAAM;oBAAQ,MAAMA,KAAK,IAAI;gBAAC;gBAEzC,OAAO;oBACL,MAAM;oBACN,WAAW;wBACT,KAAKA,KAAK,GAAG;wBACb,QAAQJ,mBAAmB;4BAAE,aAAaI,KAAK,MAAM;wBAAC;oBACxD;gBACF;YACF;QACR;IACF;AACF"}
|
|
@@ -51,7 +51,7 @@ const createAndWrapClient = async ({ openaiBaseURL, openaiApiKey, openaiExtraCon
|
|
|
51
51
|
}
|
|
52
52
|
return openai;
|
|
53
53
|
};
|
|
54
|
-
async function
|
|
54
|
+
async function createClient({ modelConfig, proxyAgent, effectiveTimeoutMs, executionId, recordEvent }) {
|
|
55
55
|
const { openaiBaseURL, openaiApiKey, openaiExtraConfig, createOpenAIClient } = modelConfig;
|
|
56
56
|
const openAIRequestContext = {
|
|
57
57
|
recordEvent
|
|
@@ -67,10 +67,10 @@ async function createChatClient({ modelConfig, proxyAgent, effectiveTimeoutMs, e
|
|
|
67
67
|
openAIRequestContext
|
|
68
68
|
});
|
|
69
69
|
return {
|
|
70
|
-
|
|
70
|
+
openai,
|
|
71
71
|
openAIRequestContext
|
|
72
72
|
};
|
|
73
73
|
}
|
|
74
|
-
export {
|
|
74
|
+
export { createClient };
|
|
75
75
|
|
|
76
76
|
//# sourceMappingURL=openai-client.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-model/service-caller/openai/openai-client.mjs","sources":["../../../../../src/ai-model/service-caller/openai/openai-client.ts"],"sourcesContent":["import {\n type IModelConfig,\n MIDSCENE_LANGFUSE_DEBUG,\n MIDSCENE_LANGSMITH_DEBUG,\n globalConfigManager,\n} from '@midscene/shared/env';\nimport { getDebug } from '@midscene/shared/logger';\nimport { ifInBrowser } from '@midscene/shared/utils';\nimport OpenAI from 'openai';\nimport { getVersion } from '../../../utils';\nimport type { createProxyAgentIfNeeded } from '../proxy';\nimport {\n type OpenAIRequestContext,\n wrapOpenAICompatibleFetch,\n} from './openai-request-context';\n\nconst createAndWrapClient = async ({\n openaiBaseURL,\n openaiApiKey,\n openaiExtraConfig,\n createOpenAIClient,\n effectiveTimeoutMs,\n proxyAgent,\n executionId,\n openAIRequestContext,\n}: {\n openaiBaseURL: IModelConfig['openaiBaseURL'];\n openaiApiKey: IModelConfig['openaiApiKey'];\n openaiExtraConfig: IModelConfig['openaiExtraConfig'];\n createOpenAIClient: IModelConfig['createOpenAIClient'];\n effectiveTimeoutMs: number | null;\n proxyAgent: Awaited<ReturnType<typeof createProxyAgentIfNeeded>>;\n executionId: string;\n openAIRequestContext: OpenAIRequestContext;\n}): Promise<OpenAI> => {\n const warnClient = getDebug('ai:call', { console: true });\n\n const openAIOptions = {\n baseURL: openaiBaseURL,\n apiKey: openaiApiKey,\n // Use fetchOptions.dispatcher for fetch-based SDK instead of httpAgent\n // Note: Type assertion needed due to undici version mismatch between dependencies\n ...(proxyAgent ? { fetchOptions: { dispatcher: proxyAgent as any } } : {}),\n ...openaiExtraConfig,\n // Midscene exposes this setting through MIDSCENE_*_INIT_CONFIG_JSON, so\n // defaultHeaders is expected to be a plain JSON object rather than another\n // HeadersLike representation supported by the OpenAI SDK.\n defaultHeaders: {\n ...(openaiExtraConfig?.defaultHeaders as\n | Record<string, string>\n | undefined),\n // These Midscene-owned headers intentionally override user-supplied\n // headers with the same names.\n 'x-midscene-version': getVersion(),\n 'x-midscene-execution-id': executionId,\n },\n fetch: wrapOpenAICompatibleFetch(openAIRequestContext),\n // Midscene handles request retries in callAI(), so disable SDK-level retries\n // to avoid duplicate attempts and duplicated backoff latency.\n maxRetries: 0,\n // Disabling the Midscene hard timeout leaves the SDK timeout at its\n // configured value or default; it does not disable SDK/network timeouts.\n ...(effectiveTimeoutMs !== null ? { timeout: effectiveTimeoutMs } : {}),\n dangerouslyAllowBrowser: true,\n };\n\n const baseOpenAI = new OpenAI(openAIOptions);\n\n let openai: OpenAI = baseOpenAI;\n\n // LangSmith wrapper\n if (\n openai &&\n globalConfigManager.getEnvConfigInBoolean(MIDSCENE_LANGSMITH_DEBUG)\n ) {\n if (ifInBrowser) {\n throw new Error('langsmith is not supported in browser');\n }\n warnClient('DEBUGGING MODE: langsmith wrapper enabled');\n // Use variable to prevent static analysis by bundlers\n const langsmithModule = 'langsmith/wrappers';\n const { wrapOpenAI } = await import(langsmithModule);\n openai = wrapOpenAI(openai);\n }\n\n // Langfuse wrapper\n if (\n openai &&\n globalConfigManager.getEnvConfigInBoolean(MIDSCENE_LANGFUSE_DEBUG)\n ) {\n if (ifInBrowser) {\n throw new Error('langfuse is not supported in browser');\n }\n warnClient('DEBUGGING MODE: langfuse wrapper enabled');\n // Use variable to prevent static analysis by bundlers\n const langfuseModule = '@langfuse/openai';\n const { observeOpenAI } = await import(langfuseModule);\n openai = observeOpenAI(openai);\n }\n\n if (createOpenAIClient) {\n const wrappedClient = await createOpenAIClient(baseOpenAI, openAIOptions);\n\n if (wrappedClient) {\n openai = wrappedClient as OpenAI;\n }\n }\n\n return openai;\n};\n\nexport async function
|
|
1
|
+
{"version":3,"file":"ai-model/service-caller/openai/openai-client.mjs","sources":["../../../../../src/ai-model/service-caller/openai/openai-client.ts"],"sourcesContent":["import {\n type IModelConfig,\n MIDSCENE_LANGFUSE_DEBUG,\n MIDSCENE_LANGSMITH_DEBUG,\n globalConfigManager,\n} from '@midscene/shared/env';\nimport { getDebug } from '@midscene/shared/logger';\nimport { ifInBrowser } from '@midscene/shared/utils';\nimport OpenAI from 'openai';\nimport { getVersion } from '../../../utils';\nimport type { createProxyAgentIfNeeded } from '../proxy';\nimport {\n type OpenAIRequestContext,\n wrapOpenAICompatibleFetch,\n} from './openai-request-context';\n\nconst createAndWrapClient = async ({\n openaiBaseURL,\n openaiApiKey,\n openaiExtraConfig,\n createOpenAIClient,\n effectiveTimeoutMs,\n proxyAgent,\n executionId,\n openAIRequestContext,\n}: {\n openaiBaseURL: IModelConfig['openaiBaseURL'];\n openaiApiKey: IModelConfig['openaiApiKey'];\n openaiExtraConfig: IModelConfig['openaiExtraConfig'];\n createOpenAIClient: IModelConfig['createOpenAIClient'];\n effectiveTimeoutMs: number | null;\n proxyAgent: Awaited<ReturnType<typeof createProxyAgentIfNeeded>>;\n executionId: string;\n openAIRequestContext: OpenAIRequestContext;\n}): Promise<OpenAI> => {\n const warnClient = getDebug('ai:call', { console: true });\n\n const openAIOptions = {\n baseURL: openaiBaseURL,\n apiKey: openaiApiKey,\n // Use fetchOptions.dispatcher for fetch-based SDK instead of httpAgent\n // Note: Type assertion needed due to undici version mismatch between dependencies\n ...(proxyAgent ? { fetchOptions: { dispatcher: proxyAgent as any } } : {}),\n ...openaiExtraConfig,\n // Midscene exposes this setting through MIDSCENE_*_INIT_CONFIG_JSON, so\n // defaultHeaders is expected to be a plain JSON object rather than another\n // HeadersLike representation supported by the OpenAI SDK.\n defaultHeaders: {\n ...(openaiExtraConfig?.defaultHeaders as\n | Record<string, string>\n | undefined),\n // These Midscene-owned headers intentionally override user-supplied\n // headers with the same names.\n 'x-midscene-version': getVersion(),\n 'x-midscene-execution-id': executionId,\n },\n fetch: wrapOpenAICompatibleFetch(openAIRequestContext),\n // Midscene handles request retries in callAI(), so disable SDK-level retries\n // to avoid duplicate attempts and duplicated backoff latency.\n maxRetries: 0,\n // Disabling the Midscene hard timeout leaves the SDK timeout at its\n // configured value or default; it does not disable SDK/network timeouts.\n ...(effectiveTimeoutMs !== null ? { timeout: effectiveTimeoutMs } : {}),\n dangerouslyAllowBrowser: true,\n };\n\n const baseOpenAI = new OpenAI(openAIOptions);\n\n let openai: OpenAI = baseOpenAI;\n\n // LangSmith wrapper\n if (\n openai &&\n globalConfigManager.getEnvConfigInBoolean(MIDSCENE_LANGSMITH_DEBUG)\n ) {\n if (ifInBrowser) {\n throw new Error('langsmith is not supported in browser');\n }\n warnClient('DEBUGGING MODE: langsmith wrapper enabled');\n // Use variable to prevent static analysis by bundlers\n const langsmithModule = 'langsmith/wrappers';\n const { wrapOpenAI } = await import(langsmithModule);\n openai = wrapOpenAI(openai);\n }\n\n // Langfuse wrapper\n if (\n openai &&\n globalConfigManager.getEnvConfigInBoolean(MIDSCENE_LANGFUSE_DEBUG)\n ) {\n if (ifInBrowser) {\n throw new Error('langfuse is not supported in browser');\n }\n warnClient('DEBUGGING MODE: langfuse wrapper enabled');\n // Use variable to prevent static analysis by bundlers\n const langfuseModule = '@langfuse/openai';\n const { observeOpenAI } = await import(langfuseModule);\n openai = observeOpenAI(openai);\n }\n\n if (createOpenAIClient) {\n const wrappedClient = await createOpenAIClient(baseOpenAI, openAIOptions);\n\n if (wrappedClient) {\n openai = wrappedClient as OpenAI;\n }\n }\n\n return openai;\n};\n\nexport async function createClient({\n modelConfig,\n proxyAgent,\n effectiveTimeoutMs,\n executionId,\n recordEvent,\n}: {\n modelConfig: IModelConfig;\n proxyAgent: Awaited<ReturnType<typeof createProxyAgentIfNeeded>>;\n effectiveTimeoutMs: number | null;\n executionId: string;\n recordEvent?: (event: Record<string, unknown>) => void;\n}): Promise<{\n openai: OpenAI;\n openAIRequestContext: OpenAIRequestContext;\n}> {\n const { openaiBaseURL, openaiApiKey, openaiExtraConfig, createOpenAIClient } =\n modelConfig;\n\n const openAIRequestContext: OpenAIRequestContext = {\n recordEvent,\n };\n\n const openai = await createAndWrapClient({\n openaiBaseURL,\n openaiApiKey,\n openaiExtraConfig,\n createOpenAIClient,\n effectiveTimeoutMs,\n proxyAgent,\n executionId,\n openAIRequestContext,\n });\n\n return {\n openai,\n openAIRequestContext,\n };\n}\n"],"names":["createAndWrapClient","openaiBaseURL","openaiApiKey","openaiExtraConfig","createOpenAIClient","effectiveTimeoutMs","proxyAgent","executionId","openAIRequestContext","warnClient","getDebug","openAIOptions","getVersion","wrapOpenAICompatibleFetch","baseOpenAI","OpenAI","openai","globalConfigManager","MIDSCENE_LANGSMITH_DEBUG","ifInBrowser","Error","langsmithModule","wrapOpenAI","MIDSCENE_LANGFUSE_DEBUG","langfuseModule","observeOpenAI","wrappedClient","createClient","modelConfig","recordEvent"],"mappings":";;;;;;AAgBA,MAAMA,sBAAsB,OAAO,EACjCC,aAAa,EACbC,YAAY,EACZC,iBAAiB,EACjBC,kBAAkB,EAClBC,kBAAkB,EAClBC,UAAU,EACVC,WAAW,EACXC,oBAAoB,EAUrB;IACC,MAAMC,aAAaC,SAAS,WAAW;QAAE,SAAS;IAAK;IAEvD,MAAMC,gBAAgB;QACpB,SAASV;QACT,QAAQC;QAGR,GAAII,aAAa;YAAE,cAAc;gBAAE,YAAYA;YAAkB;QAAE,IAAI,CAAC,CAAC;QACzE,GAAGH,iBAAiB;QAIpB,gBAAgB;YACd,GAAIA,mBAAmB,cAAc;YAKrC,sBAAsBS;YACtB,2BAA2BL;QAC7B;QACA,OAAOM,0BAA0BL;QAGjC,YAAY;QAGZ,GAAIH,AAAuB,SAAvBA,qBAA8B;YAAE,SAASA;QAAmB,IAAI,CAAC,CAAC;QACtE,yBAAyB;IAC3B;IAEA,MAAMS,aAAa,IAAIC,SAAOJ;IAE9B,IAAIK,SAAiBF;IAGrB,IACEE,UACAC,oBAAoB,qBAAqB,CAACC,2BAC1C;QACA,IAAIC,aACF,MAAM,IAAIC,MAAM;QAElBX,WAAW;QAEX,MAAMY,kBAAkB;QACxB,MAAM,EAAEC,UAAU,EAAE,GAAG,MAAM,MAAM,CAACD;QACpCL,SAASM,WAAWN;IACtB;IAGA,IACEA,UACAC,oBAAoB,qBAAqB,CAACM,0BAC1C;QACA,IAAIJ,aACF,MAAM,IAAIC,MAAM;QAElBX,WAAW;QAEX,MAAMe,iBAAiB;QACvB,MAAM,EAAEC,aAAa,EAAE,GAAG,MAAM,MAAM,CAACD;QACvCR,SAASS,cAAcT;IACzB;IAEA,IAAIZ,oBAAoB;QACtB,MAAMsB,gBAAgB,MAAMtB,mBAAmBU,YAAYH;QAE3D,IAAIe,eACFV,SAASU;IAEb;IAEA,OAAOV;AACT;AAEO,eAAeW,aAAa,EACjCC,WAAW,EACXtB,UAAU,EACVD,kBAAkB,EAClBE,WAAW,EACXsB,WAAW,EAOZ;IAIC,MAAM,EAAE5B,aAAa,EAAEC,YAAY,EAAEC,iBAAiB,EAAEC,kBAAkB,EAAE,GAC1EwB;IAEF,MAAMpB,uBAA6C;QACjDqB;IACF;IAEA,MAAMb,SAAS,MAAMhB,oBAAoB;QACvCC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;IACF;IAEA,OAAO;QACLQ;QACAR;IACF;AACF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { AIResponseParseError, hasUsableText } from "../../utils.mjs";
|
|
2
|
+
import { parseResponse } from "./utils.mjs";
|
|
3
|
+
async function callResponsesNonStreaming({ responses, requestBodyParams, requestSignal, openAIRequestContext }) {
|
|
4
|
+
requestSignal.throwIfAborted();
|
|
5
|
+
const response = await responses.create({
|
|
6
|
+
...requestBodyParams,
|
|
7
|
+
stream: false
|
|
8
|
+
}, {
|
|
9
|
+
signal: requestSignal
|
|
10
|
+
});
|
|
11
|
+
requestSignal.throwIfAborted();
|
|
12
|
+
const result = parseResponse(response);
|
|
13
|
+
if (!hasUsableText(result.content)) throw new AIResponseParseError('empty content from AI model', result.content, void 0, result.rawAssistantOutput);
|
|
14
|
+
return {
|
|
15
|
+
...result,
|
|
16
|
+
requestId: response._request_id ?? openAIRequestContext.responseRequestId?.requestId
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export { callResponsesNonStreaming };
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=non-stream.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-model/service-caller/openai/responses/non-stream.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/responses/non-stream.ts"],"sourcesContent":["import type { OpenAIProtocolCallResult } from '../../types';\nimport { AIResponseParseError, hasUsableText } from '../../utils';\nimport type { ResponsesCallOptions } from './types';\nimport { parseResponse } from './utils';\n\nexport async function callResponsesNonStreaming({\n responses,\n requestBodyParams,\n requestSignal,\n openAIRequestContext,\n}: ResponsesCallOptions): Promise<OpenAIProtocolCallResult> {\n requestSignal.throwIfAborted();\n const response = await responses.create(\n { ...requestBodyParams, stream: false },\n { signal: requestSignal },\n );\n requestSignal.throwIfAborted();\n const result = parseResponse(response);\n if (!hasUsableText(result.content)) {\n throw new AIResponseParseError(\n 'empty content from AI model',\n result.content,\n undefined,\n result.rawAssistantOutput,\n );\n }\n return {\n ...result,\n requestId:\n response._request_id ?? openAIRequestContext.responseRequestId?.requestId,\n };\n}\n"],"names":["callResponsesNonStreaming","responses","requestBodyParams","requestSignal","openAIRequestContext","response","result","parseResponse","hasUsableText","AIResponseParseError","undefined"],"mappings":";;AAKO,eAAeA,0BAA0B,EAC9CC,SAAS,EACTC,iBAAiB,EACjBC,aAAa,EACbC,oBAAoB,EACC;IACrBD,cAAc,cAAc;IAC5B,MAAME,WAAW,MAAMJ,UAAU,MAAM,CACrC;QAAE,GAAGC,iBAAiB;QAAE,QAAQ;IAAM,GACtC;QAAE,QAAQC;IAAc;IAE1BA,cAAc,cAAc;IAC5B,MAAMG,SAASC,cAAcF;IAC7B,IAAI,CAACG,cAAcF,OAAO,OAAO,GAC/B,MAAM,IAAIG,qBACR,+BACAH,OAAO,OAAO,EACdI,QACAJ,OAAO,kBAAkB;IAG7B,OAAO;QACL,GAAGA,MAAM;QACT,WACED,SAAS,WAAW,IAAID,qBAAqB,iBAAiB,EAAE;IACpE;AACF"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { getDebug } from "@midscene/shared/logger";
|
|
2
|
+
import { createProxyAgentIfNeeded } from "../../proxy/index.mjs";
|
|
3
|
+
import { stringifyForDebug } from "../../utils.mjs";
|
|
4
|
+
import { callResponsesNonStreaming } from "./non-stream.mjs";
|
|
5
|
+
import { callResponsesStream } from "./stream.mjs";
|
|
6
|
+
import { toResponsesInput } from "./utils.mjs";
|
|
7
|
+
async function prepareResponses({ messages, modelRuntime, options }) {
|
|
8
|
+
const debugCall = getDebug('ai:call');
|
|
9
|
+
const { config: modelConfig, adapter } = modelRuntime;
|
|
10
|
+
const modelCallInput = {
|
|
11
|
+
intent: modelConfig.intent,
|
|
12
|
+
userConfig: {
|
|
13
|
+
temperature: modelConfig.temperature,
|
|
14
|
+
reasoningEnabled: modelConfig.reasoningEnabled,
|
|
15
|
+
reasoningEffort: modelConfig.reasoningEffort,
|
|
16
|
+
reasoningBudget: modelConfig.reasoningBudget,
|
|
17
|
+
responseFormat: modelConfig.responseFormat
|
|
18
|
+
},
|
|
19
|
+
semanticRetryAttempt: options?.semanticRetryAttempt,
|
|
20
|
+
requiresOriginalImageDetail: options?.requiresOriginalImageDetail,
|
|
21
|
+
expectedJsonObjectResponse: options?.expectedJsonObjectResponse
|
|
22
|
+
};
|
|
23
|
+
const { config } = adapter.responses.buildResponsesParams(modelCallInput);
|
|
24
|
+
debugCall(`adapter responses params: ${stringifyForDebug({
|
|
25
|
+
config
|
|
26
|
+
})}`);
|
|
27
|
+
const resolveImageDetail = ({ imageDetail })=>adapter.resolveImageDetail({
|
|
28
|
+
imageDetail,
|
|
29
|
+
intent: modelConfig.intent,
|
|
30
|
+
requiresOriginalImageDetail: options?.requiresOriginalImageDetail
|
|
31
|
+
});
|
|
32
|
+
const requestParams = {
|
|
33
|
+
...config,
|
|
34
|
+
...modelConfig.extraBody
|
|
35
|
+
};
|
|
36
|
+
if (true === requestParams.background) throw new Error('Responses background mode is not supported');
|
|
37
|
+
const requestBodyParams = {
|
|
38
|
+
store: false,
|
|
39
|
+
...requestParams,
|
|
40
|
+
model: modelConfig.modelName,
|
|
41
|
+
input: toResponsesInput(messages, resolveImageDetail)
|
|
42
|
+
};
|
|
43
|
+
const proxyAgent = await createProxyAgentIfNeeded({
|
|
44
|
+
socksProxy: modelConfig.socksProxy,
|
|
45
|
+
httpProxy: modelConfig.httpProxy
|
|
46
|
+
});
|
|
47
|
+
return {
|
|
48
|
+
requestParams: requestBodyParams,
|
|
49
|
+
proxyAgent
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function callResponses(options, stream) {
|
|
53
|
+
return stream ? callResponsesStream(options) : callResponsesNonStreaming(options);
|
|
54
|
+
}
|
|
55
|
+
export { callResponses, prepareResponses };
|
|
56
|
+
|
|
57
|
+
//# sourceMappingURL=responses.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-model/service-caller/openai/responses/responses.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/responses/responses.ts"],"sourcesContent":["import { getDebug } from '@midscene/shared/logger';\nimport type { ResolveImageDetail } from '../../../model-adapter/types';\nimport type { ModelRequestConfigInput } from '../../../model-adapter/types';\nimport { createProxyAgentIfNeeded } from '../../proxy';\nimport type { ModelCallContext, OpenAIProtocolCallResult } from '../../types';\nimport { stringifyForDebug } from '../../utils';\nimport { callResponsesNonStreaming } from './non-stream';\nimport { callResponsesStream } from './stream';\nimport type { ResponsesCallOptions } from './types';\nimport { toResponsesInput } from './utils';\n\nexport async function prepareResponses({\n messages,\n modelRuntime,\n options,\n}: Pick<ModelCallContext, 'messages' | 'modelRuntime' | 'options'>) {\n const debugCall = getDebug('ai:call');\n const { config: modelConfig, adapter } = modelRuntime;\n const modelCallInput: ModelRequestConfigInput = {\n intent: modelConfig.intent,\n userConfig: {\n temperature: modelConfig.temperature,\n reasoningEnabled: modelConfig.reasoningEnabled,\n reasoningEffort: modelConfig.reasoningEffort,\n reasoningBudget: modelConfig.reasoningBudget,\n responseFormat: modelConfig.responseFormat,\n },\n semanticRetryAttempt: options?.semanticRetryAttempt,\n requiresOriginalImageDetail: options?.requiresOriginalImageDetail,\n expectedJsonObjectResponse: options?.expectedJsonObjectResponse,\n };\n const { config } = adapter.responses.buildResponsesParams(modelCallInput);\n debugCall(`adapter responses params: ${stringifyForDebug({ config })}`);\n const resolveImageDetail: ResolveImageDetail = ({ imageDetail }) =>\n adapter.resolveImageDetail({\n imageDetail,\n intent: modelConfig.intent,\n requiresOriginalImageDetail: options?.requiresOriginalImageDetail,\n });\n const requestParams = { ...config, ...modelConfig.extraBody };\n if (requestParams.background === true) {\n throw new Error('Responses background mode is not supported');\n }\n const requestBodyParams: ResponsesCallOptions['requestBodyParams'] = {\n store: false,\n ...requestParams,\n model: modelConfig.modelName,\n input: toResponsesInput(messages, resolveImageDetail),\n };\n const proxyAgent = await createProxyAgentIfNeeded({\n socksProxy: modelConfig.socksProxy,\n httpProxy: modelConfig.httpProxy,\n });\n return {\n requestParams: requestBodyParams,\n proxyAgent,\n };\n}\n\nexport function callResponses(\n options: ResponsesCallOptions,\n stream: boolean,\n): Promise<OpenAIProtocolCallResult> {\n return stream\n ? callResponsesStream(options)\n : callResponsesNonStreaming(options);\n}\n"],"names":["prepareResponses","messages","modelRuntime","options","debugCall","getDebug","modelConfig","adapter","modelCallInput","config","stringifyForDebug","resolveImageDetail","imageDetail","requestParams","Error","requestBodyParams","toResponsesInput","proxyAgent","createProxyAgentIfNeeded","callResponses","stream","callResponsesStream","callResponsesNonStreaming"],"mappings":";;;;;;AAWO,eAAeA,iBAAiB,EACrCC,QAAQ,EACRC,YAAY,EACZC,OAAO,EACyD;IAChE,MAAMC,YAAYC,SAAS;IAC3B,MAAM,EAAE,QAAQC,WAAW,EAAEC,OAAO,EAAE,GAAGL;IACzC,MAAMM,iBAA0C;QAC9C,QAAQF,YAAY,MAAM;QAC1B,YAAY;YACV,aAAaA,YAAY,WAAW;YACpC,kBAAkBA,YAAY,gBAAgB;YAC9C,iBAAiBA,YAAY,eAAe;YAC5C,iBAAiBA,YAAY,eAAe;YAC5C,gBAAgBA,YAAY,cAAc;QAC5C;QACA,sBAAsBH,SAAS;QAC/B,6BAA6BA,SAAS;QACtC,4BAA4BA,SAAS;IACvC;IACA,MAAM,EAAEM,MAAM,EAAE,GAAGF,QAAQ,SAAS,CAAC,oBAAoB,CAACC;IAC1DJ,UAAU,CAAC,0BAA0B,EAAEM,kBAAkB;QAAED;IAAO,IAAI;IACtE,MAAME,qBAAyC,CAAC,EAAEC,WAAW,EAAE,GAC7DL,QAAQ,kBAAkB,CAAC;YACzBK;YACA,QAAQN,YAAY,MAAM;YAC1B,6BAA6BH,SAAS;QACxC;IACF,MAAMU,gBAAgB;QAAE,GAAGJ,MAAM;QAAE,GAAGH,YAAY,SAAS;IAAC;IAC5D,IAAIO,AAA6B,SAA7BA,cAAc,UAAU,EAC1B,MAAM,IAAIC,MAAM;IAElB,MAAMC,oBAA+D;QACnE,OAAO;QACP,GAAGF,aAAa;QAChB,OAAOP,YAAY,SAAS;QAC5B,OAAOU,iBAAiBf,UAAUU;IACpC;IACA,MAAMM,aAAa,MAAMC,yBAAyB;QAChD,YAAYZ,YAAY,UAAU;QAClC,WAAWA,YAAY,SAAS;IAClC;IACA,OAAO;QACL,eAAeS;QACfE;IACF;AACF;AAEO,SAASE,cACdhB,OAA6B,EAC7BiB,MAAe;IAEf,OAAOA,SACHC,oBAAoBlB,WACpBmB,0BAA0BnB;AAChC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { assert } from "@midscene/shared/utils";
|
|
2
|
+
import { AIResponseParseError, hasUsableText } from "../../utils.mjs";
|
|
3
|
+
import { parseResponse } from "./utils.mjs";
|
|
4
|
+
async function callResponsesStream({ responses, requestBodyParams, requestSignal, openAIRequestContext, onChunk, recordEvent }) {
|
|
5
|
+
assert('function' == typeof onChunk, 'onChunk is required when stream is true');
|
|
6
|
+
requestSignal.throwIfAborted();
|
|
7
|
+
const { data: stream, request_id: requestId } = await responses.create({
|
|
8
|
+
...requestBodyParams,
|
|
9
|
+
stream: true
|
|
10
|
+
}, {
|
|
11
|
+
signal: requestSignal
|
|
12
|
+
}).withResponse();
|
|
13
|
+
let accumulated = '';
|
|
14
|
+
let finalResponse;
|
|
15
|
+
let sequence = 0;
|
|
16
|
+
for await (const event of stream){
|
|
17
|
+
requestSignal.throwIfAborted();
|
|
18
|
+
recordEvent?.({
|
|
19
|
+
type: 'chunk',
|
|
20
|
+
sequence: ++sequence,
|
|
21
|
+
chunk: event
|
|
22
|
+
});
|
|
23
|
+
if ('error' === event.type) throw new Error(event.message);
|
|
24
|
+
if ('response.failed' === event.type || 'response.incomplete' === event.type) parseResponse(event.response);
|
|
25
|
+
if ('response.completed' === event.type) finalResponse = event.response;
|
|
26
|
+
const content = 'response.output_text.delta' === event.type ? event.delta : '';
|
|
27
|
+
const reasoningContent = 'response.reasoning_summary_text.delta' === event.type || 'response.reasoning_text.delta' === event.type ? event.delta : '';
|
|
28
|
+
if (content || reasoningContent) {
|
|
29
|
+
accumulated += content;
|
|
30
|
+
onChunk({
|
|
31
|
+
content,
|
|
32
|
+
reasoning_content: reasoningContent,
|
|
33
|
+
accumulated,
|
|
34
|
+
isComplete: false
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
requestSignal.throwIfAborted();
|
|
39
|
+
assert(finalResponse, 'Responses stream ended without a completed response');
|
|
40
|
+
const result = parseResponse(finalResponse);
|
|
41
|
+
if (!hasUsableText(result.content)) throw new AIResponseParseError('empty content from AI model', result.content, void 0, result.rawAssistantOutput);
|
|
42
|
+
onChunk({
|
|
43
|
+
content: '',
|
|
44
|
+
reasoning_content: '',
|
|
45
|
+
accumulated: result.content,
|
|
46
|
+
isComplete: true,
|
|
47
|
+
usage: result.rawUsage
|
|
48
|
+
});
|
|
49
|
+
return {
|
|
50
|
+
...result,
|
|
51
|
+
requestId: requestId ?? openAIRequestContext.responseRequestId?.requestId
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export { callResponsesStream };
|
|
55
|
+
|
|
56
|
+
//# sourceMappingURL=stream.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-model/service-caller/openai/responses/stream.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/responses/stream.ts"],"sourcesContent":["import { assert } from '@midscene/shared/utils';\nimport type { Response } from 'openai/resources/responses/responses';\nimport type { OpenAIProtocolCallResult } from '../../types';\nimport { AIResponseParseError, hasUsableText } from '../../utils';\nimport type { ResponsesCallOptions } from './types';\nimport { parseResponse } from './utils';\n\nexport async function callResponsesStream({\n responses,\n requestBodyParams,\n requestSignal,\n openAIRequestContext,\n onChunk,\n recordEvent,\n}: ResponsesCallOptions): Promise<OpenAIProtocolCallResult> {\n assert(\n typeof onChunk === 'function',\n 'onChunk is required when stream is true',\n );\n requestSignal.throwIfAborted();\n const { data: stream, request_id: requestId } = await responses\n .create({ ...requestBodyParams, stream: true }, { signal: requestSignal })\n .withResponse();\n let accumulated = '';\n let finalResponse: Response | undefined;\n let sequence = 0;\n for await (const event of stream) {\n requestSignal.throwIfAborted();\n recordEvent?.({ type: 'chunk', sequence: ++sequence, chunk: event });\n if (event.type === 'error') {\n throw new Error(event.message);\n }\n if (\n event.type === 'response.failed' ||\n event.type === 'response.incomplete'\n ) {\n parseResponse(event.response);\n }\n if (event.type === 'response.completed') {\n finalResponse = event.response;\n }\n const content =\n event.type === 'response.output_text.delta' ? event.delta : '';\n const reasoningContent =\n event.type === 'response.reasoning_summary_text.delta' ||\n event.type === 'response.reasoning_text.delta'\n ? event.delta\n : '';\n if (content || reasoningContent) {\n accumulated += content;\n onChunk({\n content,\n reasoning_content: reasoningContent,\n accumulated,\n isComplete: false,\n });\n }\n }\n requestSignal.throwIfAborted();\n assert(finalResponse, 'Responses stream ended without a completed response');\n const result = parseResponse(finalResponse);\n if (!hasUsableText(result.content)) {\n throw new AIResponseParseError(\n 'empty content from AI model',\n result.content,\n undefined,\n result.rawAssistantOutput,\n );\n }\n onChunk({\n content: '',\n reasoning_content: '',\n accumulated: result.content,\n isComplete: true,\n usage: result.rawUsage,\n });\n return {\n ...result,\n requestId: requestId ?? openAIRequestContext.responseRequestId?.requestId,\n };\n}\n"],"names":["callResponsesStream","responses","requestBodyParams","requestSignal","openAIRequestContext","onChunk","recordEvent","assert","stream","requestId","accumulated","finalResponse","sequence","event","Error","parseResponse","content","reasoningContent","result","hasUsableText","AIResponseParseError","undefined"],"mappings":";;;AAOO,eAAeA,oBAAoB,EACxCC,SAAS,EACTC,iBAAiB,EACjBC,aAAa,EACbC,oBAAoB,EACpBC,OAAO,EACPC,WAAW,EACU;IACrBC,OACE,AAAmB,cAAnB,OAAOF,SACP;IAEFF,cAAc,cAAc;IAC5B,MAAM,EAAE,MAAMK,MAAM,EAAE,YAAYC,SAAS,EAAE,GAAG,MAAMR,UACnD,MAAM,CAAC;QAAE,GAAGC,iBAAiB;QAAE,QAAQ;IAAK,GAAG;QAAE,QAAQC;IAAc,GACvE,YAAY;IACf,IAAIO,cAAc;IAClB,IAAIC;IACJ,IAAIC,WAAW;IACf,WAAW,MAAMC,SAASL,OAAQ;QAChCL,cAAc,cAAc;QAC5BG,cAAc;YAAE,MAAM;YAAS,UAAU,EAAEM;YAAU,OAAOC;QAAM;QAClE,IAAIA,AAAe,YAAfA,MAAM,IAAI,EACZ,MAAM,IAAIC,MAAMD,MAAM,OAAO;QAE/B,IACEA,AAAe,sBAAfA,MAAM,IAAI,IACVA,AAAe,0BAAfA,MAAM,IAAI,EAEVE,cAAcF,MAAM,QAAQ;QAE9B,IAAIA,AAAe,yBAAfA,MAAM,IAAI,EACZF,gBAAgBE,MAAM,QAAQ;QAEhC,MAAMG,UACJH,AAAe,iCAAfA,MAAM,IAAI,GAAoCA,MAAM,KAAK,GAAG;QAC9D,MAAMI,mBACJJ,AAAe,4CAAfA,MAAM,IAAI,IACVA,AAAe,oCAAfA,MAAM,IAAI,GACNA,MAAM,KAAK,GACX;QACN,IAAIG,WAAWC,kBAAkB;YAC/BP,eAAeM;YACfX,QAAQ;gBACNW;gBACA,mBAAmBC;gBACnBP;gBACA,YAAY;YACd;QACF;IACF;IACAP,cAAc,cAAc;IAC5BI,OAAOI,eAAe;IACtB,MAAMO,SAASH,cAAcJ;IAC7B,IAAI,CAACQ,cAAcD,OAAO,OAAO,GAC/B,MAAM,IAAIE,qBACR,+BACAF,OAAO,OAAO,EACdG,QACAH,OAAO,kBAAkB;IAG7Bb,QAAQ;QACN,SAAS;QACT,mBAAmB;QACnB,aAAaa,OAAO,OAAO;QAC3B,YAAY;QACZ,OAAOA,OAAO,QAAQ;IACxB;IACA,OAAO;QACL,GAAGA,MAAM;QACT,WAAWT,aAAaL,qBAAqB,iBAAiB,EAAE;IAClE;AACF"}
|
|
File without changes
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
function toResponsesInput(messages, resolveImageDetail) {
|
|
2
|
+
return messages.flatMap((entry)=>{
|
|
3
|
+
if ('type' in entry && 'model-output' === entry.type) {
|
|
4
|
+
if ('responses' !== entry.output.type) throw new Error('Cannot replay Chat Completions output in a Responses conversation');
|
|
5
|
+
return entry.output.rawValue;
|
|
6
|
+
}
|
|
7
|
+
const message = 'role' in entry ? entry : entry.message;
|
|
8
|
+
if ('string' == typeof message.content) return [
|
|
9
|
+
{
|
|
10
|
+
role: message.role,
|
|
11
|
+
content: message.content
|
|
12
|
+
}
|
|
13
|
+
];
|
|
14
|
+
if ('assistant' === message.role) return [
|
|
15
|
+
{
|
|
16
|
+
role: message.role,
|
|
17
|
+
content: message.content.map((part)=>part.text).join('')
|
|
18
|
+
}
|
|
19
|
+
];
|
|
20
|
+
return [
|
|
21
|
+
{
|
|
22
|
+
role: message.role,
|
|
23
|
+
content: message.content.map((part)=>{
|
|
24
|
+
if ('text' === part.type) return {
|
|
25
|
+
type: 'input_text',
|
|
26
|
+
text: part.text
|
|
27
|
+
};
|
|
28
|
+
return {
|
|
29
|
+
type: 'input_image',
|
|
30
|
+
image_url: part.url,
|
|
31
|
+
detail: resolveImageDetail({
|
|
32
|
+
imageDetail: part.detail
|
|
33
|
+
})
|
|
34
|
+
};
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
];
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function mapResponsesUsage(usage) {
|
|
41
|
+
if (!usage) return;
|
|
42
|
+
return {
|
|
43
|
+
prompt_tokens: usage.input_tokens,
|
|
44
|
+
completion_tokens: usage.output_tokens,
|
|
45
|
+
total_tokens: usage.total_tokens,
|
|
46
|
+
prompt_tokens_details: usage.input_tokens_details,
|
|
47
|
+
completion_tokens_details: usage.output_tokens_details
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function parseResponse(response) {
|
|
51
|
+
if ('completed' !== response.status) throw new Error(`Responses request ${response.status}: ${response.error?.message ?? response.incomplete_details?.reason ?? 'response did not complete'}`);
|
|
52
|
+
const content = response.output.flatMap((item)=>'message' === item.type ? item.content.flatMap((part)=>'output_text' === part.type ? [
|
|
53
|
+
part.text
|
|
54
|
+
] : []) : []).join('');
|
|
55
|
+
const reasoningContent = response.output.flatMap((item)=>{
|
|
56
|
+
if ('reasoning' !== item.type) return [];
|
|
57
|
+
return (item.content?.length ? item.content : item.summary).map((part)=>part.text);
|
|
58
|
+
}).join('');
|
|
59
|
+
return {
|
|
60
|
+
content,
|
|
61
|
+
reasoningContent,
|
|
62
|
+
rawAssistantOutput: {
|
|
63
|
+
type: 'responses',
|
|
64
|
+
rawValue: response.output
|
|
65
|
+
},
|
|
66
|
+
rawUsage: mapResponsesUsage(response.usage),
|
|
67
|
+
responseModelName: response.model
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export { mapResponsesUsage, parseResponse, toResponsesInput };
|
|
71
|
+
|
|
72
|
+
//# sourceMappingURL=utils.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-model/service-caller/openai/responses/utils.mjs","sources":["../../../../../../src/ai-model/service-caller/openai/responses/utils.ts"],"sourcesContent":["import type OpenAI from 'openai';\nimport type {\n Response,\n ResponseInput,\n ResponseInputImage,\n ResponseUsage,\n} from 'openai/resources/responses/responses';\nimport type { ResolveImageDetail } from '../../../model-adapter/types';\nimport type { ModelCallMessages, OpenAIProtocolCallResult } from '../../types';\n\nexport function toResponsesInput(\n messages: ModelCallMessages,\n resolveImageDetail: ResolveImageDetail,\n): ResponseInput {\n return messages.flatMap((entry): ResponseInput => {\n if ('type' in entry && entry.type === 'model-output') {\n if (entry.output.type !== 'responses') {\n throw new Error(\n 'Cannot replay Chat Completions output in a Responses conversation',\n );\n }\n return entry.output.rawValue;\n }\n const message = 'role' in entry ? entry : entry.message;\n if (typeof message.content === 'string') {\n return [{ role: message.role, content: message.content }];\n }\n if (message.role === 'assistant') {\n return [\n {\n role: message.role,\n content: message.content.map((part) => part.text).join(''),\n },\n ];\n }\n return [\n {\n role: message.role,\n content: message.content.map((part) => {\n if (part.type === 'text') {\n return { type: 'input_text' as const, text: part.text };\n }\n return {\n type: 'input_image' as const,\n image_url: part.url,\n // The installed SDK does not yet type `original`.\n detail: resolveImageDetail({\n imageDetail: part.detail,\n }) as ResponseInputImage['detail'],\n };\n }),\n },\n ];\n });\n}\n\nexport function mapResponsesUsage(\n usage: ResponseUsage | undefined,\n): OpenAI.CompletionUsage | undefined {\n if (!usage) {\n return undefined;\n }\n return {\n prompt_tokens: usage.input_tokens,\n completion_tokens: usage.output_tokens,\n total_tokens: usage.total_tokens,\n prompt_tokens_details: usage.input_tokens_details,\n completion_tokens_details: usage.output_tokens_details,\n };\n}\n\nexport function parseResponse(response: Response): OpenAIProtocolCallResult {\n if (response.status !== 'completed') {\n throw new Error(\n `Responses request ${response.status}: ${response.error?.message ?? response.incomplete_details?.reason ?? 'response did not complete'}`,\n );\n }\n const content = response.output\n .flatMap((item) =>\n item.type === 'message'\n ? item.content.flatMap((part) =>\n part.type === 'output_text' ? [part.text] : [],\n )\n : [],\n )\n .join('');\n const reasoningContent = response.output\n .flatMap((item) => {\n if (item.type !== 'reasoning') {\n return [];\n }\n return (item.content?.length ? item.content : item.summary).map(\n (part) => part.text,\n );\n })\n .join('');\n return {\n content,\n reasoningContent,\n rawAssistantOutput: { type: 'responses', rawValue: response.output },\n rawUsage: mapResponsesUsage(response.usage),\n responseModelName: response.model,\n };\n}\n"],"names":["toResponsesInput","messages","resolveImageDetail","entry","Error","message","part","mapResponsesUsage","usage","parseResponse","response","content","item","reasoningContent"],"mappings":"AAUO,SAASA,iBACdC,QAA2B,EAC3BC,kBAAsC;IAEtC,OAAOD,SAAS,OAAO,CAAC,CAACE;QACvB,IAAI,UAAUA,SAASA,AAAe,mBAAfA,MAAM,IAAI,EAAqB;YACpD,IAAIA,AAAsB,gBAAtBA,MAAM,MAAM,CAAC,IAAI,EACnB,MAAM,IAAIC,MACR;YAGJ,OAAOD,MAAM,MAAM,CAAC,QAAQ;QAC9B;QACA,MAAME,UAAU,UAAUF,QAAQA,QAAQA,MAAM,OAAO;QACvD,IAAI,AAA2B,YAA3B,OAAOE,QAAQ,OAAO,EACxB,OAAO;YAAC;gBAAE,MAAMA,QAAQ,IAAI;gBAAE,SAASA,QAAQ,OAAO;YAAC;SAAE;QAE3D,IAAIA,AAAiB,gBAAjBA,QAAQ,IAAI,EACd,OAAO;YACL;gBACE,MAAMA,QAAQ,IAAI;gBAClB,SAASA,QAAQ,OAAO,CAAC,GAAG,CAAC,CAACC,OAASA,KAAK,IAAI,EAAE,IAAI,CAAC;YACzD;SACD;QAEH,OAAO;YACL;gBACE,MAAMD,QAAQ,IAAI;gBAClB,SAASA,QAAQ,OAAO,CAAC,GAAG,CAAC,CAACC;oBAC5B,IAAIA,AAAc,WAAdA,KAAK,IAAI,EACX,OAAO;wBAAE,MAAM;wBAAuB,MAAMA,KAAK,IAAI;oBAAC;oBAExD,OAAO;wBACL,MAAM;wBACN,WAAWA,KAAK,GAAG;wBAEnB,QAAQJ,mBAAmB;4BACzB,aAAaI,KAAK,MAAM;wBAC1B;oBACF;gBACF;YACF;SACD;IACH;AACF;AAEO,SAASC,kBACdC,KAAgC;IAEhC,IAAI,CAACA,OACH;IAEF,OAAO;QACL,eAAeA,MAAM,YAAY;QACjC,mBAAmBA,MAAM,aAAa;QACtC,cAAcA,MAAM,YAAY;QAChC,uBAAuBA,MAAM,oBAAoB;QACjD,2BAA2BA,MAAM,qBAAqB;IACxD;AACF;AAEO,SAASC,cAAcC,QAAkB;IAC9C,IAAIA,AAAoB,gBAApBA,SAAS,MAAM,EACjB,MAAM,IAAIN,MACR,CAAC,kBAAkB,EAAEM,SAAS,MAAM,CAAC,EAAE,EAAEA,SAAS,KAAK,EAAE,WAAWA,SAAS,kBAAkB,EAAE,UAAU,6BAA6B;IAG5I,MAAMC,UAAUD,SAAS,MAAM,CAC5B,OAAO,CAAC,CAACE,OACRA,AAAc,cAAdA,KAAK,IAAI,GACLA,KAAK,OAAO,CAAC,OAAO,CAAC,CAACN,OACpBA,AAAc,kBAAdA,KAAK,IAAI,GAAqB;gBAACA,KAAK,IAAI;aAAC,GAAG,EAAE,IAEhD,EAAE,EAEP,IAAI,CAAC;IACR,MAAMO,mBAAmBH,SAAS,MAAM,CACrC,OAAO,CAAC,CAACE;QACR,IAAIA,AAAc,gBAAdA,KAAK,IAAI,EACX,OAAO,EAAE;QAEX,OAAQA,AAAAA,CAAAA,KAAK,OAAO,EAAE,SAASA,KAAK,OAAO,GAAGA,KAAK,OAAM,EAAG,GAAG,CAC7D,CAACN,OAASA,KAAK,IAAI;IAEvB,GACC,IAAI,CAAC;IACR,OAAO;QACLK;QACAE;QACA,oBAAoB;YAAE,MAAM;YAAa,UAAUH,SAAS,MAAM;QAAC;QACnE,UAAUH,kBAAkBG,SAAS,KAAK;QAC1C,mBAAmBA,SAAS,KAAK;IACnC;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-model/service-caller/semantic-retry.mjs","sources":["../../../../src/ai-model/service-caller/semantic-retry.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"ai-model/service-caller/semantic-retry.mjs","sources":["../../../../src/ai-model/service-caller/semantic-retry.ts"],"sourcesContent":["import { waitForRetry } from './request-timeout';\nimport type { ModelCallMessages } from './types';\n\nexport function withSemanticRetryFeedback(\n messages: ModelCallMessages,\n previousParseError?: unknown,\n): ModelCallMessages {\n if (!previousParseError) return messages;\n\n const errorMessage =\n previousParseError instanceof Error\n ? previousParseError.message\n : String(previousParseError);\n\n return [\n ...messages,\n {\n role: 'user',\n content: `The previous response was invalid:\\n${errorMessage}\\n\\nPlease avoid the validation error above in this response.`,\n },\n ];\n}\n\nexport type CallAiAndParseWithRetryOptions<Response, Parsed> = {\n /** Sends a single model request. Request errors are always propagated as-is. */\n /**\n * `retryAttempt` is local to this retry loop: 0 for the initial request,\n * then incremented after each parsing failure.\n */\n callAi: (\n retryAttempt: number,\n previousParseError?: unknown,\n ) => Promise<Response>;\n /** Parses a successful model response. Only failures from this callback retry. */\n parseResponse: (response: Response) => Parsed | Promise<Parsed>;\n /** Converts the final parsing failure into the caller's domain error. */\n toParseError: (error: unknown, response: Response) => Error;\n /** Number of additional model requests after a parsing failure. Defaults to 0. */\n parseRetryTimes?: number;\n /** Delay in milliseconds before retrying a parsing failure. Defaults to 0. */\n parseRetryInterval?: number;\n abortSignal?: AbortSignal;\n /** Runs immediately before a parsing failure triggers another model request. */\n onParseRetry?: (error: unknown, response: Response) => void;\n};\n\n/**\n * Calls AI and parses its response, retrying only when the response cannot be\n * structurally parsed.\n *\n * Errors thrown by callAi() intentionally bypass this retry mechanism and are\n * propagated as-is. Only a successful callAi() response that fails the\n * parseResponse() callback triggers another model request.\n */\nexport async function callAiAndParseWithRetry<Response, Parsed>({\n callAi,\n parseResponse,\n toParseError,\n parseRetryTimes = 0,\n parseRetryInterval = 0,\n abortSignal,\n onParseRetry,\n}: CallAiAndParseWithRetryOptions<Response, Parsed>): Promise<Parsed> {\n const normalizedRetryTimes = Number.isFinite(parseRetryTimes)\n ? Math.max(0, Math.floor(parseRetryTimes))\n : 0;\n const normalizedRetryInterval = Number.isFinite(parseRetryInterval)\n ? Math.max(0, parseRetryInterval)\n : 0;\n\n const callAndParseOnce = async (\n remainingRetries: number,\n retryAttempt: number,\n previousParseError?: unknown,\n ): Promise<Parsed> => {\n abortSignal?.throwIfAborted();\n const response = await callAi(retryAttempt, previousParseError);\n\n try {\n const parsed = await parseResponse(response);\n abortSignal?.throwIfAborted();\n return parsed;\n } catch (error) {\n abortSignal?.throwIfAborted();\n if (remainingRetries > 0) {\n onParseRetry?.(error, response);\n if (normalizedRetryInterval > 0) {\n await waitForRetry(normalizedRetryInterval, abortSignal);\n }\n abortSignal?.throwIfAborted();\n return callAndParseOnce(remainingRetries - 1, retryAttempt + 1, error);\n }\n throw toParseError(error, response);\n }\n };\n\n return callAndParseOnce(normalizedRetryTimes, 0);\n}\n"],"names":["withSemanticRetryFeedback","messages","previousParseError","errorMessage","Error","String","callAiAndParseWithRetry","callAi","parseResponse","toParseError","parseRetryTimes","parseRetryInterval","abortSignal","onParseRetry","normalizedRetryTimes","Number","Math","normalizedRetryInterval","callAndParseOnce","remainingRetries","retryAttempt","response","parsed","error","waitForRetry"],"mappings":";AAGO,SAASA,0BACdC,QAA2B,EAC3BC,kBAA4B;IAE5B,IAAI,CAACA,oBAAoB,OAAOD;IAEhC,MAAME,eACJD,8BAA8BE,QAC1BF,mBAAmB,OAAO,GAC1BG,OAAOH;IAEb,OAAO;WACFD;QACH;YACE,MAAM;YACN,SAAS,CAAC,oCAAoC,EAAEE,aAAa,6DAA6D,CAAC;QAC7H;KACD;AACH;AAiCO,eAAeG,wBAA0C,EAC9DC,MAAM,EACNC,aAAa,EACbC,YAAY,EACZC,kBAAkB,CAAC,EACnBC,qBAAqB,CAAC,EACtBC,WAAW,EACXC,YAAY,EACqC;IACjD,MAAMC,uBAAuBC,OAAO,QAAQ,CAACL,mBACzCM,KAAK,GAAG,CAAC,GAAGA,KAAK,KAAK,CAACN,oBACvB;IACJ,MAAMO,0BAA0BF,OAAO,QAAQ,CAACJ,sBAC5CK,KAAK,GAAG,CAAC,GAAGL,sBACZ;IAEJ,MAAMO,mBAAmB,OACvBC,kBACAC,cACAlB;QAEAU,aAAa;QACb,MAAMS,WAAW,MAAMd,OAAOa,cAAclB;QAE5C,IAAI;YACF,MAAMoB,SAAS,MAAMd,cAAca;YACnCT,aAAa;YACb,OAAOU;QACT,EAAE,OAAOC,OAAO;YACdX,aAAa;YACb,IAAIO,mBAAmB,GAAG;gBACxBN,eAAeU,OAAOF;gBACtB,IAAIJ,0BAA0B,GAC5B,MAAMO,aAAaP,yBAAyBL;gBAE9CA,aAAa;gBACb,OAAOM,iBAAiBC,mBAAmB,GAAGC,eAAe,GAAGG;YAClE;YACA,MAAMd,aAAac,OAAOF;QAC5B;IACF;IAEA,OAAOH,iBAAiBJ,sBAAsB;AAChD"}
|
|
@@ -9,12 +9,12 @@ function _define_property(obj, key, value) {
|
|
|
9
9
|
return obj;
|
|
10
10
|
}
|
|
11
11
|
class AIResponseParseError extends Error {
|
|
12
|
-
constructor(message, rawResponse, usage,
|
|
13
|
-
super(message), _define_property(this, "usage", void 0), _define_property(this, "rawResponse", void 0), _define_property(this, "
|
|
12
|
+
constructor(message, rawResponse, usage, rawAssistantOutput, reasoningContent){
|
|
13
|
+
super(message), _define_property(this, "usage", void 0), _define_property(this, "rawResponse", void 0), _define_property(this, "rawAssistantOutput", void 0), _define_property(this, "reasoningContent", void 0);
|
|
14
14
|
this.name = 'AIResponseParseError';
|
|
15
15
|
this.rawResponse = rawResponse;
|
|
16
16
|
this.usage = usage;
|
|
17
|
-
this.
|
|
17
|
+
this.rawAssistantOutput = rawAssistantOutput;
|
|
18
18
|
this.reasoningContent = reasoningContent;
|
|
19
19
|
}
|
|
20
20
|
}
|
|
@@ -53,11 +53,12 @@ function appendAIRequestFailureSummary(error, attemptErrors, maxAttempts) {
|
|
|
53
53
|
error.message = `${error.message}\nPrevious AI call attempt errors:\n${details}`;
|
|
54
54
|
return error;
|
|
55
55
|
}
|
|
56
|
-
const buildUsageInfo = ({ usageData, requestId, timeCost, totalTimeCost, retryCount, modelName, modelDescription, responseModelName, slot, internalCallId })=>{
|
|
56
|
+
const buildUsageInfo = ({ apiType, usageData, requestId, timeCost, totalTimeCost, retryCount, modelName, modelDescription, responseModelName, slot, internalCallId })=>{
|
|
57
57
|
if (!usageData) return;
|
|
58
58
|
const cachedInputTokens = usageData?.prompt_tokens_details?.cached_tokens;
|
|
59
59
|
return {
|
|
60
60
|
...usageData,
|
|
61
|
+
api_type: apiType,
|
|
61
62
|
prompt_tokens: usageData.prompt_tokens ?? 0,
|
|
62
63
|
completion_tokens: usageData.completion_tokens ?? 0,
|
|
63
64
|
total_tokens: usageData.total_tokens ?? 0,
|
|
@@ -74,27 +75,7 @@ const buildUsageInfo = ({ usageData, requestId, timeCost, totalTimeCost, retryCo
|
|
|
74
75
|
[INTERNAL_CALL_ID_FIELD]: internalCallId
|
|
75
76
|
};
|
|
76
77
|
};
|
|
77
|
-
const applyImageDetail = ({ imageDetail, messages })=>{
|
|
78
|
-
if (!imageDetail) return messages;
|
|
79
|
-
return messages.map((msg)=>{
|
|
80
|
-
if (!Array.isArray(msg.content)) return msg;
|
|
81
|
-
const content = msg.content.map((part)=>{
|
|
82
|
-
if (part && 'image_url' === part.type && part.image_url?.url) return {
|
|
83
|
-
...part,
|
|
84
|
-
image_url: {
|
|
85
|
-
...part.image_url,
|
|
86
|
-
detail: imageDetail
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
return part;
|
|
90
|
-
});
|
|
91
|
-
return {
|
|
92
|
-
...msg,
|
|
93
|
-
content
|
|
94
|
-
};
|
|
95
|
-
});
|
|
96
|
-
};
|
|
97
78
|
const hasUsableText = (value)=>'string' == typeof value && value.trim().length > 0;
|
|
98
|
-
export { AIResponseParseError, INTERNAL_CALL_ID_FIELD, appendAIRequestFailureSummary,
|
|
79
|
+
export { AIResponseParseError, INTERNAL_CALL_ID_FIELD, appendAIRequestFailureSummary, buildUsageInfo, hasUsableText, nextInternalCallId, normalizeRetryCount, stringifyForDebug, toError };
|
|
99
80
|
|
|
100
81
|
//# sourceMappingURL=utils.mjs.map
|