@coclaw/openclaw-coclaw 0.25.0 → 0.25.1
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/package.json
CHANGED
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
* (纯字符串:含 '/'、'/' 不在端点;不依赖 cfg)→ loadConfig → 凭据门 → 存在性
|
|
13
13
|
* 形态校验**前置在 loadConfig 之前**,cfg 不可读时非法形态仍是 INVALID_ARGS 而非 IO_FAILED
|
|
14
14
|
* - 凭据门 + 选模型器枚举 + list 信号全部走统一别名感知原语(resolve.js),杜绝跨界面口径分叉(§ 3.2.1)
|
|
15
|
-
* - set 存在性 + listUsable
|
|
15
|
+
* - set 存在性 + listUsable 枚举走同一目录源 loadModelCatalog({readOnly:false}):选得到 ⇒ 设得上(红线天然成立)。
|
|
16
|
+
* 用 readOnly:false(含 manifest 合并)才带进 openai-codex/* 等 manifest-only provider;readOnly:true 只读落盘,
|
|
17
|
+
* 这类从不落盘的 provider 缺失(oauth 已授权却选不出,本次回归根因)。
|
|
16
18
|
*/
|
|
17
19
|
|
|
18
20
|
import { listAllPrimariesWithCredentials, computeProviderUsable, enumerateUsableModels } from './resolve.js';
|
|
@@ -66,15 +68,16 @@ function buildCredDeps(sdk, agentDir) {
|
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
/**
|
|
69
|
-
* cfg 相关的 primary 校验:凭据门 +
|
|
71
|
+
* cfg 相关的 primary 校验:凭据门 + 目录源存在性。
|
|
70
72
|
* 形态拆分由调用方完成(fail-fast 前置在 loadConfig 之前)。
|
|
71
73
|
*
|
|
72
74
|
* - 凭据门走统一原语 computeProviderUsable(取代旧 ledger-only isProviderAuthProfileConfigured):
|
|
73
75
|
* 覆盖 env + 账本 + 内联 + 别名套餐,修「内联/env/别名 provider 选得到设不上」,且继续拒幽灵
|
|
74
76
|
* (无任何源凭据的 openai/gpt-5.5 被门挡住)。cooldown 中凭据仍算已配置(沿用 isProviderApiKeyConfigured 立场)。
|
|
75
|
-
* -
|
|
76
|
-
*
|
|
77
|
-
*
|
|
77
|
+
* - 存在性走目录源 loadModelCatalog({readOnly:false})(与选模型器枚举同源 → 「选得到设不上」红线天然成立);
|
|
78
|
+
* 用 readOnly:false(含 manifest 合并)才有 openai-codex/* 这类 manifest-only provider(readOnly:true 只读落盘缺它们)。
|
|
79
|
+
* 它返回全量 manifest,但与凭据门联用并不过松——无凭据 provider 仍被门挡住;且非 buildModelsProviderData,无幽灵注入。
|
|
80
|
+
* 整体抛错由外层 catch 映射 IO_FAILED(set 是写操作,失败安全为先)。
|
|
78
81
|
*
|
|
79
82
|
* @returns {Promise<string|null>} 错误 message;null 表通过
|
|
80
83
|
*/
|
|
@@ -82,7 +85,7 @@ async function validateProviderCredAndCatalog({ provider, model, primary, cfg, s
|
|
|
82
85
|
if (!computeProviderUsable(primary, cfg, deps)) {
|
|
83
86
|
return `provider "${provider}" has no usable credential`;
|
|
84
87
|
}
|
|
85
|
-
const entries = await sdk.loadModelCatalog({ readOnly:
|
|
88
|
+
const entries = await sdk.loadModelCatalog({ readOnly: false });
|
|
86
89
|
const exists = Array.isArray(entries)
|
|
87
90
|
&& entries.some((e) => e && e.provider === provider && e.id === model);
|
|
88
91
|
if (!exists) {
|
|
@@ -97,7 +100,7 @@ async function validateProviderCredAndCatalog({ provider, model, primary, cfg, s
|
|
|
97
100
|
* @param {object} opts
|
|
98
101
|
* @param {object} opts.sdk
|
|
99
102
|
* @param {Function} opts.sdk.mutateConfigFile - openclaw/plugin-sdk/config-mutation(set 写盘)
|
|
100
|
-
* @param {Function} opts.sdk.loadModelCatalog - openclaw/plugin-sdk/agent-runtime(set 存在性 + listUsable
|
|
103
|
+
* @param {Function} opts.sdk.loadModelCatalog - openclaw/plugin-sdk/agent-runtime(set 存在性 + listUsable 枚举的目录源)
|
|
101
104
|
* @param {Function} opts.sdk.isProviderApiKeyConfigured - openclaw/plugin-sdk/provider-auth(env+账本凭据信号,别名感知)
|
|
102
105
|
* @param {Function} opts.sdk.hasConfiguredSecretInput - openclaw/plugin-sdk/provider-auth(内联 key 判定)
|
|
103
106
|
* @param {Function} opts.sdk.ensureAuthProfileStore - openclaw/plugin-sdk/provider-auth(账本非空 / configuredProviders)
|
|
@@ -233,12 +236,13 @@ export function buildModelDefaultHandlers({ sdk, loadConfig, resolveAgentDir })
|
|
|
233
236
|
// 故四个消费点在产线天然同 dir;测试可注入按 agentId 分目录的 resolver 钉住贯穿。
|
|
234
237
|
const deps = buildCredDeps(sdk, resolveAgentDir(agentId));
|
|
235
238
|
|
|
236
|
-
//
|
|
237
|
-
//
|
|
239
|
+
// 目录源 loadModelCatalog({readOnly:false}):含 manifest 合并,才有 openai-codex/* 这类 manifest-only provider
|
|
240
|
+
// (readOnly:true 只读落盘缺它们 → oauth 已授权却选不出,本次回归根因)。
|
|
241
|
+
// 整体抛错(罕见,如 runtime config 取不到)→ 兜空 entries:byProvider 退化为空,
|
|
238
242
|
// 但 configuredProviders 不依赖目录仍可算 → 「不空白」,UI 加 provider 排除照常工作(§ 3.2.1 降级)。
|
|
239
243
|
let entries;
|
|
240
244
|
try {
|
|
241
|
-
entries = await sdk.loadModelCatalog({ readOnly:
|
|
245
|
+
entries = await sdk.loadModelCatalog({ readOnly: false });
|
|
242
246
|
}
|
|
243
247
|
catch {
|
|
244
248
|
entries = [];
|
|
@@ -123,21 +123,49 @@ function hasInlineKey(cfg, provider, deps) {
|
|
|
123
123
|
return false;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
/**
|
|
127
|
+
* 某 provider(裸名)在自管账本里有没有任一来源凭据(oauth / token / api-key)。
|
|
128
|
+
* 别名感知:查询名与各 profile 的 cred.provider 两侧都过 resolveProviderIdForAuth 归一后比较,
|
|
129
|
+
* 与 computeConfiguredProviders 的账本口径一致(不校验 type:匹配到任一 well-formed profile 即算)。
|
|
130
|
+
* 补 isProviderApiKeyConfigured 只认 api-key 的缺口:纯 OAuth provider(codex / copilot 等设备码家族)
|
|
131
|
+
* 只有 oauth 凭据、无 key,旧逻辑两路皆 false 会被全组丢出 byProvider(见 changeset / TODO 根成因)。
|
|
132
|
+
* 归一为空串的 provider 不匹配(与 computeConfiguredProviders 的丢弃空 id 一致),
|
|
133
|
+
* 避免 whitespace-only 查询名与 whitespace-only cred 同归一到 '' 的误命中。
|
|
134
|
+
* @param {string} provider - 裸 provider 名
|
|
135
|
+
* @param {object} deps - { agentDir, ensureAuthProfileStore, resolveProviderIdForAuth }
|
|
136
|
+
* @returns {boolean}
|
|
137
|
+
*/
|
|
138
|
+
function hasLedgerCred(provider, deps) {
|
|
139
|
+
const store = deps.ensureAuthProfileStore(deps.agentDir, { allowKeychainPrompt: false });
|
|
140
|
+
if (!store || !store.profiles || typeof store.profiles !== 'object') return false;
|
|
141
|
+
const targetId = deps.resolveProviderIdForAuth(provider);
|
|
142
|
+
if (!targetId) return false;
|
|
143
|
+
for (const cred of Object.values(store.profiles)) {
|
|
144
|
+
if (!cred || typeof cred.provider !== 'string' || cred.provider.length === 0) continue;
|
|
145
|
+
if (deps.resolveProviderIdForAuth(cred.provider) === targetId) return true;
|
|
146
|
+
}
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
|
|
126
150
|
/**
|
|
127
151
|
* 某 provider(裸名,无斜杠)有没有可用凭据 —— 统一别名感知原语。
|
|
128
|
-
* 判定 = isProviderApiKeyConfigured
|
|
129
|
-
* ∪ hasInlineKey(内联 key
|
|
130
|
-
*
|
|
131
|
-
*
|
|
152
|
+
* 判定 = isProviderApiKeyConfigured(env + 账本里的 api-key,别名归一其内部完成)
|
|
153
|
+
* ∪ hasInlineKey(内联 key,别名归一)
|
|
154
|
+
* ∪ hasLedgerCred(账本里的 oauth/token 等非 api-key 凭据,别名归一)。
|
|
155
|
+
* 覆盖 env + 内联 + 账本(api-key / oauth / token 全口径)+ 别名套餐;
|
|
156
|
+
* 统一漏 IAM/本地(hasAuthForModelProvider 未导出 plugin-sdk,接受)。
|
|
157
|
+
* 选模型器枚举 / model.set 门 / providerUsable 三个消费点同吃本原语;noKey 走姊妹原语
|
|
158
|
+
* computeHasAnyUsableCredential(同源探针 + 账本判定),口径与本原语对齐、不跨界面分叉。
|
|
132
159
|
* @param {string|null} provider - 裸 provider 名(如 'openai' / 'volcengine-plan')
|
|
133
160
|
* @param {object} cfg
|
|
134
|
-
* @param {object} deps - { agentDir, isProviderApiKeyConfigured, hasConfiguredSecretInput, resolveProviderIdForAuth }
|
|
161
|
+
* @param {object} deps - { agentDir, isProviderApiKeyConfigured, hasConfiguredSecretInput, ensureAuthProfileStore, resolveProviderIdForAuth }
|
|
135
162
|
* @returns {boolean}
|
|
136
163
|
*/
|
|
137
164
|
export function computeProviderUsableByName(provider, cfg, deps) {
|
|
138
165
|
if (typeof provider !== 'string' || provider.length === 0) return false;
|
|
139
166
|
if (deps.isProviderApiKeyConfigured({ provider, agentDir: deps.agentDir })) return true;
|
|
140
|
-
|
|
167
|
+
if (hasInlineKey(cfg, provider, deps)) return true;
|
|
168
|
+
return hasLedgerCred(provider, deps);
|
|
141
169
|
}
|
|
142
170
|
|
|
143
171
|
/**
|
|
@@ -244,8 +272,8 @@ export function computeConfiguredProviders(cfg, deps) {
|
|
|
244
272
|
}
|
|
245
273
|
|
|
246
274
|
/**
|
|
247
|
-
*
|
|
248
|
-
* catalogEntries
|
|
275
|
+
* 选模型器枚举(纯同步):把目录源按 entry.provider 分组,留 computeProviderUsableByName 为真的 provider。
|
|
276
|
+
* catalogEntries 由调用方传入(handler 调 loadModelCatalog({readOnly:false}) 后传进来;含 manifest 才有 openai-codex/* 这类 manifest-only provider),
|
|
249
277
|
* 本函数不自己 await loadModelCatalog;空 / 非数组 entries → 空 byProvider。
|
|
250
278
|
* 变体 provider(如 volcengine-plan)经 manifest 目录行进入 entries、再经基座 key 别名感知保留;
|
|
251
279
|
* 无凭据 provider 被丢(含幽灵——幽灵根本不在 loadModelCatalog 这个源里)。
|
|
@@ -254,7 +282,7 @@ export function computeConfiguredProviders(cfg, deps) {
|
|
|
254
282
|
* (image_generation 等是网关响应的另一类型;imageModel 注入只在 buildModelsProviderData 尾部、不在此源),
|
|
255
283
|
* 故无"纯图像/视频生成"条目混入;entry.input 是"输入"模态而非输出 kind,按它滤会误删多模态文本模型。
|
|
256
284
|
*
|
|
257
|
-
* @param {object[]} catalogEntries - loadModelCatalog({readOnly:
|
|
285
|
+
* @param {object[]} catalogEntries - loadModelCatalog({readOnly:false}) 的结果(ModelCatalogEntry[])
|
|
258
286
|
* @param {object} cfg
|
|
259
287
|
* @param {object} deps - { agentDir, isProviderApiKeyConfigured, hasConfiguredSecretInput, resolveProviderIdForAuth, ensureAuthProfileStore }
|
|
260
288
|
* @returns {{ byProvider: Record<string, string[]>, configuredProviders: string[] }}
|