@bolloon/bolloon-agent 0.5.0 → 0.5.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/dist/agents/execution-supervisor.js +87 -5
- package/dist/agents/model-policy.js +651 -0
- package/dist/agents/pi-sdk-tools.js +84 -33
- package/dist/agents/pi-sdk.js +83 -23
- package/dist/agents/run-store.js +53 -0
- package/dist/agents/task/task-runner.js +8 -1
- package/dist/agents/workflow-pivot-loop.js +19 -12
- package/dist/cli/clipboard.js +65 -0
- package/dist/cli/ink-app.js +145 -17
- package/dist/cli/log-gate.js +386 -0
- package/dist/cli/mention-data.js +2 -0
- package/dist/cli/model-selector.js +538 -0
- package/dist/cli/reply-hygiene.js +54 -0
- package/dist/cli/setup-wizard.js +686 -69
- package/dist/cli/startup-notice.js +160 -0
- package/dist/cli/stores.js +22 -1
- package/dist/cli/theme.js +49 -0
- package/dist/cli/tui-select.js +970 -0
- package/dist/cli-entry.js +125 -18
- package/dist/electron-build/agents/execution-supervisor.js +86 -4
- package/dist/electron-build/agents/execution-supervisor.js.map +1 -1
- package/dist/electron-build/agents/goal-store.js.map +1 -1
- package/dist/electron-build/agents/model-policy.js +706 -0
- package/dist/electron-build/agents/model-policy.js.map +1 -0
- package/dist/electron-build/agents/pi-sdk-tools.js +84 -33
- package/dist/electron-build/agents/pi-sdk-tools.js.map +1 -1
- package/dist/electron-build/agents/pi-sdk-types.js.map +1 -1
- package/dist/electron-build/agents/pi-sdk.js +83 -23
- package/dist/electron-build/agents/pi-sdk.js.map +1 -1
- package/dist/electron-build/agents/run-store.js +55 -1
- package/dist/electron-build/agents/run-store.js.map +1 -1
- package/dist/electron-build/agents/task/task-runner.js +8 -1
- package/dist/electron-build/agents/task/task-runner.js.map +1 -1
- package/dist/electron-build/agents/workflow-pivot-loop.js +19 -12
- package/dist/electron-build/agents/workflow-pivot-loop.js.map +1 -1
- package/dist/electron-build/llm/config-store.js +146 -6
- package/dist/electron-build/llm/config-store.js.map +1 -1
- package/dist/electron-build/llm/connection-probe.js +764 -0
- package/dist/electron-build/llm/connection-probe.js.map +1 -0
- package/dist/electron-build/llm/custom-provider-store.js +272 -0
- package/dist/electron-build/llm/custom-provider-store.js.map +1 -0
- package/dist/electron-build/llm/data/provider-catalog-baked.js +23 -0
- package/dist/electron-build/llm/data/provider-catalog-baked.js.map +1 -0
- package/dist/electron-build/llm/model-catalog.js +778 -0
- package/dist/electron-build/llm/model-catalog.js.map +1 -0
- package/dist/electron-build/llm/model-discovery.js +1202 -0
- package/dist/electron-build/llm/model-discovery.js.map +1 -0
- package/dist/electron-build/llm/model-selection.js +1315 -0
- package/dist/electron-build/llm/model-selection.js.map +1 -0
- package/dist/electron-build/llm/pi-ai.js +70 -11
- package/dist/electron-build/llm/pi-ai.js.map +1 -1
- package/dist/electron-build/llm/provider-catalog.js +969 -0
- package/dist/electron-build/llm/provider-catalog.js.map +1 -0
- package/dist/electron-build/llm/provider-registry.js +950 -0
- package/dist/electron-build/llm/provider-registry.js.map +1 -0
- package/dist/electron-build/llm/tool-name.js +266 -0
- package/dist/electron-build/llm/tool-name.js.map +1 -0
- package/dist/electron-build/utils/dual-source-facts.js +236 -0
- package/dist/electron-build/utils/dual-source-facts.js.map +1 -0
- package/dist/electron-build/utils/dual-source.js +32 -156
- package/dist/electron-build/utils/dual-source.js.map +1 -1
- package/dist/electron-build/utils/update-manager.js +22 -72
- package/dist/electron-build/utils/update-manager.js.map +1 -1
- package/dist/electron-build/utils/update-state.js +2 -19
- package/dist/electron-build/utils/update-state.js.map +1 -1
- package/dist/electron-build/utils/version-identity.js +193 -0
- package/dist/electron-build/utils/version-identity.js.map +1 -0
- package/dist/electron-build/utils/version-info.js +47 -101
- package/dist/electron-build/utils/version-info.js.map +1 -1
- package/dist/index.js +282 -96
- package/dist/ios/bolloon-web.json +10 -0
- package/dist/ios/mobile-contacts.js +44 -11
- package/dist/ios/mobile-core.js +1723 -84
- package/dist/ios/mobile-tasks.js +339 -0
- package/dist/ios/mobile-update.js +1442 -0
- package/dist/ios/mobile.js +308 -35
- package/dist/ios/routes-llm-config.js +344 -52
- package/dist/ios/routes-mobile-tasks.js +353 -0
- package/dist/ios/server.js +163 -4
- package/dist/ios/sw.js +1 -1
- package/dist/llm/config-store.js +146 -6
- package/dist/llm/connection-probe.js +744 -0
- package/dist/llm/custom-provider-store.js +224 -0
- package/dist/llm/data/provider-catalog-baked.js +19 -0
- package/dist/llm/model-catalog.js +717 -0
- package/dist/llm/model-discovery.js +1137 -0
- package/dist/llm/model-selection.js +1241 -0
- package/dist/llm/pi-ai.js +70 -11
- package/dist/llm/provider-catalog.js +898 -0
- package/dist/llm/provider-registry.js +917 -0
- package/dist/llm/tool-name.js +220 -0
- package/dist/setup/onboard.js +34 -8
- package/dist/utils/dual-source-facts.js +223 -0
- package/dist/utils/dual-source.js +12 -141
- package/dist/utils/update-manager.js +16 -59
- package/dist/utils/update-state.js +6 -18
- package/dist/utils/version-identity.js +176 -0
- package/dist/utils/version-info.js +9 -78
- package/dist/web/bolloon-web.json +10 -0
- package/dist/web/mobile-core.js +1721 -84
- package/dist/web/mobile-update.js +1442 -0
- package/dist/web/mobile.js +308 -35
- package/dist/web/routes-llm-config.js +344 -52
- package/dist/web/sw.js +1 -1
- package/package.json +1 -1
- package/scripts/build-web.ts +36 -0
package/dist/llm/pi-ai.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as path from 'path';
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import { request, Agent } from 'undici';
|
|
4
|
+
import { sanitizeToolsForApi } from './tool-name.js';
|
|
4
5
|
/**
|
|
5
6
|
* 外部 system 注入钩子.
|
|
6
7
|
* 调用方 (e.g. auto-evolve-loop) 用 setSystemPrependProvider() 注册一个返回字符串的函数,
|
|
@@ -53,6 +54,34 @@ export class PiAIModel {
|
|
|
53
54
|
}
|
|
54
55
|
return valid;
|
|
55
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* 按**注册表**取这条 provider 的认证头与 query (P3 注册表是唯一出处)。
|
|
59
|
+
*
|
|
60
|
+
* `providerId` (声明 id) 优先于运行期分支 id —— 自定义供应商的 `authHeader` 只有按声明 id 才查得到。
|
|
61
|
+
* 拿不到 (模块不可用 / 这个 id 不在注册表里) → 返回 `null`, 各分支**退回自己的旧内置常量**,
|
|
62
|
+
* 于是内置供应商的请求头一字不变 (门禁 `scripts/verify-model-wiring.ts` 逐分支比对真收到的头)。
|
|
63
|
+
*/
|
|
64
|
+
async registryAuth() {
|
|
65
|
+
const declared = String(this.config.providerId || this.provider || '').trim();
|
|
66
|
+
if (!declared)
|
|
67
|
+
return null;
|
|
68
|
+
try {
|
|
69
|
+
const reg = await import('./provider-registry.js');
|
|
70
|
+
const entry = reg.getProviderRegistryEntry(declared);
|
|
71
|
+
if (!entry)
|
|
72
|
+
return null;
|
|
73
|
+
const auth = reg.authHeadersFor(entry, this.getApiKey());
|
|
74
|
+
return {
|
|
75
|
+
headers: (auth && auth.headers) || {},
|
|
76
|
+
query: (auth && auth.query) || {},
|
|
77
|
+
authKind: String(entry.auth && entry.auth.kind || 'none'),
|
|
78
|
+
entryKind: String(entry.kind || ''),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
56
85
|
/**
|
|
57
86
|
* 与 LLM 对话.
|
|
58
87
|
*
|
|
@@ -207,8 +236,14 @@ export class PiAIModel {
|
|
|
207
236
|
if (tools && tools.length > 0) {
|
|
208
237
|
// 预格式化的 tools (含参数 schema) → 直接使用
|
|
209
238
|
if (typeof tools[0] === 'object' && tools[0]?.type === 'function') {
|
|
210
|
-
|
|
211
|
-
|
|
239
|
+
// 2026-09-26: **工具名出网的唯一净化边界**.
|
|
240
|
+
// 全仓只有这里产出 wire 形状的 tools 数组 (所有入口: CLI/Web/MCP/技能/子 Agent/长期任务
|
|
241
|
+
// 都经 chat() → generateText() 到这里). 非法字符 (如 contact.list_authorized 里的 '.')
|
|
242
|
+
// 会让整个请求 400: Invalid 'tools[120].function.name': string does not match pattern.
|
|
243
|
+
// 净化同时把「原名 ↔ API 名」登记进 globalToolNameRoutes, 回程派发靠它还原成真名.
|
|
244
|
+
// 撞名/无名 → 抛错点名, 不许静默.
|
|
245
|
+
openaiTools = sanitizeToolsForApi(tools);
|
|
246
|
+
const toolDescriptions = openaiTools.map(t => `- ${t.function.name}: ${t.function.description || ''} ${Object.keys(t.function.parameters?.properties || {}).length > 0 ? `(${Object.keys(t.function.parameters.properties).join(', ')})` : ''}`).join('\n');
|
|
212
247
|
finalMessages = [{ role: 'system', content: `可用工具:\n${toolDescriptions}` }, ...messages];
|
|
213
248
|
}
|
|
214
249
|
}
|
|
@@ -348,6 +383,11 @@ export class PiAIModel {
|
|
|
348
383
|
// 会静默忽略 npm undici Agent 的 dispatcher (实测 localPort 不变), 导致重试仍在复用坏连接.
|
|
349
384
|
// 改用 npm undici 的 request(): 独立连接池 + 重试传 dispatcher 真正生效 (新 TCP 连接).
|
|
350
385
|
let retryAgent = null;
|
|
386
|
+
// 认证头走注册表 (拿不到注册表 → 退回本分支原来的 `Authorization: Bearer <key>`)
|
|
387
|
+
const regAuth = await this.registryAuth();
|
|
388
|
+
const authHeaders = regAuth
|
|
389
|
+
? regAuth.headers
|
|
390
|
+
: { 'Authorization': `Bearer ${apiKey}` };
|
|
351
391
|
for (let attempt = 0; attempt < 4; attempt++) {
|
|
352
392
|
const _tFetch = Date.now();
|
|
353
393
|
let statusCode = 0;
|
|
@@ -357,7 +397,7 @@ export class PiAIModel {
|
|
|
357
397
|
method: 'POST',
|
|
358
398
|
headers: {
|
|
359
399
|
'Content-Type': 'application/json',
|
|
360
|
-
|
|
400
|
+
...authHeaders,
|
|
361
401
|
},
|
|
362
402
|
body: JSON.stringify(requestBody),
|
|
363
403
|
signal: this.combinedSignal(signal),
|
|
@@ -439,12 +479,14 @@ export class PiAIModel {
|
|
|
439
479
|
}
|
|
440
480
|
const systemMessage = messages.find(m => m.role === 'system')?.content || '';
|
|
441
481
|
const userMessages = messages.filter(m => m.role !== 'system');
|
|
482
|
+
// 认证头走注册表 (拿不到 → 退回原来的 x-api-key + anthropic-version);
|
|
483
|
+
// `anthropic-dangerous-direct-browser-access` 是本分支历史行为, 无论注册表说什么都保留。
|
|
484
|
+
const regAuthA = await this.registryAuth();
|
|
442
485
|
const response = await fetch(`${this.getBaseUrl()}/messages`, {
|
|
443
486
|
method: 'POST',
|
|
444
487
|
headers: {
|
|
445
488
|
'Content-Type': 'application/json',
|
|
446
|
-
'x-api-key': apiKey,
|
|
447
|
-
'anthropic-version': '2023-06-01',
|
|
489
|
+
...(regAuthA ? regAuthA.headers : { 'x-api-key': apiKey, 'anthropic-version': '2023-06-01' }),
|
|
448
490
|
'anthropic-dangerous-direct-browser-access': 'true'
|
|
449
491
|
},
|
|
450
492
|
body: JSON.stringify({
|
|
@@ -463,10 +505,14 @@ export class PiAIModel {
|
|
|
463
505
|
return { reply: data.content?.[0]?.text || '' };
|
|
464
506
|
}
|
|
465
507
|
async callOllama(messages, temperature, signal) {
|
|
508
|
+
// ollama 协议在注册表里是 `auth.kind='none'` → 内置行为仍是"只带 Content-Type" (一字不变);
|
|
509
|
+
// 自定义的 ollama 协议供应商若声明了鉴权头, 这里就能真的带上。
|
|
510
|
+
const regAuthO = await this.registryAuth();
|
|
466
511
|
const response = await fetch(`${this.getBaseUrl()}/api/chat`, {
|
|
467
512
|
method: 'POST',
|
|
468
513
|
headers: {
|
|
469
|
-
'Content-Type': 'application/json'
|
|
514
|
+
'Content-Type': 'application/json',
|
|
515
|
+
...(regAuthO ? regAuthO.headers : {})
|
|
470
516
|
},
|
|
471
517
|
body: JSON.stringify({
|
|
472
518
|
model: this.mapModel(),
|
|
@@ -487,11 +533,12 @@ export class PiAIModel {
|
|
|
487
533
|
if (!apiKey) {
|
|
488
534
|
throw new Error('OPENROUTER_API_KEY not set');
|
|
489
535
|
}
|
|
536
|
+
const regAuthR = await this.registryAuth();
|
|
490
537
|
const response = await fetch(`${this.getBaseUrl()}/chat/completions`, {
|
|
491
538
|
method: 'POST',
|
|
492
539
|
headers: {
|
|
493
540
|
'Content-Type': 'application/json',
|
|
494
|
-
'Authorization': `Bearer ${apiKey}
|
|
541
|
+
...(regAuthR ? regAuthR.headers : { 'Authorization': `Bearer ${apiKey}` }),
|
|
495
542
|
'HTTP-Referer': 'https://openclaw.ai',
|
|
496
543
|
'X-Title': 'OpenClaw'
|
|
497
544
|
},
|
|
@@ -521,11 +568,22 @@ export class PiAIModel {
|
|
|
521
568
|
parts: [{ text: m.content }]
|
|
522
569
|
}));
|
|
523
570
|
const systemInstruction = messages.find(m => m.role === 'system')?.content;
|
|
524
|
-
|
|
571
|
+
// gemini 的凭据在 **query** (`?key=`) 里 —— 出处就是注册表那一格 (`auth.kind='query-key'`)。
|
|
572
|
+
// 内置 gemini 走注册表得到的仍是 `?key=<原样 key>`, 且**不加任何头** (历史行为一字不变);
|
|
573
|
+
// 只有用户**声明了自定义 authHeader** 的自定义供应商才额外带一个头。
|
|
574
|
+
const regAuthG = await this.registryAuth();
|
|
575
|
+
const keyQuery = regAuthG && typeof regAuthG.query.key === 'string'
|
|
576
|
+
? `?key=${encodeURIComponent(regAuthG.query.key)}`
|
|
577
|
+
: (regAuthG && Object.keys(regAuthG.query).length
|
|
578
|
+
? `?${new URLSearchParams(regAuthG.query).toString()}`
|
|
579
|
+
: `?key=${encodeURIComponent(apiKey)}`);
|
|
580
|
+
const geminiHeaders = { 'Content-Type': 'application/json' };
|
|
581
|
+
if (regAuthG && regAuthG.entryKind === 'custom' && Object.keys(regAuthG.headers).length) {
|
|
582
|
+
Object.assign(geminiHeaders, regAuthG.headers);
|
|
583
|
+
}
|
|
584
|
+
const response = await fetch(`${this.getBaseUrl()}/models/${this.mapModel()}:generateContent${keyQuery}`, {
|
|
525
585
|
method: 'POST',
|
|
526
|
-
headers:
|
|
527
|
-
'Content-Type': 'application/json'
|
|
528
|
-
},
|
|
586
|
+
headers: geminiHeaders,
|
|
529
587
|
body: JSON.stringify({
|
|
530
588
|
contents,
|
|
531
589
|
systemInstruction: systemInstruction ? { parts: [{ text: systemInstruction }] } : undefined,
|
|
@@ -754,6 +812,7 @@ export function initPiAI(config = {}) {
|
|
|
754
812
|
}
|
|
755
813
|
modelInstance = new PiAIModel({
|
|
756
814
|
provider,
|
|
815
|
+
providerId: config.providerId,
|
|
757
816
|
apiKey,
|
|
758
817
|
baseUrl: config.baseUrl,
|
|
759
818
|
model
|