@midscene/core 1.16.2 → 1.16.6-beta-20261023073257.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/agent.mjs +11 -11
- package/dist/es/agent/agent.mjs.map +1 -1
- package/dist/es/agent/insight.mjs.map +1 -1
- package/dist/es/agent/tasks.mjs +72 -39
- 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 +27 -22
- package/dist/es/ai-model/connectivity/run-connectivity-test.mjs.map +1 -1
- package/dist/es/ai-model/index.mjs +4 -2
- package/dist/es/ai-model/model-adapter/resolve.mjs +4 -2
- package/dist/es/ai-model/model-adapter/resolve.mjs.map +1 -1
- package/dist/es/ai-model/models/jev/adapter.mjs +6 -110
- package/dist/es/ai-model/models/jev/adapter.mjs.map +1 -1
- package/dist/es/ai-model/models/jev/boolean.mjs +48 -0
- package/dist/es/ai-model/models/jev/boolean.mjs.map +1 -0
- package/dist/es/ai-model/models/jev/image.mjs +39 -36
- package/dist/es/ai-model/models/jev/image.mjs.map +1 -1
- package/dist/es/ai-model/models/jev/locate.mjs +48 -0
- package/dist/es/ai-model/models/jev/locate.mjs.map +1 -0
- package/dist/es/ai-model/models/jev/planning-action.mjs +35 -0
- package/dist/es/ai-model/models/jev/planning-action.mjs.map +1 -0
- package/dist/es/ai-model/models/jev/planning-context.mjs +38 -0
- package/dist/es/ai-model/models/jev/planning-context.mjs.map +1 -0
- package/dist/es/ai-model/models/jev/planning-decision.mjs +68 -0
- package/dist/es/ai-model/models/jev/planning-decision.mjs.map +1 -0
- package/dist/es/ai-model/models/jev/planning.mjs +19 -131
- package/dist/es/ai-model/models/jev/planning.mjs.map +1 -1
- package/dist/es/ai-model/models/model-fallback.mjs +28 -0
- package/dist/es/ai-model/models/model-fallback.mjs.map +1 -0
- package/dist/es/ai-model/service-caller/call-ai.mjs +54 -27
- package/dist/es/ai-model/service-caller/call-ai.mjs.map +1 -1
- package/dist/es/ai-model/service-caller/codex/call-codex.mjs.map +1 -1
- package/dist/es/ai-model/service-caller/index.mjs +2 -2
- package/dist/es/ai-model/service-caller/model-call.mjs +3 -3
- package/dist/es/ai-model/service-caller/model-call.mjs.map +1 -1
- package/dist/es/ai-model/service-caller/openai/call-openai.mjs +4 -2
- 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.map +1 -1
- package/dist/es/ai-model/service-caller/openai/openai-client.mjs.map +1 -1
- package/dist/es/ai-model/service-caller/openai/responses/responses.mjs.map +1 -1
- package/dist/es/ai-model/service-caller/openai/siwc/authorization.mjs +117 -0
- package/dist/es/ai-model/service-caller/openai/siwc/authorization.mjs.map +1 -0
- package/dist/es/ai-model/service-caller/openai/siwc/credential-storage.mjs +66 -0
- package/dist/es/ai-model/service-caller/openai/siwc/credential-storage.mjs.map +1 -0
- package/dist/es/ai-model/service-caller/openai/siwc/errors.mjs +42 -0
- package/dist/es/ai-model/service-caller/openai/siwc/errors.mjs.map +1 -0
- package/dist/es/ai-model/service-caller/openai/siwc/index.mjs +7 -0
- package/dist/es/ai-model/service-caller/openai/siwc/prepare-call.mjs +33 -0
- package/dist/es/ai-model/service-caller/openai/siwc/prepare-call.mjs.map +1 -0
- package/dist/es/ai-model/service-caller/openai/siwc/refresh.mjs +60 -0
- package/dist/es/ai-model/service-caller/openai/siwc/refresh.mjs.map +1 -0
- package/dist/es/ai-model/service-caller/openai/siwc/token-manager.mjs +51 -0
- package/dist/es/ai-model/service-caller/openai/siwc/token-manager.mjs.map +1 -0
- package/dist/es/ai-model/service-caller/system-one/call-system-one.mjs +69 -0
- package/dist/es/ai-model/service-caller/system-one/call-system-one.mjs.map +1 -0
- package/dist/es/ai-model/service-caller/system-one/index.mjs +3 -0
- package/dist/es/ai-model/service-caller/system-one/prepare-system-one.mjs +44 -0
- package/dist/es/ai-model/service-caller/system-one/prepare-system-one.mjs.map +1 -0
- package/dist/es/ai-model/service-caller/system-one/schema.mjs +32 -0
- package/dist/es/ai-model/service-caller/system-one/schema.mjs.map +1 -0
- package/dist/es/ai-model/service-caller/system-one/utils.mjs +34 -0
- package/dist/es/ai-model/service-caller/system-one/utils.mjs.map +1 -0
- package/dist/es/ai-model/service-caller/utils.mjs +2 -2
- package/dist/es/ai-model/service-caller/utils.mjs.map +1 -1
- package/dist/es/ai-model/shared/model-locate-result/factory.mjs +7 -3
- package/dist/es/ai-model/shared/model-locate-result/factory.mjs.map +1 -1
- package/dist/es/ai-model/shared/model-locate-result/pixel-mapper.mjs +10 -4
- package/dist/es/ai-model/shared/model-locate-result/pixel-mapper.mjs.map +1 -1
- package/dist/es/ai-model/shared/model-locate-result/types.mjs.map +1 -1
- package/dist/es/ai-model/shared/model-locate-result/validation.mjs +4 -0
- package/dist/es/ai-model/shared/model-locate-result/validation.mjs.map +1 -1
- package/dist/es/ai-model/workflows/grounding/locate.mjs +2 -2
- package/dist/es/ai-model/workflows/grounding/locate.mjs.map +1 -1
- package/dist/es/ai-model/workflows/grounding/section-locate.mjs +2 -2
- package/dist/es/ai-model/workflows/grounding/section-locate.mjs.map +1 -1
- package/dist/es/ai-model/workflows/insight/boolean.mjs +1 -1
- package/dist/es/ai-model/workflows/insight/boolean.mjs.map +1 -1
- package/dist/es/ai-model/workflows/insight/extraction.mjs +3 -3
- package/dist/es/ai-model/workflows/insight/extraction.mjs.map +1 -1
- package/dist/es/ai-model/workflows/planning/standard-planning.mjs +4 -3
- package/dist/es/ai-model/workflows/planning/standard-planning.mjs.map +1 -1
- package/dist/es/ai-model/workflows/recorder-generation/playwright.mjs +2 -2
- package/dist/es/ai-model/workflows/recorder-generation/playwright.mjs.map +1 -1
- package/dist/es/ai-model/workflows/recorder-generation/yaml.mjs +2 -2
- package/dist/es/ai-model/workflows/recorder-generation/yaml.mjs.map +1 -1
- package/dist/es/device/index.mjs +7 -0
- package/dist/es/device/index.mjs.map +1 -1
- package/dist/es/report-html-template.mjs +1 -1
- package/dist/es/service/index.mjs +2 -1
- 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/agent.js +11 -11
- package/dist/lib/agent/agent.js.map +1 -1
- package/dist/lib/agent/insight.js.map +1 -1
- package/dist/lib/agent/tasks.js +72 -39
- 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 +27 -22
- package/dist/lib/ai-model/connectivity/run-connectivity-test.js.map +1 -1
- package/dist/lib/ai-model/index.js +34 -5
- package/dist/lib/ai-model/model-adapter/resolve.js +4 -2
- package/dist/lib/ai-model/model-adapter/resolve.js.map +1 -1
- package/dist/lib/ai-model/models/jev/adapter.js +6 -110
- package/dist/lib/ai-model/models/jev/adapter.js.map +1 -1
- package/dist/lib/ai-model/models/jev/boolean.js +82 -0
- package/dist/lib/ai-model/models/jev/boolean.js.map +1 -0
- package/dist/lib/ai-model/models/jev/image.js +41 -35
- package/dist/lib/ai-model/models/jev/image.js.map +1 -1
- package/dist/lib/ai-model/models/jev/locate.js +82 -0
- package/dist/lib/ai-model/models/jev/locate.js.map +1 -0
- package/dist/lib/ai-model/models/jev/planning-action.js +69 -0
- package/dist/lib/ai-model/models/jev/planning-action.js.map +1 -0
- package/dist/lib/ai-model/models/jev/planning-context.js +72 -0
- package/dist/lib/ai-model/models/jev/planning-context.js.map +1 -0
- package/dist/lib/ai-model/models/jev/planning-decision.js +102 -0
- package/dist/lib/ai-model/models/jev/planning-decision.js.map +1 -0
- package/dist/lib/ai-model/models/jev/planning.js +19 -131
- package/dist/lib/ai-model/models/jev/planning.js.map +1 -1
- package/dist/lib/ai-model/models/{task-routing.js → model-fallback.js} +11 -11
- package/dist/lib/ai-model/models/model-fallback.js.map +1 -0
- package/dist/lib/ai-model/service-caller/call-ai.js +59 -29
- package/dist/lib/ai-model/service-caller/call-ai.js.map +1 -1
- package/dist/lib/ai-model/service-caller/codex/call-codex.js.map +1 -1
- package/dist/lib/ai-model/service-caller/index.js +6 -3
- package/dist/lib/ai-model/service-caller/model-call.js +2 -2
- package/dist/lib/ai-model/service-caller/model-call.js.map +1 -1
- package/dist/lib/ai-model/service-caller/openai/call-openai.js +4 -2
- 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.map +1 -1
- package/dist/lib/ai-model/service-caller/openai/openai-client.js.map +1 -1
- package/dist/lib/ai-model/service-caller/openai/responses/responses.js.map +1 -1
- package/dist/lib/ai-model/service-caller/openai/siwc/authorization.js +157 -0
- package/dist/lib/ai-model/service-caller/openai/siwc/authorization.js.map +1 -0
- package/dist/lib/ai-model/service-caller/openai/siwc/credential-storage.js +103 -0
- package/dist/lib/ai-model/service-caller/openai/siwc/credential-storage.js.map +1 -0
- package/dist/lib/ai-model/service-caller/openai/siwc/errors.js +85 -0
- package/dist/lib/ai-model/service-caller/openai/siwc/errors.js.map +1 -0
- package/dist/lib/ai-model/service-caller/openai/siwc/index.js +64 -0
- package/dist/lib/ai-model/service-caller/openai/siwc/index.js.map +1 -0
- package/dist/lib/ai-model/service-caller/openai/siwc/prepare-call.js +67 -0
- package/dist/lib/ai-model/service-caller/openai/siwc/prepare-call.js.map +1 -0
- package/dist/lib/ai-model/service-caller/openai/siwc/refresh.js +94 -0
- package/dist/lib/ai-model/service-caller/openai/siwc/refresh.js.map +1 -0
- package/dist/lib/ai-model/service-caller/openai/siwc/token-manager.js +85 -0
- package/dist/lib/ai-model/service-caller/openai/siwc/token-manager.js.map +1 -0
- package/dist/lib/ai-model/service-caller/system-one/call-system-one.js +103 -0
- package/dist/lib/ai-model/service-caller/system-one/call-system-one.js.map +1 -0
- package/dist/lib/ai-model/service-caller/system-one/index.js +42 -0
- package/dist/lib/ai-model/service-caller/system-one/index.js.map +1 -0
- package/dist/lib/ai-model/service-caller/system-one/prepare-system-one.js +78 -0
- package/dist/lib/ai-model/service-caller/system-one/prepare-system-one.js.map +1 -0
- package/dist/lib/ai-model/service-caller/system-one/schema.js +69 -0
- package/dist/lib/ai-model/service-caller/system-one/schema.js.map +1 -0
- package/dist/lib/ai-model/service-caller/system-one/utils.js +68 -0
- package/dist/lib/ai-model/service-caller/system-one/utils.js.map +1 -0
- package/dist/lib/ai-model/service-caller/utils.js +2 -2
- package/dist/lib/ai-model/service-caller/utils.js.map +1 -1
- package/dist/lib/ai-model/shared/model-locate-result/factory.js +7 -3
- package/dist/lib/ai-model/shared/model-locate-result/factory.js.map +1 -1
- package/dist/lib/ai-model/shared/model-locate-result/pixel-mapper.js +10 -4
- package/dist/lib/ai-model/shared/model-locate-result/pixel-mapper.js.map +1 -1
- package/dist/lib/ai-model/shared/model-locate-result/types.js.map +1 -1
- package/dist/lib/ai-model/shared/model-locate-result/validation.js +4 -0
- package/dist/lib/ai-model/shared/model-locate-result/validation.js.map +1 -1
- package/dist/lib/ai-model/workflows/grounding/locate.js +1 -1
- package/dist/lib/ai-model/workflows/grounding/locate.js.map +1 -1
- package/dist/lib/ai-model/workflows/grounding/section-locate.js +1 -1
- package/dist/lib/ai-model/workflows/grounding/section-locate.js.map +1 -1
- package/dist/lib/ai-model/workflows/insight/boolean.js +1 -1
- package/dist/lib/ai-model/workflows/insight/boolean.js.map +1 -1
- package/dist/lib/ai-model/workflows/insight/extraction.js +2 -2
- package/dist/lib/ai-model/workflows/insight/extraction.js.map +1 -1
- package/dist/lib/ai-model/workflows/planning/standard-planning.js +3 -2
- package/dist/lib/ai-model/workflows/planning/standard-planning.js.map +1 -1
- package/dist/lib/ai-model/workflows/recorder-generation/playwright.js +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 +1 -1
- package/dist/lib/ai-model/workflows/recorder-generation/yaml.js.map +1 -1
- package/dist/lib/device/index.js +7 -0
- package/dist/lib/device/index.js.map +1 -1
- package/dist/lib/report-html-template.js +1 -1
- package/dist/lib/service/index.js +2 -1
- package/dist/lib/service/index.js.map +1 -1
- package/dist/lib/test-runner/engine/index.js +2 -2
- package/dist/lib/test-runner/node/index.js +2 -2
- package/dist/lib/types.js.map +1 -1
- package/dist/lib/utils.js +1 -1
- package/dist/types/agent/agent.d.ts.map +1 -1
- package/dist/types/agent/insight.d.ts +2 -2
- package/dist/types/agent/insight.d.ts.map +1 -1
- package/dist/types/agent/tasks.d.ts.map +1 -1
- package/dist/types/ai-model/connectivity/run-connectivity-test.d.ts.map +1 -1
- package/dist/types/ai-model/index.d.ts +4 -1
- package/dist/types/ai-model/index.d.ts.map +1 -1
- package/dist/types/ai-model/model-adapter/resolve.d.ts +2 -1
- package/dist/types/ai-model/model-adapter/resolve.d.ts.map +1 -1
- package/dist/types/ai-model/model-adapter/types.d.ts +8 -5
- package/dist/types/ai-model/model-adapter/types.d.ts.map +1 -1
- package/dist/types/ai-model/models/gpt.d.ts +2 -2
- package/dist/types/ai-model/models/jev/adapter.d.ts +4 -5
- package/dist/types/ai-model/models/jev/adapter.d.ts.map +1 -1
- package/dist/types/ai-model/models/jev/boolean.d.ts +3 -0
- package/dist/types/ai-model/models/jev/boolean.d.ts.map +1 -0
- package/dist/types/ai-model/models/jev/image.d.ts +11 -11
- package/dist/types/ai-model/models/jev/image.d.ts.map +1 -1
- package/dist/types/ai-model/models/jev/locate.d.ts +3 -0
- package/dist/types/ai-model/models/jev/locate.d.ts.map +1 -0
- package/dist/types/ai-model/models/jev/planning-action.d.ts +6 -0
- package/dist/types/ai-model/models/jev/planning-action.d.ts.map +1 -0
- package/dist/types/ai-model/models/jev/planning-context.d.ts +23 -0
- package/dist/types/ai-model/models/jev/planning-context.d.ts.map +1 -0
- package/dist/types/ai-model/models/jev/planning-decision.d.ts +35 -0
- package/dist/types/ai-model/models/jev/planning-decision.d.ts.map +1 -0
- package/dist/types/ai-model/models/jev/planning.d.ts.map +1 -1
- package/dist/types/ai-model/models/model-fallback.d.ts +6 -0
- package/dist/types/ai-model/models/model-fallback.d.ts.map +1 -0
- package/dist/types/ai-model/models/registry.d.ts +4 -3
- package/dist/types/ai-model/models/registry.d.ts.map +1 -1
- package/dist/types/ai-model/service-caller/call-ai.d.ts +3 -1
- 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 +5 -3
- package/dist/types/ai-model/service-caller/codex/call-codex.d.ts.map +1 -1
- package/dist/types/ai-model/service-caller/index.d.ts +1 -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 +2 -2
- 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 +2 -2
- 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 +4 -2
- 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/responses/responses.d.ts +4 -2
- package/dist/types/ai-model/service-caller/openai/responses/responses.d.ts.map +1 -1
- package/dist/types/ai-model/service-caller/openai/siwc/authorization.d.ts +42 -0
- package/dist/types/ai-model/service-caller/openai/siwc/authorization.d.ts.map +1 -0
- package/dist/types/ai-model/service-caller/openai/siwc/credential-storage.d.ts +21 -0
- package/dist/types/ai-model/service-caller/openai/siwc/credential-storage.d.ts.map +1 -0
- package/dist/types/ai-model/service-caller/openai/siwc/errors.d.ts +10 -0
- package/dist/types/ai-model/service-caller/openai/siwc/errors.d.ts.map +1 -0
- package/dist/types/ai-model/service-caller/openai/siwc/index.d.ts +7 -0
- package/dist/types/ai-model/service-caller/openai/siwc/index.d.ts.map +1 -0
- package/dist/types/ai-model/service-caller/openai/siwc/prepare-call.d.ts +8 -0
- package/dist/types/ai-model/service-caller/openai/siwc/prepare-call.d.ts.map +1 -0
- package/dist/types/ai-model/service-caller/openai/siwc/refresh.d.ts +19 -0
- package/dist/types/ai-model/service-caller/openai/siwc/refresh.d.ts.map +1 -0
- package/dist/types/ai-model/service-caller/openai/siwc/token-manager.d.ts +10 -0
- package/dist/types/ai-model/service-caller/openai/siwc/token-manager.d.ts.map +1 -0
- package/dist/types/ai-model/service-caller/system-one/call-system-one.d.ts +4 -0
- package/dist/types/ai-model/service-caller/system-one/call-system-one.d.ts.map +1 -0
- package/dist/types/ai-model/service-caller/system-one/index.d.ts +3 -0
- package/dist/types/ai-model/service-caller/system-one/index.d.ts.map +1 -0
- package/dist/types/ai-model/service-caller/system-one/prepare-system-one.d.ts +21 -0
- package/dist/types/ai-model/service-caller/system-one/prepare-system-one.d.ts.map +1 -0
- package/dist/types/ai-model/service-caller/{system-one.d.ts → system-one/schema.d.ts} +1 -22
- package/dist/types/ai-model/service-caller/system-one/schema.d.ts.map +1 -0
- package/dist/types/ai-model/service-caller/system-one/utils.d.ts +6 -0
- package/dist/types/ai-model/service-caller/system-one/utils.d.ts.map +1 -0
- package/dist/types/ai-model/service-caller/types.d.ts +0 -3
- package/dist/types/ai-model/service-caller/types.d.ts.map +1 -1
- package/dist/types/ai-model/service-caller/utils.d.ts +3 -3
- package/dist/types/ai-model/shared/model-locate-result/factory.d.ts.map +1 -1
- package/dist/types/ai-model/shared/model-locate-result/index.d.ts +1 -1
- package/dist/types/ai-model/shared/model-locate-result/index.d.ts.map +1 -1
- package/dist/types/ai-model/shared/model-locate-result/pixel-mapper.d.ts +3 -3
- package/dist/types/ai-model/shared/model-locate-result/pixel-mapper.d.ts.map +1 -1
- package/dist/types/ai-model/shared/model-locate-result/types.d.ts +4 -0
- package/dist/types/ai-model/shared/model-locate-result/types.d.ts.map +1 -1
- package/dist/types/ai-model/shared/model-locate-result/validation.d.ts.map +1 -1
- package/dist/types/ai-model/workflows/grounding/locate.d.ts.map +1 -1
- package/dist/types/ai-model/workflows/grounding/section-locate.d.ts.map +1 -1
- package/dist/types/ai-model/workflows/insight/boolean.d.ts.map +1 -1
- package/dist/types/ai-model/workflows/insight/extraction.d.ts +2 -0
- package/dist/types/ai-model/workflows/insight/extraction.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/planning/types.d.ts +2 -1
- package/dist/types/ai-model/workflows/planning/types.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/device/index.d.ts +1 -0
- package/dist/types/device/index.d.ts.map +1 -1
- package/dist/types/service/index.d.ts +1 -1
- package/dist/types/service/index.d.ts.map +1 -1
- package/dist/types/types.d.ts +14 -3
- package/dist/types/types.d.ts.map +1 -1
- package/package.json +3 -2
- package/dist/es/ai-model/models/task-routing.mjs +0 -28
- package/dist/es/ai-model/models/task-routing.mjs.map +0 -1
- package/dist/es/ai-model/service-caller/system-one.mjs +0 -163
- package/dist/es/ai-model/service-caller/system-one.mjs.map +0 -1
- package/dist/lib/ai-model/models/task-routing.js.map +0 -1
- package/dist/lib/ai-model/service-caller/system-one.js +0 -206
- package/dist/lib/ai-model/service-caller/system-one.js.map +0 -1
- package/dist/types/ai-model/models/task-routing.d.ts +0 -6
- package/dist/types/ai-model/models/task-routing.d.ts.map +0 -1
- package/dist/types/ai-model/service-caller/system-one.d.ts.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-model/models/jev/planning-context.mjs","sources":["../../../../../src/ai-model/models/jev/planning-context.ts"],"sourcesContent":["import type { PlanFn, PlanOptions } from '../../workflows/planning/types';\nimport { prepareJevImage } from './image';\n\nexport async function prepareJevPlanningContext(\n instruction: Parameters<PlanFn>[0],\n options: PlanOptions,\n) {\n const history = options.conversationHistory;\n const image = await prepareJevImage(options.context.screenshot.base64);\n const references = await Promise.all(\n instruction.referenceImages.map(async (reference, index) => ({\n key: `reference_${index}`,\n name: reference.name,\n image: await prepareJevImage(reference.url),\n })),\n );\n const state = {\n goal: instruction.text,\n context: options.actionContext,\n history: history.historicalLogsToText(),\n memory: history.memoriesToText(),\n feedback: history.pendingFeedbackMessage,\n references: references.map(({ key, name }) => ({\n image: `\\`${key}\\``,\n name,\n })),\n availableActions: options.actionSpace.map(({ name, description }) => ({\n name,\n description,\n })),\n };\n return {\n state,\n images: {\n screenshot: image.imageBase64,\n ...Object.fromEntries(\n references.map(({ key, image }) => [key, image.imageBase64]),\n ),\n },\n };\n}\n\nexport type JevPlanningContext = Awaited<\n ReturnType<typeof prepareJevPlanningContext>\n>;\n"],"names":["prepareJevPlanningContext","instruction","options","history","image","prepareJevImage","references","Promise","reference","index","state","key","name","description","Object"],"mappings":";AAGO,eAAeA,0BACpBC,WAAkC,EAClCC,OAAoB;IAEpB,MAAMC,UAAUD,QAAQ,mBAAmB;IAC3C,MAAME,QAAQ,MAAMC,gBAAgBH,QAAQ,OAAO,CAAC,UAAU,CAAC,MAAM;IACrE,MAAMI,aAAa,MAAMC,QAAQ,GAAG,CAClCN,YAAY,eAAe,CAAC,GAAG,CAAC,OAAOO,WAAWC,QAAW;YAC3D,KAAK,CAAC,UAAU,EAAEA,OAAO;YACzB,MAAMD,UAAU,IAAI;YACpB,OAAO,MAAMH,gBAAgBG,UAAU,GAAG;QAC5C;IAEF,MAAME,QAAQ;QACZ,MAAMT,YAAY,IAAI;QACtB,SAASC,QAAQ,aAAa;QAC9B,SAASC,QAAQ,oBAAoB;QACrC,QAAQA,QAAQ,cAAc;QAC9B,UAAUA,QAAQ,sBAAsB;QACxC,YAAYG,WAAW,GAAG,CAAC,CAAC,EAAEK,GAAG,EAAEC,IAAI,EAAE,GAAM;gBAC7C,OAAO,CAAC,EAAE,EAAED,IAAI,EAAE,CAAC;gBACnBC;YACF;QACA,kBAAkBV,QAAQ,WAAW,CAAC,GAAG,CAAC,CAAC,EAAEU,IAAI,EAAEC,WAAW,EAAE,GAAM;gBACpED;gBACAC;YACF;IACF;IACA,OAAO;QACLH;QACA,QAAQ;YACN,YAAYN,MAAM,WAAW;YAC7B,GAAGU,OAAO,WAAW,CACnBR,WAAW,GAAG,CAAC,CAAC,EAAEK,GAAG,EAAEP,KAAK,EAAE,GAAK;oBAACO;oBAAKP,MAAM,WAAW;iBAAC,EAC5D;QACH;IACF;AACF"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { findAllMidsceneLocatorField } from "../../../common.mjs";
|
|
2
|
+
import { assert } from "@midscene/shared/utils";
|
|
3
|
+
import { callSystemOneAI } from "../../service-caller/index.mjs";
|
|
4
|
+
import { systemOneResponseSchema } from "../../service-caller/system-one/schema.mjs";
|
|
5
|
+
async function decideJevAction(context, options) {
|
|
6
|
+
const criteria = {
|
|
7
|
+
'control:complete': 'The entire user goal is already satisfied, confirmed by the current screenshot and execution feedback. No text answer is requested.',
|
|
8
|
+
'control:delegate': 'The next step needs generated output, an explanation of why the task cannot be completed, or something not covered by the action choices. Delegate to the default model.'
|
|
9
|
+
};
|
|
10
|
+
const choices = new Map([
|
|
11
|
+
[
|
|
12
|
+
'control:complete',
|
|
13
|
+
{
|
|
14
|
+
kind: 'complete'
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
[
|
|
18
|
+
'control:delegate',
|
|
19
|
+
{
|
|
20
|
+
kind: 'delegate'
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
]);
|
|
24
|
+
for (const action of options.actionSpace){
|
|
25
|
+
const kind = action.supportedBySystemOne ? 'action' : 'delegate';
|
|
26
|
+
const key = `${kind}:${action.name}`;
|
|
27
|
+
assert(!choices.has(key), `Duplicate Jev planning choice: ${key}`);
|
|
28
|
+
choices.set(key, {
|
|
29
|
+
kind,
|
|
30
|
+
action
|
|
31
|
+
});
|
|
32
|
+
criteria[key] = `${action.name}: ${action.description ?? action.name}. ${'action' === kind ? 'Perform this action.' : 'Suggest this action and delegate the next planning step, including its parameters, to the default model.'}`;
|
|
33
|
+
}
|
|
34
|
+
assert(choices.size <= 255, 'Jev Choice supports at most 255 options');
|
|
35
|
+
const locateInPlanning = options.includeLocateInPlanning && options.actionSpace.some((action)=>action.supportedBySystemOne && action.paramSchema && 1 === findAllMidsceneLocatorField(action.paramSchema).length);
|
|
36
|
+
const response = await callSystemOneAI({
|
|
37
|
+
...context,
|
|
38
|
+
questions: {
|
|
39
|
+
...locateInPlanning ? {
|
|
40
|
+
target: {
|
|
41
|
+
type: 'box',
|
|
42
|
+
instructions: 'Identify the single UI element to interact with in the NEXT step toward `goal`, using the current `screenshot`, context, history and feedback. Return its bounding box in `screenshot`. This is the target of the next direct action (such as Tap, DoubleClick, Hover or ClearInput), not the final goal of the entire task. Reference images describe targets, not the current page. If the next step needs no target or must be delegated, this box is unused.'
|
|
43
|
+
}
|
|
44
|
+
} : {},
|
|
45
|
+
action: {
|
|
46
|
+
type: 'choice',
|
|
47
|
+
instructions: 'Choose exactly the next step toward `goal` using the current `screenshot`, context, history and feedback. History records proposed actions; feedback and current screenshot establish what actually happened. Do not repeat completed steps. Reference images describe targets, not the current page. A delegate choice means the named action is likely needed; it has not been executed. Choose control:complete only when no requested work or text answer remains.',
|
|
48
|
+
criteria
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}, options.modelRuntime, {
|
|
52
|
+
abortSignal: options.abortSignal
|
|
53
|
+
});
|
|
54
|
+
const { answers } = systemOneResponseSchema.parse(JSON.parse(response.content));
|
|
55
|
+
assert('choice' === answers.action.type, 'Invalid Jev planning action');
|
|
56
|
+
const selected = answers.action.choice;
|
|
57
|
+
const choice = choices.get(selected);
|
|
58
|
+
assert(choice, `Unknown Jev planning choice: ${selected}`);
|
|
59
|
+
return {
|
|
60
|
+
selected,
|
|
61
|
+
choice,
|
|
62
|
+
response,
|
|
63
|
+
target: locateInPlanning ? answers.target : void 0
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export { decideJevAction };
|
|
67
|
+
|
|
68
|
+
//# sourceMappingURL=planning-decision.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-model/models/jev/planning-decision.mjs","sources":["../../../../../src/ai-model/models/jev/planning-decision.ts"],"sourcesContent":["import { findAllMidsceneLocatorField } from '@/common';\nimport type { DeviceAction } from '@/types';\nimport { assert } from '@midscene/shared/utils';\nimport { callSystemOneAI } from '../../service-caller';\nimport { systemOneResponseSchema } from '../../service-caller/system-one/schema';\nimport type { PlanOptions } from '../../workflows/planning/types';\nimport type { JevPlanningContext } from './planning-context';\n\ntype JevPlanningChoice =\n | { kind: 'complete' }\n | { kind: 'delegate'; action?: DeviceAction }\n | { kind: 'action'; action: DeviceAction };\n\nexport async function decideJevAction(\n context: JevPlanningContext,\n options: PlanOptions,\n) {\n const criteria: Record<string, string> = {\n 'control:complete':\n 'The entire user goal is already satisfied, confirmed by the current screenshot and execution feedback. No text answer is requested.',\n 'control:delegate':\n 'The next step needs generated output, an explanation of why the task cannot be completed, or something not covered by the action choices. Delegate to the default model.',\n };\n const choices = new Map<string, JevPlanningChoice>([\n ['control:complete', { kind: 'complete' }],\n ['control:delegate', { kind: 'delegate' }],\n ]);\n for (const action of options.actionSpace) {\n const kind = action.supportedBySystemOne ? 'action' : 'delegate';\n const key = `${kind}:${action.name}`;\n assert(!choices.has(key), `Duplicate Jev planning choice: ${key}`);\n choices.set(key, { kind, action });\n criteria[key] = `${action.name}: ${action.description ?? action.name}. ${\n kind === 'action'\n ? 'Perform this action.'\n : 'Suggest this action and delegate the next planning step, including its parameters, to the default model.'\n }`;\n }\n assert(choices.size <= 255, 'Jev Choice supports at most 255 options');\n const locateInPlanning =\n options.includeLocateInPlanning &&\n options.actionSpace.some(\n (action) =>\n action.supportedBySystemOne &&\n action.paramSchema &&\n findAllMidsceneLocatorField(action.paramSchema).length === 1,\n );\n const response = await callSystemOneAI(\n {\n ...context,\n questions: {\n ...(locateInPlanning\n ? {\n target: {\n type: 'box' as const,\n instructions:\n 'Identify the single UI element to interact with in the NEXT step toward `goal`, using the current `screenshot`, context, history and feedback. Return its bounding box in `screenshot`. This is the target of the next direct action (such as Tap, DoubleClick, Hover or ClearInput), not the final goal of the entire task. Reference images describe targets, not the current page. If the next step needs no target or must be delegated, this box is unused.',\n },\n }\n : {}),\n action: {\n type: 'choice',\n instructions:\n 'Choose exactly the next step toward `goal` using the current `screenshot`, context, history and feedback. History records proposed actions; feedback and current screenshot establish what actually happened. Do not repeat completed steps. Reference images describe targets, not the current page. A delegate choice means the named action is likely needed; it has not been executed. Choose control:complete only when no requested work or text answer remains.',\n criteria,\n },\n },\n },\n options.modelRuntime,\n { abortSignal: options.abortSignal },\n );\n const { answers } = systemOneResponseSchema.parse(\n JSON.parse(response.content),\n );\n assert(answers.action.type === 'choice', 'Invalid Jev planning action');\n const selected = answers.action.choice;\n const choice = choices.get(selected);\n assert(choice, `Unknown Jev planning choice: ${selected}`);\n return {\n selected,\n choice,\n response,\n target: locateInPlanning ? answers.target : undefined,\n };\n}\n\nexport type JevActionDecision = Awaited<ReturnType<typeof decideJevAction>>;\n"],"names":["decideJevAction","context","options","criteria","choices","Map","action","kind","key","assert","locateInPlanning","findAllMidsceneLocatorField","response","callSystemOneAI","answers","systemOneResponseSchema","JSON","selected","choice","undefined"],"mappings":";;;;AAaO,eAAeA,gBACpBC,OAA2B,EAC3BC,OAAoB;IAEpB,MAAMC,WAAmC;QACvC,oBACE;QACF,oBACE;IACJ;IACA,MAAMC,UAAU,IAAIC,IAA+B;QACjD;YAAC;YAAoB;gBAAE,MAAM;YAAW;SAAE;QAC1C;YAAC;YAAoB;gBAAE,MAAM;YAAW;SAAE;KAC3C;IACD,KAAK,MAAMC,UAAUJ,QAAQ,WAAW,CAAE;QACxC,MAAMK,OAAOD,OAAO,oBAAoB,GAAG,WAAW;QACtD,MAAME,MAAM,GAAGD,KAAK,CAAC,EAAED,OAAO,IAAI,EAAE;QACpCG,OAAO,CAACL,QAAQ,GAAG,CAACI,MAAM,CAAC,+BAA+B,EAAEA,KAAK;QACjEJ,QAAQ,GAAG,CAACI,KAAK;YAAED;YAAMD;QAAO;QAChCH,QAAQ,CAACK,IAAI,GAAG,GAAGF,OAAO,IAAI,CAAC,EAAE,EAAEA,OAAO,WAAW,IAAIA,OAAO,IAAI,CAAC,EAAE,EACrEC,AAAS,aAATA,OACI,yBACA,4GACJ;IACJ;IACAE,OAAOL,QAAQ,IAAI,IAAI,KAAK;IAC5B,MAAMM,mBACJR,QAAQ,uBAAuB,IAC/BA,QAAQ,WAAW,CAAC,IAAI,CACtB,CAACI,SACCA,OAAO,oBAAoB,IAC3BA,OAAO,WAAW,IAClBK,AAA2D,MAA3DA,4BAA4BL,OAAO,WAAW,EAAE,MAAM;IAE5D,MAAMM,WAAW,MAAMC,gBACrB;QACE,GAAGZ,OAAO;QACV,WAAW;YACT,GAAIS,mBACA;gBACE,QAAQ;oBACN,MAAM;oBACN,cACE;gBACJ;YACF,IACA,CAAC,CAAC;YACN,QAAQ;gBACN,MAAM;gBACN,cACE;gBACFP;YACF;QACF;IACF,GACAD,QAAQ,YAAY,EACpB;QAAE,aAAaA,QAAQ,WAAW;IAAC;IAErC,MAAM,EAAEY,OAAO,EAAE,GAAGC,wBAAwB,KAAK,CAC/CC,KAAK,KAAK,CAACJ,SAAS,OAAO;IAE7BH,OAAOK,AAAwB,aAAxBA,QAAQ,MAAM,CAAC,IAAI,EAAe;IACzC,MAAMG,WAAWH,QAAQ,MAAM,CAAC,MAAM;IACtC,MAAMI,SAASd,QAAQ,GAAG,CAACa;IAC3BR,OAAOS,QAAQ,CAAC,6BAA6B,EAAED,UAAU;IACzD,OAAO;QACLA;QACAC;QACAN;QACA,QAAQF,mBAAmBI,QAAQ,MAAM,GAAGK;IAC9C;AACF"}
|
|
@@ -1,137 +1,25 @@
|
|
|
1
1
|
import { buildYamlFlowFromPlans } from "../../../common.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { standardPlan } from "../../workflows/planning/standard-planning.mjs";
|
|
6
|
-
import { prepareJevImage } from "./image.mjs";
|
|
2
|
+
import { buildJevAction } from "./planning-action.mjs";
|
|
3
|
+
import { prepareJevPlanningContext } from "./planning-context.mjs";
|
|
4
|
+
import { decideJevAction } from "./planning-decision.mjs";
|
|
7
5
|
const jevPlan = async (instruction, options)=>{
|
|
6
|
+
if (options.actionSpace.length + 2 > 255) throw new Error('Jev planning supports at most 253 actions (255 choices including completion and delegation).');
|
|
8
7
|
const history = options.conversationHistory;
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
...usage,
|
|
22
|
-
intent: 'planning'
|
|
23
|
-
}) : void 0,
|
|
24
|
-
modelRouting: {
|
|
25
|
-
requestedModel: options.modelRuntime.config.modelName,
|
|
26
|
-
requestedSlot: options.modelRuntime.config.slot,
|
|
27
|
-
task: 'planning',
|
|
28
|
-
reason
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
const planner = 'custom' === runtime.adapter.planning.kind ? runtime.adapter.planning.planFn : standardPlan;
|
|
32
|
-
return planner(instruction, {
|
|
33
|
-
...options,
|
|
34
|
-
modelRuntime: runtime,
|
|
35
|
-
includeLocateInPlanning: false
|
|
36
|
-
});
|
|
37
|
-
};
|
|
38
|
-
const image = await prepareJevImage(options.context.screenshot.base64);
|
|
39
|
-
const references = await Promise.all(instruction.referenceImages.map(async (reference, index)=>({
|
|
40
|
-
key: `reference_${index}`,
|
|
41
|
-
name: reference.name,
|
|
42
|
-
image: await prepareJevImage(reference.url)
|
|
43
|
-
})));
|
|
44
|
-
const state = {
|
|
45
|
-
goal: instruction.text,
|
|
46
|
-
context: options.actionContext,
|
|
47
|
-
history: history.historicalLogsToText(),
|
|
48
|
-
memory: history.memoriesToText(),
|
|
49
|
-
feedback: history.pendingFeedbackMessage,
|
|
50
|
-
references: references.map(({ key, name })=>({
|
|
51
|
-
image: `\`${key}\``,
|
|
52
|
-
name
|
|
53
|
-
})),
|
|
54
|
-
availableActions: options.actionSpace.map(({ name, description })=>({
|
|
55
|
-
name,
|
|
56
|
-
description
|
|
57
|
-
}))
|
|
58
|
-
};
|
|
59
|
-
const criteria = {
|
|
60
|
-
Complete: 'The entire user goal is already satisfied, confirmed by the current screenshot and execution feedback. No text answer is requested.',
|
|
61
|
-
Delegate: 'The next step requires text input, generated output, an action or parameters not covered by the other choices. Also use for impossible tasks needing explanation.'
|
|
62
|
-
};
|
|
63
|
-
for (const action of options.actionSpace)if ('Tap' === action.name || 'Scroll' === action.name || 'Sleep' === action.name) criteria[action.name] = 'Sleep' === action.name ? 'Wait 800 ms for a transient loading state.' : action.description ?? action.name;
|
|
64
|
-
const response = await callAI([], options.modelRuntime, {
|
|
65
|
-
abortSignal: options.abortSignal,
|
|
66
|
-
systemOneRequest: {
|
|
67
|
-
state,
|
|
68
|
-
images: {
|
|
69
|
-
screenshot: image.imageBase64,
|
|
70
|
-
...Object.fromEntries(references.map(({ key, image })=>[
|
|
71
|
-
key,
|
|
72
|
-
image.imageBase64
|
|
73
|
-
]))
|
|
74
|
-
},
|
|
75
|
-
questions: {
|
|
76
|
-
action: {
|
|
77
|
-
type: 'choice',
|
|
78
|
-
instructions: 'Choose exactly the next step toward `goal` using the current `screenshot`, context, history and feedback. History records proposed actions; feedback and current screenshot establish what actually happened. Do not repeat completed steps. Reference images describe targets, not the current page.',
|
|
79
|
-
criteria
|
|
80
|
-
},
|
|
81
|
-
...criteria.Scroll ? {
|
|
82
|
-
direction: {
|
|
83
|
-
type: 'choice',
|
|
84
|
-
instructions: 'If scrolling is the next step toward `goal`, which direction reveals the desired off-screen content? Evaluate from the screenshot and history independently of the action question.',
|
|
85
|
-
criteria: {
|
|
86
|
-
down: 'Reveal content below',
|
|
87
|
-
up: 'Reveal content above',
|
|
88
|
-
left: 'Reveal content to the left',
|
|
89
|
-
right: 'Reveal content to the right'
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
} : {}
|
|
93
|
-
}
|
|
8
|
+
const context = await prepareJevPlanningContext(instruction, options);
|
|
9
|
+
const decision = await decideJevAction(context, options);
|
|
10
|
+
const { selected, choice, response } = decision;
|
|
11
|
+
if ('delegate' === choice.kind) return {
|
|
12
|
+
actions: [],
|
|
13
|
+
log: `Jev selected ${selected}`,
|
|
14
|
+
rawResponse: response.content,
|
|
15
|
+
usage: response.usage,
|
|
16
|
+
shouldContinuePlanning: true,
|
|
17
|
+
delegation: {
|
|
18
|
+
reason: choice.action ? `The previous planner suggested ${choice.action.name}; delegating planning with this action as an advisory suggestion` : 'The previous planner delegated planning of the next step',
|
|
19
|
+
suggestedAction: choice.action?.name
|
|
94
20
|
}
|
|
95
|
-
});
|
|
96
|
-
const { answers } = systemOneResponseSchema.parse(JSON.parse(response.content));
|
|
97
|
-
assert('choice' === answers.action.type, 'Invalid Jev planning action');
|
|
98
|
-
const selected = answers.action.choice;
|
|
99
|
-
if ('Delegate' === selected) return delegate('The next step requires parameters or output that Jev cannot generate');
|
|
100
|
-
if (('Tap' === selected || 'Scroll' === selected) && options.locateModelRuntime?.config.modelFamily !== 'jev') return delegate("The configured Locate model requires a concrete target description from a general-purpose planner");
|
|
101
|
-
const locate = {
|
|
102
|
-
prompt: `Locate the single ${'Scroll' === selected ? 'scrollable region to scroll' : 'element to tap'} for the NEXT step toward this goal. Use the current screenshot as authoritative. Previous proposals may have failed; use feedback. Task context: ${JSON.stringify(state)}`,
|
|
103
|
-
images: instruction.referenceImages
|
|
104
21
|
};
|
|
105
|
-
const actions = (
|
|
106
|
-
if ('Complete' === selected) return [];
|
|
107
|
-
if ('Sleep' === selected) return [
|
|
108
|
-
{
|
|
109
|
-
type: 'Sleep',
|
|
110
|
-
param: {
|
|
111
|
-
timeMs: 800
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
];
|
|
115
|
-
if ('Tap' === selected) return [
|
|
116
|
-
{
|
|
117
|
-
type: 'Tap',
|
|
118
|
-
param: {
|
|
119
|
-
locate
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
];
|
|
123
|
-
assert('Scroll' === selected && answers.direction?.type === 'choice', 'Invalid Jev scroll action');
|
|
124
|
-
return [
|
|
125
|
-
{
|
|
126
|
-
type: 'Scroll',
|
|
127
|
-
param: {
|
|
128
|
-
locate,
|
|
129
|
-
direction: answers.direction.choice,
|
|
130
|
-
scrollType: 'singleAction'
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
];
|
|
134
|
-
})();
|
|
22
|
+
const actions = buildJevAction(decision, context, instruction, options);
|
|
135
23
|
const log = `Jev selected ${selected}`;
|
|
136
24
|
const feedback = history.pendingFeedbackMessage;
|
|
137
25
|
history.resetPendingFeedbackMessageIfExists();
|
|
@@ -156,8 +44,8 @@ const jevPlan = async (instruction, options)=>{
|
|
|
156
44
|
log,
|
|
157
45
|
rawResponse: response.content,
|
|
158
46
|
usage: response.usage,
|
|
159
|
-
shouldContinuePlanning: '
|
|
160
|
-
...'
|
|
47
|
+
shouldContinuePlanning: 'complete' !== choice.kind,
|
|
48
|
+
...'complete' === choice.kind ? {
|
|
161
49
|
finalizeSuccess: true
|
|
162
50
|
} : {},
|
|
163
51
|
yamlFlow: buildYamlFlowFromPlans(actions, options.actionSpace)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-model/models/jev/planning.mjs","sources":["../../../../../src/ai-model/models/jev/planning.ts"],"sourcesContent":["import { buildYamlFlowFromPlans } from '@/common';\nimport type { AIUsageInfo, PlanningAction } from '@/types';\nimport { assert } from '@midscene/shared/utils';\nimport { callAI } from '../../service-caller';\nimport { systemOneResponseSchema } from '../../service-caller/system-one';\nimport { standardPlan } from '../../workflows/planning/standard-planning';\nimport type { PlanFn } from '../../workflows/planning/types';\nimport { prepareJevImage } from './image';\n\nexport const jevPlan: PlanFn = async (instruction, options) => {\n const history = options.conversationHistory;\n const delegate = async (reason: string) => {\n assert(\n options.getDefaultModelRuntime,\n 'Default model runtime is required for Jev planning delegation',\n );\n const base = options.getDefaultModelRuntime();\n assert(\n base.config.modelFamily !== 'jev',\n 'Jev cannot delegate planning to itself',\n );\n const runtime = {\n ...base,\n config: { ...base.config, intent: 'planning' as const },\n executionId: options.modelRuntime.executionId,\n onUsage: base.onUsage\n ? (usage: AIUsageInfo) =>\n base.onUsage?.({ ...usage, intent: 'planning' })\n : undefined,\n modelRouting: {\n requestedModel: options.modelRuntime.config.modelName,\n requestedSlot: options.modelRuntime.config.slot,\n task: 'planning' as const,\n reason,\n },\n };\n const planner =\n runtime.adapter.planning.kind === 'custom'\n ? runtime.adapter.planning.planFn\n : standardPlan;\n return planner(instruction, {\n ...options,\n modelRuntime: runtime,\n includeLocateInPlanning: false,\n });\n };\n const image = await prepareJevImage(options.context.screenshot.base64);\n const references = await Promise.all(\n instruction.referenceImages.map(async (reference, index) => ({\n key: `reference_${index}`,\n name: reference.name,\n image: await prepareJevImage(reference.url),\n })),\n );\n const state = {\n goal: instruction.text,\n context: options.actionContext,\n history: history.historicalLogsToText(),\n memory: history.memoriesToText(),\n feedback: history.pendingFeedbackMessage,\n references: references.map(({ key, name }) => ({\n image: `\\`${key}\\``,\n name,\n })),\n availableActions: options.actionSpace.map(({ name, description }) => ({\n name,\n description,\n })),\n };\n const criteria: Record<string, string> = {\n Complete:\n 'The entire user goal is already satisfied, confirmed by the current screenshot and execution feedback. No text answer is requested.',\n Delegate:\n 'The next step requires text input, generated output, an action or parameters not covered by the other choices. Also use for impossible tasks needing explanation.',\n };\n for (const action of options.actionSpace) {\n if (\n action.name === 'Tap' ||\n action.name === 'Scroll' ||\n action.name === 'Sleep'\n ) {\n criteria[action.name] =\n action.name === 'Sleep'\n ? 'Wait 800 ms for a transient loading state.'\n : (action.description ?? action.name);\n }\n }\n const response = await callAI([], options.modelRuntime, {\n abortSignal: options.abortSignal,\n systemOneRequest: {\n state,\n images: {\n screenshot: image.imageBase64,\n ...Object.fromEntries(\n references.map(({ key, image }) => [key, image.imageBase64]),\n ),\n },\n questions: {\n action: {\n type: 'choice',\n instructions:\n 'Choose exactly the next step toward `goal` using the current `screenshot`, context, history and feedback. History records proposed actions; feedback and current screenshot establish what actually happened. Do not repeat completed steps. Reference images describe targets, not the current page.',\n criteria,\n },\n ...(criteria.Scroll\n ? {\n direction: {\n type: 'choice' as const,\n instructions:\n 'If scrolling is the next step toward `goal`, which direction reveals the desired off-screen content? Evaluate from the screenshot and history independently of the action question.',\n criteria: {\n down: 'Reveal content below',\n up: 'Reveal content above',\n left: 'Reveal content to the left',\n right: 'Reveal content to the right',\n },\n },\n }\n : {}),\n },\n },\n });\n const { answers } = systemOneResponseSchema.parse(\n JSON.parse(response.content),\n );\n assert(answers.action.type === 'choice', 'Invalid Jev planning action');\n const selected = answers.action.choice;\n if (selected === 'Delegate') {\n return delegate(\n 'The next step requires parameters or output that Jev cannot generate',\n );\n }\n if (\n (selected === 'Tap' || selected === 'Scroll') &&\n options.locateModelRuntime?.config.modelFamily !== 'jev'\n ) {\n return delegate(\n 'The configured Locate model requires a concrete target description from a general-purpose planner',\n );\n }\n // The normal Locate stage resolves this contextual target with its own runtime.\n // Do not embed planning coordinates or bypass the configured Locate model.\n const locate = {\n prompt: `Locate the single ${selected === 'Scroll' ? 'scrollable region to scroll' : 'element to tap'} for the NEXT step toward this goal. Use the current screenshot as authoritative. Previous proposals may have failed; use feedback. Task context: ${JSON.stringify(state)}`,\n images: instruction.referenceImages,\n };\n const actions: PlanningAction[] = (() => {\n if (selected === 'Complete') {\n return [];\n }\n if (selected === 'Sleep') {\n return [{ type: 'Sleep', param: { timeMs: 800 } }];\n }\n if (selected === 'Tap') {\n return [{ type: 'Tap', param: { locate } }];\n }\n assert(\n selected === 'Scroll' && answers.direction?.type === 'choice',\n 'Invalid Jev scroll action',\n );\n return [\n {\n type: 'Scroll',\n param: {\n locate,\n direction: answers.direction.choice,\n scrollType: 'singleAction',\n },\n },\n ];\n })();\n const log = `Jev selected ${selected}`;\n const feedback = history.pendingFeedbackMessage;\n history.resetPendingFeedbackMessageIfExists();\n history.appendMessage({\n role: 'user',\n content: `Goal: ${instruction.text}\\nExecution feedback: ${feedback}`,\n });\n history.appendMessage({\n role: 'assistant',\n content: JSON.stringify({ actions, log }),\n });\n history.appendHistoricalLog(\n `${log}: ${JSON.stringify(actions.map(({ type, param }) => ({ type, direction: param?.direction })))}`,\n );\n history.compressHistory(50, 20);\n return {\n actions,\n log,\n rawResponse: response.content,\n usage: response.usage,\n shouldContinuePlanning: selected !== 'Complete',\n ...(selected === 'Complete' ? { finalizeSuccess: true } : {}),\n yamlFlow: buildYamlFlowFromPlans(actions, options.actionSpace),\n };\n};\n"],"names":["jevPlan","instruction","options","history","delegate","reason","assert","base","runtime","usage","undefined","planner","standardPlan","image","prepareJevImage","references","Promise","reference","index","state","key","name","description","criteria","action","response","callAI","Object","answers","systemOneResponseSchema","JSON","selected","locate","actions","log","feedback","type","param","buildYamlFlowFromPlans"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ai-model/models/jev/planning.mjs","sources":["../../../../../src/ai-model/models/jev/planning.ts"],"sourcesContent":["import { buildYamlFlowFromPlans } from '@/common';\nimport type { PlanFn } from '../../workflows/planning/types';\nimport { buildJevAction } from './planning-action';\nimport { prepareJevPlanningContext } from './planning-context';\nimport { decideJevAction } from './planning-decision';\n\nexport const jevPlan: PlanFn = async (instruction, options) => {\n if (options.actionSpace.length + 2 > 255) {\n throw new Error(\n 'Jev planning supports at most 253 actions (255 choices including completion and delegation).',\n );\n }\n const history = options.conversationHistory;\n const context = await prepareJevPlanningContext(instruction, options);\n const decision = await decideJevAction(context, options);\n const { selected, choice, response } = decision;\n if (choice.kind === 'delegate') {\n return {\n actions: [],\n log: `Jev selected ${selected}`,\n rawResponse: response.content,\n usage: response.usage,\n shouldContinuePlanning: true,\n delegation: {\n reason: choice.action\n ? `The previous planner suggested ${choice.action.name}; delegating planning with this action as an advisory suggestion`\n : 'The previous planner delegated planning of the next step',\n suggestedAction: choice.action?.name,\n },\n };\n }\n const actions = buildJevAction(decision, context, instruction, options);\n const log = `Jev selected ${selected}`;\n const feedback = history.pendingFeedbackMessage;\n history.resetPendingFeedbackMessageIfExists();\n history.appendMessage({\n role: 'user',\n content: `Goal: ${instruction.text}\\nExecution feedback: ${feedback}`,\n });\n history.appendMessage({\n role: 'assistant',\n content: JSON.stringify({ actions, log }),\n });\n history.appendHistoricalLog(\n `${log}: ${JSON.stringify(actions.map(({ type, param }) => ({ type, direction: param?.direction })))}`,\n );\n history.compressHistory(50, 20);\n return {\n actions,\n log,\n rawResponse: response.content,\n usage: response.usage,\n shouldContinuePlanning: choice.kind !== 'complete',\n ...(choice.kind === 'complete' ? { finalizeSuccess: true } : {}),\n yamlFlow: buildYamlFlowFromPlans(actions, options.actionSpace),\n };\n};\n"],"names":["jevPlan","instruction","options","Error","history","context","prepareJevPlanningContext","decision","decideJevAction","selected","choice","response","actions","buildJevAction","log","feedback","JSON","type","param","buildYamlFlowFromPlans"],"mappings":";;;;AAMO,MAAMA,UAAkB,OAAOC,aAAaC;IACjD,IAAIA,QAAQ,WAAW,CAAC,MAAM,GAAG,IAAI,KACnC,MAAM,IAAIC,MACR;IAGJ,MAAMC,UAAUF,QAAQ,mBAAmB;IAC3C,MAAMG,UAAU,MAAMC,0BAA0BL,aAAaC;IAC7D,MAAMK,WAAW,MAAMC,gBAAgBH,SAASH;IAChD,MAAM,EAAEO,QAAQ,EAAEC,MAAM,EAAEC,QAAQ,EAAE,GAAGJ;IACvC,IAAIG,AAAgB,eAAhBA,OAAO,IAAI,EACb,OAAO;QACL,SAAS,EAAE;QACX,KAAK,CAAC,aAAa,EAAED,UAAU;QAC/B,aAAaE,SAAS,OAAO;QAC7B,OAAOA,SAAS,KAAK;QACrB,wBAAwB;QACxB,YAAY;YACV,QAAQD,OAAO,MAAM,GACjB,CAAC,+BAA+B,EAAEA,OAAO,MAAM,CAAC,IAAI,CAAC,gEAAgE,CAAC,GACtH;YACJ,iBAAiBA,OAAO,MAAM,EAAE;QAClC;IACF;IAEF,MAAME,UAAUC,eAAeN,UAAUF,SAASJ,aAAaC;IAC/D,MAAMY,MAAM,CAAC,aAAa,EAAEL,UAAU;IACtC,MAAMM,WAAWX,QAAQ,sBAAsB;IAC/CA,QAAQ,mCAAmC;IAC3CA,QAAQ,aAAa,CAAC;QACpB,MAAM;QACN,SAAS,CAAC,MAAM,EAAEH,YAAY,IAAI,CAAC,sBAAsB,EAAEc,UAAU;IACvE;IACAX,QAAQ,aAAa,CAAC;QACpB,MAAM;QACN,SAASY,KAAK,SAAS,CAAC;YAAEJ;YAASE;QAAI;IACzC;IACAV,QAAQ,mBAAmB,CACzB,GAAGU,IAAI,EAAE,EAAEE,KAAK,SAAS,CAACJ,QAAQ,GAAG,CAAC,CAAC,EAAEK,IAAI,EAAEC,KAAK,EAAE,GAAM;YAAED;YAAM,WAAWC,OAAO;QAAU,MAAM;IAExGd,QAAQ,eAAe,CAAC,IAAI;IAC5B,OAAO;QACLQ;QACAE;QACA,aAAaH,SAAS,OAAO;QAC7B,OAAOA,SAAS,KAAK;QACrB,wBAAwBD,AAAgB,eAAhBA,OAAO,IAAI;QACnC,GAAIA,AAAgB,eAAhBA,OAAO,IAAI,GAAkB;YAAE,iBAAiB;QAAK,IAAI,CAAC,CAAC;QAC/D,UAAUS,uBAAuBP,SAASV,QAAQ,WAAW;IAC/D;AACF"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { getDebug } from "@midscene/shared/logger";
|
|
2
|
+
import { getModelRuntime } from "./registry.mjs";
|
|
3
|
+
function resolveModelForTaskType(configs, intent, taskType) {
|
|
4
|
+
const requested = getModelRuntime(configs.getModelConfig(intent));
|
|
5
|
+
if (!requested.adapter.supportedTaskTypes || requested.adapter.supportedTaskTypes.includes(taskType)) return requested;
|
|
6
|
+
const config = configs.getModelConfig('default');
|
|
7
|
+
const runtime = getModelRuntime({
|
|
8
|
+
...config,
|
|
9
|
+
intent
|
|
10
|
+
});
|
|
11
|
+
if (runtime.adapter.supportedTaskTypes && !runtime.adapter.supportedTaskTypes.includes(taskType)) throw new Error(`The default model cannot perform ${taskType}. Configure a general-purpose default model.`);
|
|
12
|
+
const reason = `${requested.config.modelFamily} does not support ${taskType}; using the default model`;
|
|
13
|
+
getDebug('ai:model-fallback', {
|
|
14
|
+
console: true
|
|
15
|
+
})(reason);
|
|
16
|
+
return {
|
|
17
|
+
...runtime,
|
|
18
|
+
modelFallback: {
|
|
19
|
+
requestedModel: requested.config.modelName,
|
|
20
|
+
requestedSlot: requested.config.slot,
|
|
21
|
+
taskType,
|
|
22
|
+
reason
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export { resolveModelForTaskType };
|
|
27
|
+
|
|
28
|
+
//# sourceMappingURL=model-fallback.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-model/models/model-fallback.mjs","sources":["../../../../src/ai-model/models/model-fallback.ts"],"sourcesContent":["import type { IModelConfig, TIntent } from '@midscene/shared/env';\nimport { getDebug } from '@midscene/shared/logger';\nimport type { ModelRuntime, ModelTaskType } from '../model-adapter/types';\nimport { getModelRuntime } from './registry';\n\nexport function resolveModelForTaskType(\n configs: { getModelConfig(intent: TIntent): IModelConfig },\n intent: TIntent,\n taskType: ModelTaskType,\n): ModelRuntime {\n const requested = getModelRuntime(configs.getModelConfig(intent));\n if (\n !requested.adapter.supportedTaskTypes ||\n requested.adapter.supportedTaskTypes.includes(taskType)\n ) {\n return requested;\n }\n const config = configs.getModelConfig('default');\n const runtime = getModelRuntime({ ...config, intent });\n if (\n runtime.adapter.supportedTaskTypes &&\n !runtime.adapter.supportedTaskTypes.includes(taskType)\n ) {\n throw new Error(\n `The default model cannot perform ${taskType}. Configure a general-purpose default model.`,\n );\n }\n const reason = `${requested.config.modelFamily} does not support ${taskType}; using the default model`;\n getDebug('ai:model-fallback', { console: true })(reason);\n return {\n ...runtime,\n modelFallback: {\n requestedModel: requested.config.modelName,\n requestedSlot: requested.config.slot,\n taskType,\n reason,\n },\n };\n}\n"],"names":["resolveModelForTaskType","configs","intent","taskType","requested","getModelRuntime","config","runtime","Error","reason","getDebug"],"mappings":";;AAKO,SAASA,wBACdC,OAA0D,EAC1DC,MAAe,EACfC,QAAuB;IAEvB,MAAMC,YAAYC,gBAAgBJ,QAAQ,cAAc,CAACC;IACzD,IACE,CAACE,UAAU,OAAO,CAAC,kBAAkB,IACrCA,UAAU,OAAO,CAAC,kBAAkB,CAAC,QAAQ,CAACD,WAE9C,OAAOC;IAET,MAAME,SAASL,QAAQ,cAAc,CAAC;IACtC,MAAMM,UAAUF,gBAAgB;QAAE,GAAGC,MAAM;QAAEJ;IAAO;IACpD,IACEK,QAAQ,OAAO,CAAC,kBAAkB,IAClC,CAACA,QAAQ,OAAO,CAAC,kBAAkB,CAAC,QAAQ,CAACJ,WAE7C,MAAM,IAAIK,MACR,CAAC,iCAAiC,EAAEL,SAAS,4CAA4C,CAAC;IAG9F,MAAMM,SAAS,GAAGL,UAAU,MAAM,CAAC,WAAW,CAAC,kBAAkB,EAAED,SAAS,yBAAyB,CAAC;IACtGO,SAAS,qBAAqB;QAAE,SAAS;IAAK,GAAGD;IACjD,OAAO;QACL,GAAGF,OAAO;QACV,eAAe;YACb,gBAAgBH,UAAU,MAAM,CAAC,SAAS;YAC1C,eAAeA,UAAU,MAAM,CAAC,IAAI;YACpCD;YACAM;QACF;IACF;AACF"}
|
|
@@ -6,8 +6,9 @@ import { isModelCallRecordingEnabled, recordModelCallEvent } from "./model-call-
|
|
|
6
6
|
import { callOpenAI } from "./openai/call-openai.mjs";
|
|
7
7
|
import { prepareChatCompletion } from "./openai/chat-completion/chat-completion.mjs";
|
|
8
8
|
import { prepareResponses } from "./openai/responses/responses.mjs";
|
|
9
|
+
import { SiwcTokenExpiredError, prepareSiwcCall, siwcTokenManager } from "./openai/siwc/index.mjs";
|
|
9
10
|
import { buildRequestAbortSignal, resolveEffectiveTimeoutMs, runWithAbortSignal, waitForRetry } from "./request-timeout.mjs";
|
|
10
|
-
import { callSystemOne, prepareSystemOne } from "./system-one.mjs";
|
|
11
|
+
import { callSystemOne, prepareSystemOne } from "./system-one/index.mjs";
|
|
11
12
|
import { appendAIRequestFailureSummary, buildUsageInfo, nextInternalCallId, normalizeRetryCount, toError } from "./utils.mjs";
|
|
12
13
|
function _define_property(obj, key, value) {
|
|
13
14
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
@@ -20,44 +21,49 @@ function _define_property(obj, key, value) {
|
|
|
20
21
|
return obj;
|
|
21
22
|
}
|
|
22
23
|
const DEFAULT_MODEL_PROTOCOL = 'openai-chat';
|
|
23
|
-
async function
|
|
24
|
-
|
|
25
|
-
const isStreaming =
|
|
26
|
-
if (isStreaming) assert('function' == typeof
|
|
27
|
-
const
|
|
28
|
-
const internalCallId = nextInternalCallId();
|
|
24
|
+
async function callGenerativeAI(messages, originalModelRuntime, originalOptions) {
|
|
25
|
+
originalOptions?.abortSignal?.throwIfAborted();
|
|
26
|
+
const isStreaming = originalOptions?.stream === true;
|
|
27
|
+
if (isStreaming) assert('function' == typeof originalOptions?.onChunk, 'onChunk is required when stream: true is explicitly specified');
|
|
28
|
+
const { modelRuntime, options } = await prepareSiwcCall(originalModelRuntime, originalOptions);
|
|
29
29
|
const { config: modelConfig } = modelRuntime;
|
|
30
|
-
|
|
31
|
-
if (options?.systemOneRequest) {
|
|
32
|
-
assert('jev' === modelConfig.modelFamily, 'System One requests require the Jev model family');
|
|
33
|
-
return {
|
|
34
|
-
protocol: 'system-one',
|
|
35
|
-
input: await prepareSystemOne(modelConfig, options.systemOneRequest)
|
|
36
|
-
};
|
|
37
|
-
}
|
|
30
|
+
return executeModelCall(modelRuntime, options, async ()=>{
|
|
38
31
|
const input = {
|
|
39
32
|
messages,
|
|
40
33
|
modelRuntime,
|
|
41
34
|
options
|
|
42
35
|
};
|
|
43
36
|
if (isCodexAppServerProvider(modelConfig.openaiBaseURL)) return {
|
|
44
|
-
|
|
37
|
+
kind: 'codex',
|
|
45
38
|
input: prepareCodexCall(input)
|
|
46
39
|
};
|
|
47
40
|
const protocol = modelConfig.protocol ?? DEFAULT_MODEL_PROTOCOL;
|
|
48
41
|
assert(modelRuntime.adapter.supportedProtocols.includes(protocol), `Model adapter "${modelConfig.modelFamily ?? 'default'}" does not support protocol "${protocol}"`);
|
|
49
42
|
if ('openai-responses' === protocol) return {
|
|
50
|
-
|
|
43
|
+
kind: 'responses',
|
|
51
44
|
input: await prepareResponses(input)
|
|
52
45
|
};
|
|
53
46
|
return {
|
|
54
|
-
|
|
47
|
+
kind: 'chat-completion',
|
|
55
48
|
input: await prepareChatCompletion(input)
|
|
56
49
|
};
|
|
57
|
-
};
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
async function callSystemOneAI(request, modelRuntime, options) {
|
|
53
|
+
options?.abortSignal?.throwIfAborted();
|
|
54
|
+
assert(!options?.stream, 'Jev does not support streaming output');
|
|
55
|
+
assert('jev' === modelRuntime.config.modelFamily, 'System One currently only supports the Jev model family in Midscene');
|
|
56
|
+
return executeModelCall(modelRuntime, options, async ()=>({
|
|
57
|
+
kind: 'system-one',
|
|
58
|
+
input: await prepareSystemOne(modelRuntime.config, request)
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
async function executeModelCall(modelRuntime, options, prepare) {
|
|
62
|
+
const executionId = modelRuntime.executionId ?? `unscoped-${uuid()}`;
|
|
63
|
+
const internalCallId = nextInternalCallId();
|
|
64
|
+
const { config: modelConfig } = modelRuntime;
|
|
58
65
|
const prepared = options?.abortSignal ? await runWithAbortSignal(options.abortSignal, prepare) : await prepare();
|
|
59
66
|
const result = await callModelWithRetry({
|
|
60
|
-
messages,
|
|
61
67
|
modelRuntime,
|
|
62
68
|
options,
|
|
63
69
|
executionId,
|
|
@@ -66,7 +72,7 @@ async function callAI(messages, modelRuntime, options) {
|
|
|
66
72
|
});
|
|
67
73
|
const { rawUsage, timeCost, totalTimeCost, retryCount, requestId, responseModelName, ...response } = result;
|
|
68
74
|
const rawUsageInfo = buildUsageInfo({
|
|
69
|
-
|
|
75
|
+
requestKind: prepared.kind,
|
|
70
76
|
stream: response.isStreamed,
|
|
71
77
|
usageData: rawUsage,
|
|
72
78
|
timeCost,
|
|
@@ -81,7 +87,7 @@ async function callAI(messages, modelRuntime, options) {
|
|
|
81
87
|
});
|
|
82
88
|
const usage = rawUsageInfo ? {
|
|
83
89
|
...rawUsageInfo,
|
|
84
|
-
|
|
90
|
+
modelFallback: modelRuntime.modelFallback
|
|
85
91
|
} : void 0;
|
|
86
92
|
const debugProfileStats = getDebug('ai:profile:stats');
|
|
87
93
|
const debugProfileDetail = getDebug('ai:profile:detail');
|
|
@@ -119,6 +125,28 @@ async function callModelWithRetry(input) {
|
|
|
119
125
|
} catch (error) {
|
|
120
126
|
options?.abortSignal?.throwIfAborted();
|
|
121
127
|
if (error instanceof NonRetryableModelCallError) throw error.cause;
|
|
128
|
+
if (error instanceof SiwcTokenExpiredError) {
|
|
129
|
+
const refresh = async ()=>{
|
|
130
|
+
assert(config.openaiApiKey, 'Missing rejected SIWC access token');
|
|
131
|
+
await siwcTokenManager.refreshAccessToken(config.openaiApiKey);
|
|
132
|
+
return prepareSiwcCall(input.modelRuntime, options);
|
|
133
|
+
};
|
|
134
|
+
const refreshed = options?.abortSignal ? await runWithAbortSignal(options.abortSignal, refresh) : await refresh();
|
|
135
|
+
options?.abortSignal?.throwIfAborted();
|
|
136
|
+
try {
|
|
137
|
+
const result = await callModelOnce({
|
|
138
|
+
...input,
|
|
139
|
+
...refreshed
|
|
140
|
+
}, attempt + 1);
|
|
141
|
+
return {
|
|
142
|
+
...result,
|
|
143
|
+
totalTimeCost: Date.now() - startTime,
|
|
144
|
+
retryCount: attempt
|
|
145
|
+
};
|
|
146
|
+
} catch (retryError) {
|
|
147
|
+
throw retryError instanceof NonRetryableModelCallError ? retryError.cause : retryError;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
122
150
|
const lastError = toError(error);
|
|
123
151
|
attemptErrors.push({
|
|
124
152
|
attempt,
|
|
@@ -141,7 +169,7 @@ async function callModelWithRetry(input) {
|
|
|
141
169
|
await waitForRetry(retryInterval, options?.abortSignal);
|
|
142
170
|
}
|
|
143
171
|
}
|
|
144
|
-
async function callModelOnce({
|
|
172
|
+
async function callModelOnce({ modelRuntime, options, executionId, internalCallId, prepared }, attempt) {
|
|
145
173
|
const { config: modelConfig } = modelRuntime;
|
|
146
174
|
const recordingEnabled = isModelCallRecordingEnabled();
|
|
147
175
|
const recordEvent = recordingEnabled || modelRuntime.onRequest ? (event)=>{
|
|
@@ -157,7 +185,7 @@ async function callModelOnce({ messages, modelRuntime, options, executionId, int
|
|
|
157
185
|
slot: modelConfig.slot,
|
|
158
186
|
intent: modelConfig.intent,
|
|
159
187
|
modelFamily: modelConfig.modelFamily,
|
|
160
|
-
|
|
188
|
+
modelFallback: modelRuntime.modelFallback,
|
|
161
189
|
...event,
|
|
162
190
|
attempt
|
|
163
191
|
});
|
|
@@ -167,7 +195,6 @@ async function callModelOnce({ messages, modelRuntime, options, executionId, int
|
|
|
167
195
|
let deliveredChunk = false;
|
|
168
196
|
const onChunk = options?.onChunk;
|
|
169
197
|
const context = {
|
|
170
|
-
messages,
|
|
171
198
|
modelRuntime,
|
|
172
199
|
executionId,
|
|
173
200
|
recordEvent,
|
|
@@ -183,7 +210,7 @@ async function callModelOnce({ messages, modelRuntime, options, executionId, int
|
|
|
183
210
|
} : options
|
|
184
211
|
};
|
|
185
212
|
try {
|
|
186
|
-
return await runWithAbortSignal(requestSignal, ()=>'system-one' === prepared.
|
|
213
|
+
return await runWithAbortSignal(requestSignal, ()=>'system-one' === prepared.kind ? callSystemOne(context, prepared.input) : 'codex' === prepared.kind ? callCodex(context, prepared.input) : callOpenAI(context, prepared));
|
|
187
214
|
} catch (error) {
|
|
188
215
|
options?.abortSignal?.throwIfAborted();
|
|
189
216
|
const lastError = toError(error);
|
|
@@ -193,6 +220,6 @@ async function callModelOnce({ messages, modelRuntime, options, executionId, int
|
|
|
193
220
|
cleanup();
|
|
194
221
|
}
|
|
195
222
|
}
|
|
196
|
-
export {
|
|
223
|
+
export { callGenerativeAI, callSystemOneAI };
|
|
197
224
|
|
|
198
225
|
//# sourceMappingURL=call-ai.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-model/service-caller/call-ai.mjs","sources":["../../../../src/ai-model/service-caller/call-ai.ts"],"sourcesContent":["import { getDebug } from '@midscene/shared/logger';\nimport { assert, uuid } from '@midscene/shared/utils';\nimport type { ModelRuntime } from '../models';\nimport { callCodex, prepareCodexCall } from './codex/call-codex';\nimport { isCodexAppServerProvider } from './codex/codex-app-server';\nimport {\n isModelCallRecordingEnabled,\n recordModelCallEvent,\n} from './model-call-recorder';\nimport { type PreparedOpenAIInput, callOpenAI } from './openai/call-openai';\nimport { prepareChatCompletion } from './openai/chat-completion/chat-completion';\nimport { prepareResponses } from './openai/responses/responses';\nimport {\n buildRequestAbortSignal,\n resolveEffectiveTimeoutMs,\n runWithAbortSignal,\n waitForRetry,\n} from './request-timeout';\nimport { callSystemOne, prepareSystemOne } from './system-one';\nimport type { ModelCallMessages } from './types';\nimport type {\n AICallResult,\n CallAIOptions,\n ModelCallContext,\n ModelCallResult,\n} from './types';\nimport {\n appendAIRequestFailureSummary,\n buildUsageInfo,\n nextInternalCallId,\n normalizeRetryCount,\n toError,\n} from './utils';\n\nconst DEFAULT_MODEL_PROTOCOL = 'openai-chat';\n\nexport async function callAI(\n messages: ModelCallMessages,\n modelRuntime: ModelRuntime,\n options?: CallAIOptions,\n): Promise<AICallResult> {\n options?.abortSignal?.throwIfAborted();\n const isStreaming = options?.stream === true;\n if (isStreaming) {\n // Explicit streaming is currently used only by recorder code generation.\n // Streaming can also be aggregated without onChunk, but then the caller\n // cannot consume incremental output, which is the purpose of this option.\n // Environment-enabled streaming supports that aggregation-only use case.\n // Once onChunk delivers a chunk, later errors are not retried to avoid\n // delivering duplicate content. Errors before the first chunk can retry.\n assert(\n typeof options?.onChunk === 'function',\n 'onChunk is required when stream: true is explicitly specified',\n );\n }\n\n // Low-level callers without a TaskRunner still need a stable ID for the\n // lifetime of this model call (including its network retries).\n const executionId = modelRuntime.executionId ?? `unscoped-${uuid()}`;\n\n // Stable internal ID for this call, used by the agent to deduplicate usage\n // across the onUsage callback and the task-dump-based collectUsageMetrics()\n // path when the provider does not return a request_id.\n const internalCallId = nextInternalCallId();\n\n const { config: modelConfig } = modelRuntime;\n\n const prepare = async (): Promise<PreparedModelInput> => {\n if (options?.systemOneRequest) {\n assert(\n modelConfig.modelFamily === 'jev',\n 'System One requests require the Jev model family',\n );\n return {\n protocol: 'system-one',\n input: await prepareSystemOne(modelConfig, options.systemOneRequest),\n };\n }\n const input = { messages, modelRuntime, options };\n if (isCodexAppServerProvider(modelConfig.openaiBaseURL)) {\n return { protocol: 'codex', input: prepareCodexCall(input) };\n }\n const protocol = modelConfig.protocol ?? DEFAULT_MODEL_PROTOCOL;\n\n assert(\n modelRuntime.adapter.supportedProtocols.includes(protocol),\n `Model adapter \"${modelConfig.modelFamily ?? 'default'}\" does not support protocol \"${protocol}\"`,\n );\n if (protocol === 'openai-responses') {\n return { protocol: 'responses', input: await prepareResponses(input) };\n }\n return {\n protocol: 'chat-completion',\n input: await prepareChatCompletion(input),\n };\n };\n\n const prepared = options?.abortSignal\n ? await runWithAbortSignal(options.abortSignal, prepare)\n : await prepare();\n\n const result = await callModelWithRetry({\n messages,\n modelRuntime,\n options,\n executionId,\n internalCallId,\n prepared,\n });\n\n const {\n rawUsage,\n timeCost,\n totalTimeCost,\n retryCount,\n requestId,\n responseModelName,\n ...response\n } = result;\n\n const rawUsageInfo = buildUsageInfo({\n apiProtocol: prepared.protocol,\n stream: response.isStreamed,\n usageData: rawUsage,\n timeCost,\n totalTimeCost,\n retryCount,\n requestId,\n responseModelName,\n modelName: modelConfig.modelName,\n modelDescription: modelConfig.modelDescription,\n slot: modelConfig.slot,\n internalCallId,\n });\n\n const usage = rawUsageInfo\n ? { ...rawUsageInfo, modelRouting: modelRuntime.modelRouting }\n : undefined;\n\n const debugProfileStats = getDebug('ai:profile:stats');\n const debugProfileDetail = getDebug('ai:profile:detail');\n debugProfileStats(\n `model, ${modelConfig.modelName}, mode, ${modelConfig.modelFamily || 'default'}, streaming, ${response.isStreamed}, prompt-tokens, ${usage?.prompt_tokens ?? ''}, completion-tokens, ${usage?.completion_tokens ?? ''}, total-tokens, ${usage?.total_tokens ?? ''}, cached-input, ${usage?.cached_input ?? ''}, cost-ms, ${timeCost ?? ''}, requestId, ${requestId ?? ''}, slot, ${modelConfig.slot}, configured-temperature, ${modelConfig.temperature ?? ''}`,\n );\n debugProfileDetail(`model usage detail: ${JSON.stringify(usage)}`);\n\n if (usage && modelRuntime.onUsage) {\n modelRuntime.onUsage(usage);\n }\n return { ...response, usage };\n}\n\ntype PreparedModelInput =\n | {\n protocol: 'system-one';\n input: Awaited<ReturnType<typeof prepareSystemOne>>;\n }\n | { protocol: 'codex'; input: ReturnType<typeof prepareCodexCall> }\n | PreparedOpenAIInput;\n\ntype ModelCallInput = {\n messages: ModelCallMessages;\n modelRuntime: ModelRuntime;\n options?: CallAIOptions;\n executionId: string;\n internalCallId: string;\n prepared: PreparedModelInput;\n};\n\n/** Carries the original failure across the retry boundary without replaying output. */\nclass NonRetryableModelCallError extends Error {\n readonly cause: Error;\n\n constructor(cause: Error) {\n super(cause.message, { cause });\n this.cause = cause;\n }\n}\n\nasync function callModelWithRetry(\n input: ModelCallInput,\n): Promise<ModelCallResult & { totalTimeCost: number; retryCount: number }> {\n const startTime = Date.now();\n const {\n modelRuntime: { config },\n options,\n } = input;\n const maxAttempts = normalizeRetryCount(config.retryCount) + 1;\n const retryInterval = config.retryInterval ?? 2000;\n const attemptErrors: Array<{ attempt: number; error: unknown }> = [];\n\n for (let attempt = 1; ; attempt++) {\n options?.abortSignal?.throwIfAborted();\n try {\n const result = await callModelOnce(input, attempt);\n return {\n ...result,\n totalTimeCost: Date.now() - startTime,\n retryCount: attempt - 1,\n };\n } catch (error) {\n options?.abortSignal?.throwIfAborted();\n if (error instanceof NonRetryableModelCallError) {\n throw error.cause;\n }\n const lastError = toError(error);\n attemptErrors.push({ attempt, error: lastError });\n if (attempt === maxAttempts) {\n throw appendAIRequestFailureSummary(\n lastError,\n attemptErrors,\n maxAttempts,\n );\n }\n getDebug('ai:call', {\n console: true,\n warning: {\n kind: 'model-request-retry',\n modelName: config.modelName,\n error: lastError,\n callId: input.internalCallId,\n attempt,\n maxAttempts,\n delayMs: retryInterval,\n },\n })(\n `AI call failed (attempt ${attempt}/${maxAttempts}), retrying in ${retryInterval}ms... Error: ${lastError.message}`,\n );\n }\n await waitForRetry(retryInterval, options?.abortSignal);\n }\n}\n\nasync function callModelOnce(\n {\n messages,\n modelRuntime,\n options,\n executionId,\n internalCallId,\n prepared,\n }: ModelCallInput,\n attempt: number,\n): Promise<ModelCallResult> {\n const { config: modelConfig } = modelRuntime;\n const recordingEnabled = isModelCallRecordingEnabled();\n const recordEvent =\n recordingEnabled || modelRuntime.onRequest\n ? (event: Record<string, unknown>) => {\n if (event.type === 'request') {\n const request = event.request as { url?: string } | undefined;\n modelRuntime.onRequest?.(request?.url);\n }\n if (!recordingEnabled) return;\n void recordModelCallEvent({\n executionId,\n callId: internalCallId,\n semanticRetryAttempt: options?.semanticRetryAttempt,\n slot: modelConfig.slot,\n intent: modelConfig.intent,\n modelFamily: modelConfig.modelFamily,\n modelRouting: modelRuntime.modelRouting,\n ...event,\n attempt,\n });\n }\n : undefined;\n const effectiveTimeoutMs = resolveEffectiveTimeoutMs(modelConfig.timeout);\n const { signal: requestSignal, cleanup } = buildRequestAbortSignal(\n effectiveTimeoutMs,\n options?.abortSignal,\n );\n let deliveredChunk = false;\n const onChunk = options?.onChunk;\n const context: ModelCallContext = {\n messages,\n modelRuntime,\n executionId,\n recordEvent,\n requestSignal,\n effectiveTimeoutMs,\n options: onChunk\n ? {\n ...options,\n onChunk: (chunk) => {\n requestSignal.throwIfAborted();\n deliveredChunk = true;\n onChunk(chunk);\n },\n }\n : options,\n };\n try {\n return await runWithAbortSignal(requestSignal, () =>\n prepared.protocol === 'system-one'\n ? callSystemOne(context, prepared.input)\n : prepared.protocol === 'codex'\n ? callCodex(context, prepared.input)\n : callOpenAI(context, prepared),\n );\n } catch (error) {\n options?.abortSignal?.throwIfAborted();\n const lastError = toError(error);\n if (deliveredChunk) {\n throw new NonRetryableModelCallError(lastError);\n }\n throw lastError;\n } finally {\n cleanup();\n }\n}\n"],"names":["DEFAULT_MODEL_PROTOCOL","callAI","messages","modelRuntime","options","isStreaming","assert","executionId","uuid","internalCallId","nextInternalCallId","modelConfig","prepare","prepareSystemOne","input","isCodexAppServerProvider","prepareCodexCall","protocol","prepareResponses","prepareChatCompletion","prepared","runWithAbortSignal","result","callModelWithRetry","rawUsage","timeCost","totalTimeCost","retryCount","requestId","responseModelName","response","rawUsageInfo","buildUsageInfo","usage","undefined","debugProfileStats","getDebug","debugProfileDetail","JSON","NonRetryableModelCallError","Error","cause","startTime","Date","config","maxAttempts","normalizeRetryCount","retryInterval","attemptErrors","attempt","callModelOnce","error","lastError","toError","appendAIRequestFailureSummary","waitForRetry","recordingEnabled","isModelCallRecordingEnabled","recordEvent","event","request","recordModelCallEvent","effectiveTimeoutMs","resolveEffectiveTimeoutMs","requestSignal","cleanup","buildRequestAbortSignal","deliveredChunk","onChunk","context","chunk","callSystemOne","callCodex","callOpenAI"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ai-model/service-caller/call-ai.mjs","sources":["../../../../src/ai-model/service-caller/call-ai.ts"],"sourcesContent":["import { getDebug } from '@midscene/shared/logger';\nimport { assert, uuid } from '@midscene/shared/utils';\nimport type { ModelRuntime } from '../models';\nimport { callCodex, prepareCodexCall } from './codex/call-codex';\nimport { isCodexAppServerProvider } from './codex/codex-app-server';\nimport {\n isModelCallRecordingEnabled,\n recordModelCallEvent,\n} from './model-call-recorder';\nimport { type PreparedOpenAIInput, callOpenAI } from './openai/call-openai';\nimport { prepareChatCompletion } from './openai/chat-completion/chat-completion';\nimport { prepareResponses } from './openai/responses/responses';\nimport {\n SiwcTokenExpiredError,\n prepareSiwcCall,\n siwcTokenManager,\n} from './openai/siwc';\nimport {\n buildRequestAbortSignal,\n resolveEffectiveTimeoutMs,\n runWithAbortSignal,\n waitForRetry,\n} from './request-timeout';\nimport {\n prepareSystemOne,\n callSystemOne as sendSystemOneRequest,\n} from './system-one';\nimport type { SystemOneRequest } from './system-one/schema';\nimport type { ModelCallMessages } from './types';\nimport type {\n AICallResult,\n CallAIOptions,\n ModelCallContext,\n ModelCallResult,\n} from './types';\nimport {\n appendAIRequestFailureSummary,\n buildUsageInfo,\n nextInternalCallId,\n normalizeRetryCount,\n toError,\n} from './utils';\n\nconst DEFAULT_MODEL_PROTOCOL = 'openai-chat';\n\nexport async function callGenerativeAI(\n messages: ModelCallMessages,\n originalModelRuntime: ModelRuntime,\n originalOptions?: CallAIOptions,\n): Promise<AICallResult> {\n originalOptions?.abortSignal?.throwIfAborted();\n const isStreaming = originalOptions?.stream === true;\n if (isStreaming) {\n // Explicit streaming is currently used only by recorder code generation.\n // Streaming can also be aggregated without onChunk, but then the caller\n // cannot consume incremental output, which is the purpose of this option.\n // Environment-enabled streaming supports that aggregation-only use case.\n // Once onChunk delivers a chunk, later errors are not retried to avoid\n // delivering duplicate content. Errors before the first chunk can retry.\n assert(\n typeof originalOptions?.onChunk === 'function',\n 'onChunk is required when stream: true is explicitly specified',\n );\n }\n\n // Resolve authentication constraints before protocol selection and validation.\n const { modelRuntime, options } = await prepareSiwcCall(\n originalModelRuntime,\n originalOptions,\n );\n\n const { config: modelConfig } = modelRuntime;\n return executeModelCall(modelRuntime, options, async () => {\n const input = { messages, modelRuntime, options };\n if (isCodexAppServerProvider(modelConfig.openaiBaseURL)) {\n return { kind: 'codex', input: prepareCodexCall(input) };\n }\n const protocol = modelConfig.protocol ?? DEFAULT_MODEL_PROTOCOL;\n\n assert(\n modelRuntime.adapter.supportedProtocols.includes(protocol),\n `Model adapter \"${modelConfig.modelFamily ?? 'default'}\" does not support protocol \"${protocol}\"`,\n );\n if (protocol === 'openai-responses') {\n return { kind: 'responses', input: await prepareResponses(input) };\n }\n return {\n kind: 'chat-completion',\n input: await prepareChatCompletion(input),\n };\n });\n}\n\nexport async function callSystemOneAI(\n request: SystemOneRequest,\n modelRuntime: ModelRuntime,\n options?: CallAIOptions,\n): Promise<AICallResult> {\n options?.abortSignal?.throwIfAborted();\n assert(!options?.stream, 'Jev does not support streaming output');\n assert(\n modelRuntime.config.modelFamily === 'jev',\n 'System One currently only supports the Jev model family in Midscene',\n );\n return executeModelCall(modelRuntime, options, async () => ({\n kind: 'system-one',\n input: await prepareSystemOne(modelRuntime.config, request),\n }));\n}\n\nasync function executeModelCall(\n modelRuntime: ModelRuntime,\n options: CallAIOptions | undefined,\n prepare: () => Promise<PreparedModelInput>,\n): Promise<AICallResult> {\n // Keep identifiers stable across all request attempts.\n const executionId = modelRuntime.executionId ?? `unscoped-${uuid()}`;\n const internalCallId = nextInternalCallId();\n const { config: modelConfig } = modelRuntime;\n\n const prepared = options?.abortSignal\n ? await runWithAbortSignal(options.abortSignal, prepare)\n : await prepare();\n\n const result = await callModelWithRetry({\n modelRuntime,\n options,\n executionId,\n internalCallId,\n prepared,\n });\n\n const {\n rawUsage,\n timeCost,\n totalTimeCost,\n retryCount,\n requestId,\n responseModelName,\n ...response\n } = result;\n\n const rawUsageInfo = buildUsageInfo({\n requestKind: prepared.kind,\n stream: response.isStreamed,\n usageData: rawUsage,\n timeCost,\n totalTimeCost,\n retryCount,\n requestId,\n responseModelName,\n modelName: modelConfig.modelName,\n modelDescription: modelConfig.modelDescription,\n slot: modelConfig.slot,\n internalCallId,\n });\n\n const usage = rawUsageInfo\n ? { ...rawUsageInfo, modelFallback: modelRuntime.modelFallback }\n : undefined;\n\n const debugProfileStats = getDebug('ai:profile:stats');\n const debugProfileDetail = getDebug('ai:profile:detail');\n debugProfileStats(\n `model, ${modelConfig.modelName}, mode, ${modelConfig.modelFamily || 'default'}, streaming, ${response.isStreamed}, prompt-tokens, ${usage?.prompt_tokens ?? ''}, completion-tokens, ${usage?.completion_tokens ?? ''}, total-tokens, ${usage?.total_tokens ?? ''}, cached-input, ${usage?.cached_input ?? ''}, cost-ms, ${timeCost ?? ''}, requestId, ${requestId ?? ''}, slot, ${modelConfig.slot}, configured-temperature, ${modelConfig.temperature ?? ''}`,\n );\n debugProfileDetail(`model usage detail: ${JSON.stringify(usage)}`);\n\n if (usage && modelRuntime.onUsage) {\n modelRuntime.onUsage(usage);\n }\n return { ...response, usage };\n}\n\ntype PreparedModelInput =\n | {\n kind: 'system-one';\n input: Awaited<ReturnType<typeof prepareSystemOne>>;\n }\n | { kind: 'codex'; input: ReturnType<typeof prepareCodexCall> }\n | PreparedOpenAIInput;\n\ntype ModelCallInput = {\n modelRuntime: ModelRuntime;\n options?: CallAIOptions;\n executionId: string;\n internalCallId: string;\n prepared: PreparedModelInput;\n};\n\n/** Carries the original failure across the retry boundary without replaying output. */\nclass NonRetryableModelCallError extends Error {\n readonly cause: Error;\n\n constructor(cause: Error) {\n super(cause.message, { cause });\n this.cause = cause;\n }\n}\n\nasync function callModelWithRetry(\n input: ModelCallInput,\n): Promise<ModelCallResult & { totalTimeCost: number; retryCount: number }> {\n const startTime = Date.now();\n const {\n modelRuntime: { config },\n options,\n } = input;\n const maxAttempts = normalizeRetryCount(config.retryCount) + 1;\n const retryInterval = config.retryInterval ?? 2000;\n const attemptErrors: Array<{ attempt: number; error: unknown }> = [];\n\n for (let attempt = 1; ; attempt++) {\n options?.abortSignal?.throwIfAborted();\n try {\n const result = await callModelOnce(input, attempt);\n return {\n ...result,\n totalTimeCost: Date.now() - startTime,\n retryCount: attempt - 1,\n };\n } catch (error) {\n options?.abortSignal?.throwIfAborted();\n if (error instanceof NonRetryableModelCallError) {\n throw error.cause;\n }\n // A rejected SIWC token gets one authentication retry, independently of\n // normal retryCount. Delivered chunks are rejected above before refreshing.\n if (error instanceof SiwcTokenExpiredError) {\n const refresh = async () => {\n assert(config.openaiApiKey, 'Missing rejected SIWC access token');\n await siwcTokenManager.refreshAccessToken(config.openaiApiKey);\n return prepareSiwcCall(input.modelRuntime, options);\n };\n // Cancel only this caller's wait; other callers may share the refresh.\n const refreshed = options?.abortSignal\n ? await runWithAbortSignal(options.abortSignal, refresh)\n : await refresh();\n options?.abortSignal?.throwIfAborted();\n try {\n const result = await callModelOnce(\n { ...input, ...refreshed },\n attempt + 1,\n );\n return {\n ...result,\n totalTimeCost: Date.now() - startTime,\n retryCount: attempt,\n };\n } catch (retryError) {\n // Do not re-enter either retry path after the refreshed request fails.\n throw retryError instanceof NonRetryableModelCallError\n ? retryError.cause\n : retryError;\n }\n }\n const lastError = toError(error);\n attemptErrors.push({ attempt, error: lastError });\n if (attempt === maxAttempts) {\n throw appendAIRequestFailureSummary(\n lastError,\n attemptErrors,\n maxAttempts,\n );\n }\n getDebug('ai:call', {\n console: true,\n warning: {\n kind: 'model-request-retry',\n modelName: config.modelName,\n error: lastError,\n callId: input.internalCallId,\n attempt,\n maxAttempts,\n delayMs: retryInterval,\n },\n })(\n `AI call failed (attempt ${attempt}/${maxAttempts}), retrying in ${retryInterval}ms... Error: ${lastError.message}`,\n );\n }\n await waitForRetry(retryInterval, options?.abortSignal);\n }\n}\n\nasync function callModelOnce(\n {\n modelRuntime,\n options,\n executionId,\n internalCallId,\n prepared,\n }: ModelCallInput,\n attempt: number,\n): Promise<ModelCallResult> {\n const { config: modelConfig } = modelRuntime;\n const recordingEnabled = isModelCallRecordingEnabled();\n const recordEvent =\n recordingEnabled || modelRuntime.onRequest\n ? (event: Record<string, unknown>) => {\n if (event.type === 'request') {\n const request = event.request as { url?: string } | undefined;\n modelRuntime.onRequest?.(request?.url);\n }\n if (!recordingEnabled) return;\n void recordModelCallEvent({\n executionId,\n callId: internalCallId,\n semanticRetryAttempt: options?.semanticRetryAttempt,\n slot: modelConfig.slot,\n intent: modelConfig.intent,\n modelFamily: modelConfig.modelFamily,\n modelFallback: modelRuntime.modelFallback,\n ...event,\n attempt,\n });\n }\n : undefined;\n const effectiveTimeoutMs = resolveEffectiveTimeoutMs(modelConfig.timeout);\n const { signal: requestSignal, cleanup } = buildRequestAbortSignal(\n effectiveTimeoutMs,\n options?.abortSignal,\n );\n let deliveredChunk = false;\n const onChunk = options?.onChunk;\n const context: ModelCallContext = {\n modelRuntime,\n executionId,\n recordEvent,\n requestSignal,\n effectiveTimeoutMs,\n options: onChunk\n ? {\n ...options,\n onChunk: (chunk) => {\n requestSignal.throwIfAborted();\n deliveredChunk = true;\n onChunk(chunk);\n },\n }\n : options,\n };\n try {\n return await runWithAbortSignal(requestSignal, () =>\n prepared.kind === 'system-one'\n ? sendSystemOneRequest(context, prepared.input)\n : prepared.kind === 'codex'\n ? callCodex(context, prepared.input)\n : callOpenAI(context, prepared),\n );\n } catch (error) {\n options?.abortSignal?.throwIfAborted();\n const lastError = toError(error);\n if (deliveredChunk) {\n throw new NonRetryableModelCallError(lastError);\n }\n throw lastError;\n } finally {\n cleanup();\n }\n}\n"],"names":["DEFAULT_MODEL_PROTOCOL","callGenerativeAI","messages","originalModelRuntime","originalOptions","isStreaming","assert","modelRuntime","options","prepareSiwcCall","modelConfig","executeModelCall","input","isCodexAppServerProvider","prepareCodexCall","protocol","prepareResponses","prepareChatCompletion","callSystemOneAI","request","prepareSystemOne","prepare","executionId","uuid","internalCallId","nextInternalCallId","prepared","runWithAbortSignal","result","callModelWithRetry","rawUsage","timeCost","totalTimeCost","retryCount","requestId","responseModelName","response","rawUsageInfo","buildUsageInfo","usage","undefined","debugProfileStats","getDebug","debugProfileDetail","JSON","NonRetryableModelCallError","Error","cause","startTime","Date","config","maxAttempts","normalizeRetryCount","retryInterval","attemptErrors","attempt","callModelOnce","error","SiwcTokenExpiredError","refresh","siwcTokenManager","refreshed","retryError","lastError","toError","appendAIRequestFailureSummary","waitForRetry","recordingEnabled","isModelCallRecordingEnabled","recordEvent","event","recordModelCallEvent","effectiveTimeoutMs","resolveEffectiveTimeoutMs","requestSignal","cleanup","buildRequestAbortSignal","deliveredChunk","onChunk","context","chunk","sendSystemOneRequest","callCodex","callOpenAI"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-model/service-caller/codex/call-codex.mjs","sources":["../../../../../src/ai-model/service-caller/codex/call-codex.ts"],"sourcesContent":["import type { ResolveImageDetail } from '../../model-adapter/types';\nimport type {
|
|
1
|
+
{"version":3,"file":"ai-model/service-caller/codex/call-codex.mjs","sources":["../../../../../src/ai-model/service-caller/codex/call-codex.ts"],"sourcesContent":["import type { ResolveImageDetail } from '../../model-adapter/types';\nimport type {\n ModelCallContext,\n ModelCallMessages,\n ModelCallResult,\n} from '../types';\nimport {\n type CodexAppServerRecordEvent,\n callAIWithCodexAppServer,\n} from './codex-app-server';\n\nexport const prepareCodexCall = ({\n messages,\n modelRuntime,\n options,\n}: Pick<ModelCallContext, 'modelRuntime' | 'options'> & {\n messages: ModelCallMessages;\n}) => {\n const { config: modelConfig, adapter } = modelRuntime;\n const { config } = adapter.buildCodexAppServerParams({\n intent: modelConfig.intent,\n userConfig: {\n reasoningEnabled: modelConfig.reasoningEnabled,\n reasoningEffort: modelConfig.reasoningEffort,\n reasoningBudget: modelConfig.reasoningBudget,\n },\n requiresOriginalImageDetail: options?.requiresOriginalImageDetail,\n });\n const resolveImageDetail: ResolveImageDetail = ({ imageDetail }) =>\n adapter.resolveImageDetail({\n imageDetail,\n intent: modelConfig.intent,\n requiresOriginalImageDetail: options?.requiresOriginalImageDetail,\n });\n return { messages, resolveImageDetail, requestParams: config };\n};\n\nexport const callCodex = async (\n { modelRuntime, options, recordEvent, requestSignal }: ModelCallContext,\n {\n messages,\n resolveImageDetail,\n requestParams,\n }: ReturnType<typeof prepareCodexCall>,\n): Promise<ModelCallResult> => {\n const { config: modelConfig } = modelRuntime;\n let protocolChunkSequence = 0;\n const codexStartTime = Date.now();\n const recordCodexEvent = recordEvent\n ? (event: CodexAppServerRecordEvent) => {\n if (event.type === 'chunk') {\n protocolChunkSequence += 1;\n recordEvent({\n ...event,\n attempt: 1,\n sequence: protocolChunkSequence,\n provider: 'codex-app-server',\n });\n return;\n }\n\n recordEvent({\n ...event,\n attempt: 1,\n provider: 'codex-app-server',\n });\n }\n : undefined;\n\n try {\n const codexResult = await callAIWithCodexAppServer(messages, modelConfig, {\n stream: options?.stream,\n onChunk: options?.onChunk,\n params: requestParams,\n resolveImageDetail,\n abortSignal: requestSignal,\n onRecordEvent: recordCodexEvent,\n });\n requestSignal.throwIfAborted();\n const { protocolMetadata, usage: rawUsage, ...response } = codexResult;\n const timeCost = Date.now() - codexStartTime;\n recordEvent?.({\n type: 'response',\n attempt: 1,\n provider: 'codex-app-server',\n final: {\n content: response.content,\n reasoningContent: response.reasoning_content,\n usage: rawUsage,\n timeCost,\n protocol: protocolMetadata,\n },\n });\n return {\n ...response,\n rawUsage,\n timeCost,\n requestId: protocolMetadata.turnId,\n };\n } catch (error) {\n recordEvent?.({\n type: 'error',\n attempt: 1,\n provider: 'codex-app-server',\n error:\n error instanceof Error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n }\n : String(error),\n });\n throw error;\n }\n};\n"],"names":["prepareCodexCall","messages","modelRuntime","options","modelConfig","adapter","config","resolveImageDetail","imageDetail","callCodex","recordEvent","requestSignal","requestParams","protocolChunkSequence","codexStartTime","Date","recordCodexEvent","event","undefined","codexResult","callAIWithCodexAppServer","protocolMetadata","rawUsage","response","timeCost","error","Error","String"],"mappings":";AAWO,MAAMA,mBAAmB,CAAC,EAC/BC,QAAQ,EACRC,YAAY,EACZC,OAAO,EAGR;IACC,MAAM,EAAE,QAAQC,WAAW,EAAEC,OAAO,EAAE,GAAGH;IACzC,MAAM,EAAEI,MAAM,EAAE,GAAGD,QAAQ,yBAAyB,CAAC;QACnD,QAAQD,YAAY,MAAM;QAC1B,YAAY;YACV,kBAAkBA,YAAY,gBAAgB;YAC9C,iBAAiBA,YAAY,eAAe;YAC5C,iBAAiBA,YAAY,eAAe;QAC9C;QACA,6BAA6BD,SAAS;IACxC;IACA,MAAMI,qBAAyC,CAAC,EAAEC,WAAW,EAAE,GAC7DH,QAAQ,kBAAkB,CAAC;YACzBG;YACA,QAAQJ,YAAY,MAAM;YAC1B,6BAA6BD,SAAS;QACxC;IACF,OAAO;QAAEF;QAAUM;QAAoB,eAAeD;IAAO;AAC/D;AAEO,MAAMG,YAAY,OACvB,EAAEP,YAAY,EAAEC,OAAO,EAAEO,WAAW,EAAEC,aAAa,EAAoB,EACvE,EACEV,QAAQ,EACRM,kBAAkB,EAClBK,aAAa,EACuB;IAEtC,MAAM,EAAE,QAAQR,WAAW,EAAE,GAAGF;IAChC,IAAIW,wBAAwB;IAC5B,MAAMC,iBAAiBC,KAAK,GAAG;IAC/B,MAAMC,mBAAmBN,cACrB,CAACO;QACC,IAAIA,AAAe,YAAfA,MAAM,IAAI,EAAc;YAC1BJ,yBAAyB;YACzBH,YAAY;gBACV,GAAGO,KAAK;gBACR,SAAS;gBACT,UAAUJ;gBACV,UAAU;YACZ;YACA;QACF;QAEAH,YAAY;YACV,GAAGO,KAAK;YACR,SAAS;YACT,UAAU;QACZ;IACF,IACAC;IAEJ,IAAI;QACF,MAAMC,cAAc,MAAMC,yBAAyBnB,UAAUG,aAAa;YACxE,QAAQD,SAAS;YACjB,SAASA,SAAS;YAClB,QAAQS;YACRL;YACA,aAAaI;YACb,eAAeK;QACjB;QACAL,cAAc,cAAc;QAC5B,MAAM,EAAEU,gBAAgB,EAAE,OAAOC,QAAQ,EAAE,GAAGC,UAAU,GAAGJ;QAC3D,MAAMK,WAAWT,KAAK,GAAG,KAAKD;QAC9BJ,cAAc;YACZ,MAAM;YACN,SAAS;YACT,UAAU;YACV,OAAO;gBACL,SAASa,SAAS,OAAO;gBACzB,kBAAkBA,SAAS,iBAAiB;gBAC5C,OAAOD;gBACPE;gBACA,UAAUH;YACZ;QACF;QACA,OAAO;YACL,GAAGE,QAAQ;YACXD;YACAE;YACA,WAAWH,iBAAiB,MAAM;QACpC;IACF,EAAE,OAAOI,OAAO;QACdf,cAAc;YACZ,MAAM;YACN,SAAS;YACT,UAAU;YACV,OACEe,iBAAiBC,QACb;gBACE,MAAMD,MAAM,IAAI;gBAChB,SAASA,MAAM,OAAO;gBACtB,OAAOA,MAAM,KAAK;YACpB,IACAE,OAAOF;QACf;QACA,MAAMA;IACR;AACF"}
|