@x-otto/cli 0.0.1-alpha.8 → 0.1.0-alpha.9
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/README.md +72 -65
- package/bin/otto.js +6 -0
- package/dist/{auth-command-CXAB3_hs.js → auth-command-WddVZWgz.js} +3 -3
- package/dist/auth-command-WddVZWgz.js.map +1 -0
- package/dist/backend-handler-DUafuNWw.js +3 -0
- package/dist/backend-handler-DUafuNWw.js.map +1 -0
- package/dist/build-id-CGJ2iv_o.js +3 -0
- package/dist/build-id-CGJ2iv_o.js.map +1 -0
- package/dist/bundled-extensions/plugin-otto-wire-protocols/plugin-dist/meta.json +1 -1
- package/dist/bundled-extensions/plugin-otto-wire-protocols/plugin-dist/plugin.cjs +1056 -43191
- package/dist/bundled-extensions/plugin-otto-wire-protocols/plugin.ts +4 -0
- package/dist/bundled-extensions/plugin-otto-wire-protocols/src/anthropic-messages.ts +14 -24
- package/dist/bundled-extensions/plugin-otto-wire-protocols/src/openai-completions.ts +27 -10
- package/dist/bundled-extensions/plugin-otto-wire-protocols/src/openai-responses.ts +20 -17
- package/dist/bundled-extensions-C3n8jg20.js +3 -0
- package/dist/bundled-extensions-C3n8jg20.js.map +1 -0
- package/dist/command-dispatcher-Du_Sk33M.js +18 -0
- package/dist/command-dispatcher-Du_Sk33M.js.map +1 -0
- package/dist/config-migration-DatflIxs.js.map +1 -1
- package/dist/create-host-app-DwlqiuPB.js +3 -0
- package/dist/create-host-app-DwlqiuPB.js.map +1 -0
- package/dist/{daemon-base-YOWgYYN7.js → daemon-base-D015ew5y.js} +1 -1
- package/dist/{daemon-base-YOWgYYN7.js.map → daemon-base-D015ew5y.js.map} +1 -1
- package/dist/discover-with-bundled-B5d4q___.js +2 -0
- package/dist/discover-with-bundled-CF8qFP41.js +3 -0
- package/dist/discover-with-bundled-CF8qFP41.js.map +1 -0
- package/dist/doctor-CPIS47uZ.js +36 -0
- package/dist/doctor-CPIS47uZ.js.map +1 -0
- package/dist/{doctor-attach-_zeIJewx.js → doctor-attach-DEoE7eFx.js} +2 -2
- package/dist/{doctor-attach-_zeIJewx.js.map → doctor-attach-DEoE7eFx.js.map} +1 -1
- package/dist/{doctor-cdp-K_mIFRfA.js → doctor-cdp-Cj9IFpEP.js} +1 -1
- package/dist/{doctor-cdp-K_mIFRfA.js.map → doctor-cdp-Cj9IFpEP.js.map} +1 -1
- package/dist/{doctor-heap-Rr2nNvcw.js → doctor-heap-SIxiRvL8.js} +2 -2
- package/dist/{doctor-heap-Rr2nNvcw.js.map → doctor-heap-SIxiRvL8.js.map} +1 -1
- package/dist/{doctor-ps-OL3FGQYu.js → doctor-ps-DNVOF6yY.js} +2 -2
- package/dist/{doctor-ps-OL3FGQYu.js.map → doctor-ps-DNVOF6yY.js.map} +1 -1
- package/dist/export-trajectory-D-BcH0Wt.js +14 -0
- package/dist/export-trajectory-D-BcH0Wt.js.map +1 -0
- package/dist/extension-CoJqqktf.js +2 -0
- package/dist/extension-Dpn8gltG.js +179 -0
- package/dist/extension-Dpn8gltG.js.map +1 -0
- package/dist/feedback-BivcU-y_.js +30 -0
- package/dist/feedback-BivcU-y_.js.map +1 -0
- package/dist/feedback-backend-methods-DkhBM2l6.js +3 -0
- package/dist/feedback-backend-methods-DkhBM2l6.js.map +1 -0
- package/dist/{feishu-setup-D6vnuNLw.js → feishu-setup-DbAq_BRH.js} +2 -2
- package/dist/feishu-setup-DbAq_BRH.js.map +1 -0
- package/dist/ftue-doctor-recovery-CKTMnxM8.js +3 -0
- package/dist/ftue-doctor-recovery-CKTMnxM8.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -13
- package/dist/index.js.map +1 -1
- package/dist/install-CEPczuet.js +11 -0
- package/dist/install-CEPczuet.js.map +1 -0
- package/dist/install-CG6b6fox.js +2 -0
- package/dist/interactive-schedule-DVJjhqnt.js +3 -0
- package/dist/interactive-schedule-DVJjhqnt.js.map +1 -0
- package/dist/{mcp-DbTYT7hB.js → mcp-DjReRjuu.js} +1 -1
- package/dist/{mcp-DbTYT7hB.js.map → mcp-DjReRjuu.js.map} +1 -1
- package/dist/mcp-server-Dq72PTeW.js +5 -0
- package/dist/mcp-server-Dq72PTeW.js.map +1 -0
- package/dist/{migrate-boDXhEyV.js → migrate-BBi3Txu2.js} +1 -1
- package/dist/{migrate-boDXhEyV.js.map → migrate-BBi3Txu2.js.map} +1 -1
- package/dist/observe-BqLCpmFD.js +83 -0
- package/dist/observe-BqLCpmFD.js.map +1 -0
- package/dist/parse-cli-Cp5a7taK.js +3 -0
- package/dist/parse-cli-Cp5a7taK.js.map +1 -0
- package/dist/persistence-BvLRnpfi.js +85 -0
- package/dist/persistence-BvLRnpfi.js.map +1 -0
- package/dist/plugin-assembly-check-BntT5W6H.js +3 -0
- package/dist/plugin-assembly-check-BntT5W6H.js.map +1 -0
- package/dist/{proxy-evg7ZvoD.js → proxy-CFZDVIwI.js} +1 -1
- package/dist/proxy-CFZDVIwI.js.map +1 -0
- package/dist/proxy-CkSf8ziQ.js +2 -0
- package/dist/{ps-DKrluEuy.js → ps-BVKv6rAo.js} +1 -1
- package/dist/{ps-DKrluEuy.js.map → ps-BVKv6rAo.js.map} +1 -1
- package/dist/{registry-D0NONjLv.js → registry-BUvu-es1.js} +4 -4
- package/dist/registry-BUvu-es1.js.map +1 -0
- package/dist/registry-DYHR-ONu.js +2 -0
- package/dist/{run-attach-Ci5jYyCa.js → run-attach-X35puJ_n.js} +2 -2
- package/dist/{run-attach-Ci5jYyCa.js.map → run-attach-X35puJ_n.js.map} +1 -1
- package/dist/schedule-C_uHI2M8.js +5 -0
- package/dist/schedule-C_uHI2M8.js.map +1 -0
- package/dist/serve-a4W5vFXL.js +21 -0
- package/dist/serve-a4W5vFXL.js.map +1 -0
- package/dist/{service-client-BLNeugM9.js → service-client-cfUUP4EE.js} +1 -1
- package/dist/{service-client-BLNeugM9.js.map → service-client-cfUUP4EE.js.map} +1 -1
- package/dist/{version-DaMJKLwj.js → version-D1Hmbcos.js} +2 -2
- package/dist/{version-DaMJKLwj.js.map → version-D1Hmbcos.js.map} +1 -1
- package/package.json +28 -25
- package/dist/auth-command-CXAB3_hs.js.map +0 -1
- package/dist/build-id-DMyumG97.js +0 -3
- package/dist/build-id-DMyumG97.js.map +0 -1
- package/dist/bundled-extensions/plugin-skill-inductor/otto-plugin.json +0 -8
- package/dist/bundled-extensions/plugin-skill-inductor/plugin-dist/meta.json +0 -1
- package/dist/bundled-extensions/plugin-skill-inductor/plugin-dist/plugin.cjs +0 -52781
- package/dist/bundled-extensions/plugin-skill-inductor/plugin.ts +0 -77
- package/dist/bundled-extensions/plugin-skill-inductor/src/candidate-detector.ts +0 -210
- package/dist/bundled-extensions/plugin-skill-inductor/src/candidate-digest.ts +0 -146
- package/dist/bundled-extensions/plugin-skill-inductor/src/candidate-store.ts +0 -87
- package/dist/bundled-extensions/plugin-skill-inductor/src/episode-store.ts +0 -122
- package/dist/bundled-extensions/plugin-skill-inductor/src/episode.ts +0 -125
- package/dist/bundled-extensions/plugin-skill-inductor/src/extraction-prompt.ts +0 -97
- package/dist/bundled-extensions/plugin-skill-inductor/src/inductor-service.ts +0 -183
- package/dist/bundled-extensions/plugin-skill-inductor/src/similarity.ts +0 -58
- package/dist/command-dispatcher-CR7RCzUl.js +0 -13
- package/dist/command-dispatcher-CR7RCzUl.js.map +0 -1
- package/dist/debug-CiosFwme.js +0 -34
- package/dist/debug-CiosFwme.js.map +0 -1
- package/dist/discover-with-bundled-CznLjkkw.js +0 -3
- package/dist/discover-with-bundled-CznLjkkw.js.map +0 -1
- package/dist/doctor-C84-hhEr.js +0 -30
- package/dist/doctor-C84-hhEr.js.map +0 -1
- package/dist/extension-BKXIr86F.js +0 -170
- package/dist/extension-BKXIr86F.js.map +0 -1
- package/dist/extension-CnON6Xum.js +0 -2
- package/dist/extension-plugin-B6WF8HzF.js +0 -2
- package/dist/extension-plugin-DH-4D0tt.js +0 -7
- package/dist/extension-plugin-DH-4D0tt.js.map +0 -1
- package/dist/feedback-7qQsiabD.js +0 -21
- package/dist/feedback-7qQsiabD.js.map +0 -1
- package/dist/feedback-Cc1eBsqy.js +0 -2
- package/dist/feishu-setup-D6vnuNLw.js.map +0 -1
- package/dist/install-DlVJRHRT.js +0 -11
- package/dist/install-DlVJRHRT.js.map +0 -1
- package/dist/install-WCcQ9k9M.js +0 -2
- package/dist/model-auth-7WCx1j-B.js +0 -2
- package/dist/model-auth-ylinoVLo.js +0 -3
- package/dist/model-auth-ylinoVLo.js.map +0 -1
- package/dist/observe-CVg-MRM2.js +0 -32
- package/dist/observe-CVg-MRM2.js.map +0 -1
- package/dist/parse-cli-2Cs-ZcSC.js +0 -3
- package/dist/parse-cli-2Cs-ZcSC.js.map +0 -1
- package/dist/persistenced-CCwHu1Ww.js +0 -36
- package/dist/persistenced-CCwHu1Ww.js.map +0 -1
- package/dist/proxy-BvdBsB1O.js +0 -2
- package/dist/proxy-evg7ZvoD.js.map +0 -1
- package/dist/registry-B3nfN62q.js +0 -2
- package/dist/registry-D0NONjLv.js.map +0 -1
- package/dist/remote-persistence-server-B_hONoVR.js +0 -35
- package/dist/remote-persistence-server-B_hONoVR.js.map +0 -1
- package/dist/serve-pVR6UIT9.js +0 -21
- package/dist/serve-pVR6UIT9.js.map +0 -1
- package/dist/time-travel-ZozuPPI-.js +0 -21
- package/dist/time-travel-ZozuPPI-.js.map +0 -1
|
@@ -19,6 +19,8 @@ import type { WireProtocolFactoryInput } from '@x-otto/provider'
|
|
|
19
19
|
function adaptToOpenAICompletions(input: WireProtocolFactoryInput) {
|
|
20
20
|
return createOpenAICompletionsProvider({
|
|
21
21
|
resolveKey: () => input.resolveAuth().then((a) => a?.token),
|
|
22
|
+
resolveBaseUrl: input.resolveBaseUrl,
|
|
23
|
+
preferResolvedBaseUrl: input.preferResolvedBaseUrl,
|
|
22
24
|
headers: input.headers,
|
|
23
25
|
tokenDerivedHeaders: input.tokenDerivedHeaders,
|
|
24
26
|
logger: input.logger,
|
|
@@ -32,6 +34,7 @@ function adaptToOpenAIResponses(input: WireProtocolFactoryInput) {
|
|
|
32
34
|
return createOpenAIResponsesProvider({
|
|
33
35
|
resolveKey: () => input.resolveAuth().then((a) => a?.token),
|
|
34
36
|
resolveBaseUrl: input.resolveBaseUrl,
|
|
37
|
+
preferResolvedBaseUrl: input.preferResolvedBaseUrl,
|
|
35
38
|
tokenDerivedHeaders: input.tokenDerivedHeaders,
|
|
36
39
|
headers: input.headers,
|
|
37
40
|
logger: input.logger,
|
|
@@ -45,6 +48,7 @@ function adaptToAnthropicMessages(input: WireProtocolFactoryInput) {
|
|
|
45
48
|
return createAnthropicProvider({
|
|
46
49
|
resolveAuth: () => input.resolveAuth(),
|
|
47
50
|
resolveBaseUrl: input.resolveBaseUrl,
|
|
51
|
+
preferResolvedBaseUrl: input.preferResolvedBaseUrl,
|
|
48
52
|
customizeRequest: input.customizeRequest,
|
|
49
53
|
logger: input.logger,
|
|
50
54
|
// RFC-270 缺陷 1(P0):此前这两行缺失——另两个 adapter 都透传了 headers,唯独本
|
|
@@ -41,30 +41,12 @@ import type {
|
|
|
41
41
|
* (红线:绝不 fallback 到 createLogger)。
|
|
42
42
|
*/
|
|
43
43
|
import type { WireProtocolLogger } from '@x-otto/provider'
|
|
44
|
-
|
|
45
|
-
const noopLogger: WireProtocolLogger = { debug: () => {}, info: () => {}, warn: () => {}, error: () => {} }
|
|
44
|
+
import { noopWireProtocolLogger, resolveProviderBaseUrl } from '@x-otto/provider'
|
|
46
45
|
|
|
47
46
|
export type AnthropicCredentialResolver = () => Promise<string | undefined>
|
|
48
47
|
export type AnthropicAuthResolver = () => Promise<ResolvedAuth | undefined>
|
|
49
48
|
export type AnthropicBaseUrlResolver = () => Promise<string | undefined>
|
|
50
49
|
|
|
51
|
-
async function resolveBaseUrl(
|
|
52
|
-
modelBaseUrl: string,
|
|
53
|
-
resolver?: AnthropicBaseUrlResolver,
|
|
54
|
-
): Promise<string> {
|
|
55
|
-
const envUrl = process.env['ANTHROPIC_BASE_URL']
|
|
56
|
-
if (envUrl) {
|
|
57
|
-
return envUrl
|
|
58
|
-
}
|
|
59
|
-
if (resolver) {
|
|
60
|
-
const authUrl = await resolver()
|
|
61
|
-
if (authUrl) {
|
|
62
|
-
return authUrl
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return modelBaseUrl
|
|
66
|
-
}
|
|
67
|
-
|
|
68
50
|
export function toBudgetTokens(level: string, maxOutputTokens: number): number {
|
|
69
51
|
// RFC-235:Anthropic 是 token 预算型(非 effort 关键字)。otto 档位 → maxOutput 百分比预算。
|
|
70
52
|
// 词表对齐 Claude Code(去 minimal 加 max):low 25% / medium 50% / high 75% / xhigh 90% / max 95%。
|
|
@@ -623,6 +605,7 @@ export interface AnthropicProviderOptions {
|
|
|
623
605
|
resolveKey?: AnthropicCredentialResolver
|
|
624
606
|
resolveAuth?: AnthropicAuthResolver
|
|
625
607
|
resolveBaseUrl?: AnthropicBaseUrlResolver
|
|
608
|
+
preferResolvedBaseUrl?: boolean
|
|
626
609
|
/**
|
|
627
610
|
* 请求定制点(RFC-140 D-copilot-spoof-split,取代此前的 `enableClaudeCodeSpoof` 布尔开关):
|
|
628
611
|
* `createAnthropicProvider` 是**任意**声明 `wireApi: 'anthropic-messages'` 的插件共用的
|
|
@@ -638,8 +621,8 @@ export interface AnthropicProviderOptions {
|
|
|
638
621
|
*/
|
|
639
622
|
customizeRequest?: (input: AnthropicRequestCustomizeInput) => AnthropicRequestCustomization
|
|
640
623
|
/**
|
|
641
|
-
* RFC-270 缺陷 1(P0):静态额外 headers(如 manifest
|
|
642
|
-
*
|
|
624
|
+
* RFC-270 缺陷 1(P0):静态额外 headers(如 manifest 声明的企业网关路由标识头)。
|
|
625
|
+
* 此前本 Options **完全没有这个字段**——`plugin.ts` 的 adapter 也因此未透传
|
|
643
626
|
* `input.headers`,声明式 provider 给本协议写的 headers 被静默丢弃且不报错。该缺陷长期
|
|
644
627
|
* 未被发现,是因为唯一的真实用例 `anthropic-version` 恰好被 @anthropic-ai/sdk 自身硬编码
|
|
645
628
|
* 补上(`client.js` buildRequest),掩盖了丢弃。
|
|
@@ -649,7 +632,7 @@ export interface AnthropicProviderOptions {
|
|
|
649
632
|
tokenDerivedHeaders?: TokenDerivedHeader[]
|
|
650
633
|
/** RFC-270 D3:manifest 显式声明后,允许自定义头覆盖鉴权头(企业网关换鉴权)。 */
|
|
651
634
|
allowAuthHeaderOverride?: boolean
|
|
652
|
-
/** RFC-185 D3:宿主注入的日志端口,缺省 no-op
|
|
635
|
+
/** RFC-185 D3:宿主注入的日志端口,缺省 no-op(`noopWireProtocolLogger`,@x-otto/provider 单例)。 */
|
|
653
636
|
logger?: WireProtocolLogger
|
|
654
637
|
}
|
|
655
638
|
|
|
@@ -666,10 +649,11 @@ class AnthropicStream implements ProviderStream {
|
|
|
666
649
|
constructor(
|
|
667
650
|
private readonly resolveCredential?: AnthropicCredentialResolver,
|
|
668
651
|
private readonly baseUrlResolver?: AnthropicBaseUrlResolver,
|
|
652
|
+
private readonly preferResolvedBaseUrl = false,
|
|
669
653
|
private readonly authResolver?: AnthropicAuthResolver,
|
|
670
654
|
/** 见 `AnthropicProviderOptions.customizeRequest` 注释。缺省 = 零定制。 */
|
|
671
655
|
private readonly customizeRequest?: (input: AnthropicRequestCustomizeInput) => AnthropicRequestCustomization,
|
|
672
|
-
private readonly logger: WireProtocolLogger =
|
|
656
|
+
private readonly logger: WireProtocolLogger = noopWireProtocolLogger,
|
|
673
657
|
/** 见 `AnthropicProviderOptions.headers`(RFC-270 缺陷 1 修复)。 */
|
|
674
658
|
private readonly staticHeaders?: Record<string, string>,
|
|
675
659
|
private readonly tokenDerivedHeaders?: TokenDerivedHeader[],
|
|
@@ -711,7 +695,12 @@ class AnthropicStream implements ProviderStream {
|
|
|
711
695
|
context: StreamContext,
|
|
712
696
|
auth: ResolvedAuth,
|
|
713
697
|
): Promise<{ client: Anthropic; requestParams: Anthropic.MessageStreamParams; baseURL: string }> {
|
|
714
|
-
const baseURL = await
|
|
698
|
+
const baseURL = await resolveProviderBaseUrl(
|
|
699
|
+
'ANTHROPIC_BASE_URL',
|
|
700
|
+
this.baseUrlResolver,
|
|
701
|
+
model.baseUrl,
|
|
702
|
+
this.preferResolvedBaseUrl,
|
|
703
|
+
)
|
|
715
704
|
// RFC-140 D-copilot-spoof-split:本文件不再判断"是否 oauth 才伪装"——那是具体厂商
|
|
716
705
|
// (如 plugin-anthropic 的 Claude Code 伪装)的业务逻辑,交给 customizeRequest 定制器
|
|
717
706
|
// 自行按 input.auth.mode 判断要不要返回定制内容。未提供定制器 = 零调用零开销。
|
|
@@ -906,6 +895,7 @@ export function createAnthropicProvider(options: AnthropicProviderOptions = {}):
|
|
|
906
895
|
return new AnthropicStream(
|
|
907
896
|
options.resolveKey,
|
|
908
897
|
options.resolveBaseUrl,
|
|
898
|
+
options.preferResolvedBaseUrl,
|
|
909
899
|
options.resolveAuth,
|
|
910
900
|
options.customizeRequest,
|
|
911
901
|
options.logger,
|
|
@@ -20,9 +20,7 @@ import type {
|
|
|
20
20
|
WireRequestCustomization,
|
|
21
21
|
WireRequestCustomizeInput,
|
|
22
22
|
} from '@x-otto/provider'
|
|
23
|
-
|
|
24
|
-
/** RFC-185 D3:日志走宿主注入端口,缺省 no-op——插件源码禁 createLogger(防第二单例直写 stderr)。 */
|
|
25
|
-
const noopLogger: WireProtocolLogger = { debug: () => {}, info: () => {}, warn: () => {}, error: () => {} }
|
|
23
|
+
import { noopWireProtocolLogger, resolveProviderBaseUrl } from '@x-otto/provider'
|
|
26
24
|
|
|
27
25
|
/**
|
|
28
26
|
* 通用 OpenAI Chat Completions provider(对标 opencode/pi 的 openai-compatible 基座)。
|
|
@@ -38,6 +36,7 @@ const noopLogger: WireProtocolLogger = { debug: () => {}, info: () => {}, warn:
|
|
|
38
36
|
* RFC-122 D3:支持声明式 `tokenDerivedHeaders`(插件 provider 轴),JWT claim 值提取后注入请求头。
|
|
39
37
|
*/
|
|
40
38
|
export type OpenAICompletionsCredentialResolver = (provider: string) => Promise<string | undefined>
|
|
39
|
+
export type OpenAICompletionsBaseUrlResolver = () => Promise<string | undefined>
|
|
41
40
|
|
|
42
41
|
// RFC-122 D3:TokenDerivedHeader 定义单一真源在 @x-otto/provider(协议中立层,见该包
|
|
43
42
|
// types.ts 头注释)——此前本文件与 openai-responses.ts 各自重复定义一份相同形状,
|
|
@@ -45,6 +44,8 @@ export type OpenAICompletionsCredentialResolver = (provider: string) => Promise<
|
|
|
45
44
|
|
|
46
45
|
export interface OpenAICompletionsProviderOptions {
|
|
47
46
|
resolveKey?: OpenAICompletionsCredentialResolver
|
|
47
|
+
resolveBaseUrl?: OpenAICompletionsBaseUrlResolver
|
|
48
|
+
preferResolvedBaseUrl?: boolean
|
|
48
49
|
/** RFC-122 D3:静态额外 headers(如 vendor 自定义头)。 */
|
|
49
50
|
headers?: Record<string, string>
|
|
50
51
|
/** RFC-122 D3:JWT claim 派生 headers。 */
|
|
@@ -73,9 +74,11 @@ class OpenAICompletionsStream implements ProviderStream {
|
|
|
73
74
|
|
|
74
75
|
constructor(
|
|
75
76
|
private readonly resolveCredential?: OpenAICompletionsCredentialResolver,
|
|
77
|
+
private readonly baseUrlResolver?: OpenAICompletionsBaseUrlResolver,
|
|
78
|
+
private readonly preferResolvedBaseUrl = false,
|
|
76
79
|
private readonly extraHeaders?: Record<string, string>,
|
|
77
80
|
private readonly tokenDerivedHeaders?: TokenDerivedHeader[],
|
|
78
|
-
private readonly logger: WireProtocolLogger =
|
|
81
|
+
private readonly logger: WireProtocolLogger = noopWireProtocolLogger,
|
|
79
82
|
/** 见 `OpenAICompletionsProviderOptions.customizeRequest`。缺省 = 零定制。 */
|
|
80
83
|
private readonly customizeRequest?: (input: WireRequestCustomizeInput) => WireRequestCustomization,
|
|
81
84
|
private readonly allowAuthHeaderOverride?: boolean,
|
|
@@ -127,17 +130,29 @@ class OpenAICompletionsStream implements ProviderStream {
|
|
|
127
130
|
})
|
|
128
131
|
|
|
129
132
|
yield* streamChatCompletions({
|
|
130
|
-
url: `${
|
|
133
|
+
url: `${await resolveProviderBaseUrl(
|
|
134
|
+
model.provider === 'deepseek' ? 'DEEPSEEK_BASE_URL' : 'OPENAI_BASE_URL',
|
|
135
|
+
this.baseUrlResolver,
|
|
136
|
+
model.baseUrl,
|
|
137
|
+
this.preferResolvedBaseUrl,
|
|
138
|
+
)}/chat/completions`,
|
|
131
139
|
headers,
|
|
132
140
|
body: buildChatCompletionsBody(model, context),
|
|
133
141
|
identity: { api: model.api, provider: model.provider, model: model.id },
|
|
134
142
|
signal,
|
|
135
143
|
timeout: options.timeout,
|
|
136
|
-
// RFC-
|
|
137
|
-
//
|
|
138
|
-
//
|
|
139
|
-
//
|
|
140
|
-
|
|
144
|
+
// RFC-361:**不再**给 reasoning 模型统一放大 idleTimeout。
|
|
145
|
+
//
|
|
146
|
+
// 旧做法(`idleTimeout: model.reasoning ? 300_000 : undefined`)是"把阈值往上堆"的
|
|
147
|
+
// 治标手段:它同时放宽了两个语义完全不同的阶段——"首 token 前的长思考"(正常)与
|
|
148
|
+
// "已开始吐字后突然静默"(真卡死)。后果有二:①300s 对 deepseek-v4-flash·max 的
|
|
149
|
+
// thinking 仍然不够,误杀照旧(真机实测 4 个长推理任务因此失败);②真卡死的检测被
|
|
150
|
+
// 无谓延迟到 5 分钟。
|
|
151
|
+
//
|
|
152
|
+
// 新机制由 `@x-otto/shared` 的 `stream()` 分段承担:首字节前默认 900s(放行长思考),
|
|
153
|
+
// 首字节后回到 120s(保持对流中断的灵敏度)。故此处不再需要按 `model.reasoning`
|
|
154
|
+
// 区分——分段判据比"模型是否声明 reasoning"更准(同一个 reasoning 模型的不同 turn,
|
|
155
|
+
// 思考时长差异极大,用模型属性预测本就是弱相关变量)。
|
|
141
156
|
// RFC-232(终局修正):跨 wire 协议救回违约响应,见 @x-otto/provider stream-state.ts。
|
|
142
157
|
registeredToolNames: registeredToolNames(context.tools),
|
|
143
158
|
})
|
|
@@ -149,6 +164,8 @@ export function createOpenAICompletionsProvider(
|
|
|
149
164
|
): ProviderStream {
|
|
150
165
|
return new OpenAICompletionsStream(
|
|
151
166
|
options.resolveKey,
|
|
167
|
+
options.resolveBaseUrl,
|
|
168
|
+
options.preferResolvedBaseUrl,
|
|
152
169
|
options.headers,
|
|
153
170
|
options.tokenDerivedHeaders,
|
|
154
171
|
options.logger,
|
|
@@ -34,9 +34,7 @@ import type {
|
|
|
34
34
|
WireRequestCustomization,
|
|
35
35
|
WireRequestCustomizeInput,
|
|
36
36
|
} from '@x-otto/provider'
|
|
37
|
-
|
|
38
|
-
/** RFC-185 D3:日志走宿主注入端口,缺省 no-op——插件源码禁 createLogger(防第二单例直写 stderr)。 */
|
|
39
|
-
const noopLogger: WireProtocolLogger = { debug: () => {}, info: () => {}, warn: () => {}, error: () => {} }
|
|
37
|
+
import { noopWireProtocolLogger, resolveProviderBaseUrl } from '@x-otto/provider'
|
|
40
38
|
|
|
41
39
|
export type OpenAIResponsesCredentialResolver = () => Promise<string | undefined>
|
|
42
40
|
export type OpenAIResponsesBaseUrlResolver = () => Promise<string | undefined>
|
|
@@ -318,7 +316,11 @@ function dispatchResponsesSSEEvent(
|
|
|
318
316
|
}
|
|
319
317
|
const hasTool = [...state.blocks.values()].some((b) => b.kind === 'tool_call')
|
|
320
318
|
if (type === 'response.incomplete') {
|
|
321
|
-
|
|
319
|
+
// 08-14 review A1:不再无条件映射 max_tokens——读 incomplete_details.reason 区分截断根因。
|
|
320
|
+
// OpenAI Responses 的 incomplete 可能因 max_output_tokens(真截断,走引擎续写/升档路径)
|
|
321
|
+
// 或 content_filter(内容过滤,应映射 refusal 让引擎干净终止,而非误走"触顶重试"白烧一轮)。
|
|
322
|
+
const reason = (response?.incomplete_details as Record<string, unknown> | undefined)?.reason
|
|
323
|
+
state.stopReason = reason === 'content_filter' ? 'refusal' : 'max_tokens'
|
|
322
324
|
} else {
|
|
323
325
|
state.stopReason = hasTool ? 'tool_use' : 'end_turn'
|
|
324
326
|
}
|
|
@@ -359,6 +361,7 @@ class OpenAIResponsesStream implements ProviderStream {
|
|
|
359
361
|
constructor(
|
|
360
362
|
private readonly resolveCredential?: OpenAIResponsesCredentialResolver,
|
|
361
363
|
private readonly baseUrlResolver?: OpenAIResponsesBaseUrlResolver,
|
|
364
|
+
private readonly preferResolvedBaseUrl = false,
|
|
362
365
|
private readonly tokenDerivedHeaders?: TokenDerivedHeader[],
|
|
363
366
|
/**
|
|
364
367
|
* 终局 review 2026-07-10 P1-7:静态额外 headers(如 vendor 自定义头),对齐
|
|
@@ -369,7 +372,7 @@ class OpenAIResponsesStream implements ProviderStream {
|
|
|
369
372
|
* 补齐此字段后硬编码分支已冗余,随本次一并删除(见下方 buildHeaders)。
|
|
370
373
|
*/
|
|
371
374
|
private readonly staticHeaders?: Record<string, string>,
|
|
372
|
-
private readonly logger: WireProtocolLogger =
|
|
375
|
+
private readonly logger: WireProtocolLogger = noopWireProtocolLogger,
|
|
373
376
|
/** 见 `OpenAIResponsesProviderOptions.customizeRequest`。缺省 = 零定制。 */
|
|
374
377
|
private readonly customizeRequest?: (input: WireRequestCustomizeInput) => WireRequestCustomization,
|
|
375
378
|
private readonly allowAuthHeaderOverride?: boolean,
|
|
@@ -401,17 +404,12 @@ class OpenAIResponsesStream implements ProviderStream {
|
|
|
401
404
|
}
|
|
402
405
|
|
|
403
406
|
private async resolveBaseUrl(model: Model): Promise<string> {
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
if (url) {
|
|
411
|
-
return url
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
return model.baseUrl
|
|
407
|
+
return resolveProviderBaseUrl(
|
|
408
|
+
'OPENAI_BASE_URL',
|
|
409
|
+
this.baseUrlResolver,
|
|
410
|
+
model.baseUrl,
|
|
411
|
+
this.preferResolvedBaseUrl,
|
|
412
|
+
)
|
|
415
413
|
}
|
|
416
414
|
|
|
417
415
|
/**
|
|
@@ -464,7 +462,10 @@ class OpenAIResponsesStream implements ProviderStream {
|
|
|
464
462
|
body,
|
|
465
463
|
headers: this.buildHeaders(auth, model.provider),
|
|
466
464
|
signal,
|
|
467
|
-
|
|
465
|
+
// RFC-361 D5:不再兜底 300s——那会让墙钟先于首字节空闲阈值(默认 900s)触发,
|
|
466
|
+
// 使分段计时成为死代码。`stream()` 会按 `max(requested, firstTokenIdle + 余量)`
|
|
467
|
+
// 统一解析,保证墙钟总是大于首字节阈值。o3/o1 等 reasoning 模型的长思考同样受益。
|
|
468
|
+
timeout: options.timeout,
|
|
468
469
|
onResponse: (h) => {
|
|
469
470
|
responseHeaders = h
|
|
470
471
|
},
|
|
@@ -541,6 +542,7 @@ class OpenAIResponsesStream implements ProviderStream {
|
|
|
541
542
|
export interface OpenAIResponsesProviderOptions {
|
|
542
543
|
resolveKey?: OpenAIResponsesCredentialResolver
|
|
543
544
|
resolveBaseUrl?: OpenAIResponsesBaseUrlResolver
|
|
545
|
+
preferResolvedBaseUrl?: boolean
|
|
544
546
|
/** RFC-122 D3:插件声明式 token 派生 header(provider-loader 装载时注入) */
|
|
545
547
|
tokenDerivedHeaders?: TokenDerivedHeader[]
|
|
546
548
|
/**
|
|
@@ -566,6 +568,7 @@ export function createOpenAIResponsesProvider(
|
|
|
566
568
|
return new OpenAIResponsesStream(
|
|
567
569
|
options.resolveKey,
|
|
568
570
|
options.resolveBaseUrl,
|
|
571
|
+
options.preferResolvedBaseUrl,
|
|
569
572
|
options.tokenDerivedHeaders,
|
|
570
573
|
options.headers,
|
|
571
574
|
options.logger,
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{dirname as e,join as t}from"node:path";import{existsSync as n}from"node:fs";import{fileURLToPath as r}from"node:url";function i(){let i=t(e(r(import.meta.url)),`bundled-extensions`);return n(i)?i:``}export{i as t};
|
|
3
|
+
//# sourceMappingURL=bundled-extensions-C3n8jg20.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundled-extensions-C3n8jg20.js","names":[],"sources":["../src/bundled-extensions.ts"],"sourcesContent":["/**\n * bundled-extensions.ts —— 随 otto 分发的内置扩展目录解析。\n *\n * cli 构建时(scripts/bundle-builtin-extensions.mjs)把内置扩展的编译产物拷进\n * `dist/bundled-extensions/<id>/`。本模块解析该目录,供 `discoverPlugins` 作为\n * 最高优先扫描层传入。\n *\n * ## 为什么在 cli 层解析而不是 plugin 层\n * `@x-otto/plugin` 是库,不该知道 cli 的 dist 布局(反向依赖)。目录位置只有 cli\n * 自己知道(它拥有 `import.meta.url` → dist 的路径)。\n *\n * ## 分布式的可移植性\n * 发布物 = `dist/`(package.json files:[\"dist\"])。本目录与 dist 同级,\n * 打包后相对路径关系保持不变——`import.meta.url` 解析到 dist 内的一个 js,\n * `../bundled-extensions` 即发布物内的扩展目录。\n */\nimport { existsSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\n/** cli 发布物内内置扩展目录(不存在 = 该发布物没带内置扩展,返回空)。 */\nexport function bundledExtensionsDir(): string {\n // dist 里的这个 js 文件 → dist/bundled-extensions(同目录,非父级——这是 cli 构建\n // 时拷进去的发布物内目录,见 scripts/bundle-builtin-extensions.mjs)。\n const dir = join(dirname(fileURLToPath(import.meta.url)), 'bundled-extensions')\n return existsSync(dir) ? dir : ''\n}\n"],"mappings":";4HAqBA,SAAgB,GAA+B,CAG7C,IAAM,EAAM,EAAK,EAAQ,EAAc,OAAO,KAAK,IAAI,CAAC,CAAE,qBAAqB,CAC/E,OAAO,EAAW,EAAI,CAAG,EAAM"}
|