@bolloon/bolloon-agent 0.4.33 → 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.
Files changed (214) hide show
  1. package/dist/agents/contacts/chain.js +27 -7
  2. package/dist/agents/execution-supervisor.js +580 -40
  3. package/dist/agents/external-events.js +35 -6
  4. package/dist/agents/gateway-group.js +100 -12
  5. package/dist/agents/goal-criteria.js +10 -3
  6. package/dist/agents/goal-flywheel/block-executor.js +346 -0
  7. package/dist/agents/goal-flywheel/continuation-decision.js +592 -0
  8. package/dist/agents/goal-flywheel/goal-change.js +754 -0
  9. package/dist/agents/goal-flywheel/index.js +26 -0
  10. package/dist/agents/goal-flywheel/memory-layers.js +227 -0
  11. package/dist/agents/goal-flywheel/run-closure.js +809 -0
  12. package/dist/agents/goal-flywheel/skill-candidate.js +628 -0
  13. package/dist/agents/goal-flywheel/types.js +329 -0
  14. package/dist/agents/goal-flywheel/wiring/change.js +288 -0
  15. package/dist/agents/goal-flywheel/wiring/closure.js +697 -0
  16. package/dist/agents/goal-flywheel/wiring/continuation.js +432 -0
  17. package/dist/agents/goal-flywheel/wiring/contract.js +270 -0
  18. package/dist/agents/goal-flywheel/wiring/index.js +26 -0
  19. package/dist/agents/goal-flywheel/wiring/monitor.js +254 -0
  20. package/dist/agents/goal-flywheel/wiring/seams.js +592 -0
  21. package/dist/agents/goal-flywheel/work-contract.js +478 -0
  22. package/dist/agents/goal-flywheel/work-monitor.js +488 -0
  23. package/dist/agents/goal-flywheel-wiring.js +1870 -0
  24. package/dist/agents/goal-state-reducer.js +406 -0
  25. package/dist/agents/goal-store.js +35 -1
  26. package/dist/agents/mobile-flywheel-view.js +144 -0
  27. package/dist/agents/mobile-task-actions-verify.js +74 -0
  28. package/dist/agents/mobile-task-actions.js +178 -0
  29. package/dist/agents/mobile-task-views.js +199 -0
  30. package/dist/agents/model-policy.js +651 -0
  31. package/dist/agents/network-pulse.js +304 -18
  32. package/dist/agents/pi-sdk-tools.js +84 -33
  33. package/dist/agents/pi-sdk.js +157 -42
  34. package/dist/agents/run-store.js +71 -5
  35. package/dist/agents/skill-readiness.js +52 -10
  36. package/dist/agents/subagent-manager.js +209 -3
  37. package/dist/agents/task/task-runner.js +17 -4
  38. package/dist/agents/task-group.js +8 -51
  39. package/dist/agents/task-public-text.js +89 -0
  40. package/dist/agents/workflow-pivot-loop.js +19 -12
  41. package/dist/cli/clipboard.js +65 -0
  42. package/dist/cli/commands/index.js +1 -0
  43. package/dist/cli/commands/tasks.js +350 -2
  44. package/dist/cli/identity-command.js +177 -0
  45. package/dist/cli/ink-app.js +145 -17
  46. package/dist/cli/log-gate.js +386 -0
  47. package/dist/cli/mention-data.js +2 -0
  48. package/dist/cli/model-selector.js +538 -0
  49. package/dist/cli/reply-hygiene.js +54 -0
  50. package/dist/cli/setup-wizard.js +757 -69
  51. package/dist/cli/startup-notice.js +160 -0
  52. package/dist/cli/stores.js +22 -1
  53. package/dist/cli/theme.js +49 -0
  54. package/dist/cli/tui-select.js +970 -0
  55. package/dist/cli/update-commands.js +150 -24
  56. package/dist/cli-entry.js +137 -20
  57. package/dist/electron-build/agents/contacts/chain.js +26 -6
  58. package/dist/electron-build/agents/contacts/chain.js.map +1 -1
  59. package/dist/electron-build/agents/execution-supervisor.js +578 -38
  60. package/dist/electron-build/agents/execution-supervisor.js.map +1 -1
  61. package/dist/electron-build/agents/external-events.js +34 -5
  62. package/dist/electron-build/agents/external-events.js.map +1 -1
  63. package/dist/electron-build/agents/goal-criteria.js +10 -3
  64. package/dist/electron-build/agents/goal-criteria.js.map +1 -1
  65. package/dist/electron-build/agents/goal-flywheel/continuation-decision.js +598 -0
  66. package/dist/electron-build/agents/goal-flywheel/continuation-decision.js.map +1 -0
  67. package/dist/electron-build/agents/goal-flywheel/goal-change.js +773 -0
  68. package/dist/electron-build/agents/goal-flywheel/goal-change.js.map +1 -0
  69. package/dist/electron-build/agents/goal-flywheel/memory-layers.js +269 -0
  70. package/dist/electron-build/agents/goal-flywheel/memory-layers.js.map +1 -0
  71. package/dist/electron-build/agents/goal-flywheel/run-closure.js +818 -0
  72. package/dist/electron-build/agents/goal-flywheel/run-closure.js.map +1 -0
  73. package/dist/electron-build/agents/goal-flywheel/skill-candidate.js +642 -0
  74. package/dist/electron-build/agents/goal-flywheel/skill-candidate.js.map +1 -0
  75. package/dist/electron-build/agents/goal-flywheel/types.js +333 -0
  76. package/dist/electron-build/agents/goal-flywheel/types.js.map +1 -0
  77. package/dist/electron-build/agents/goal-flywheel/wiring/change.js +294 -0
  78. package/dist/electron-build/agents/goal-flywheel/wiring/change.js.map +1 -0
  79. package/dist/electron-build/agents/goal-flywheel/wiring/closure.js +742 -0
  80. package/dist/electron-build/agents/goal-flywheel/wiring/closure.js.map +1 -0
  81. package/dist/electron-build/agents/goal-flywheel/wiring/continuation.js +444 -0
  82. package/dist/electron-build/agents/goal-flywheel/wiring/continuation.js.map +1 -0
  83. package/dist/electron-build/agents/goal-flywheel/wiring/contract.js +279 -0
  84. package/dist/electron-build/agents/goal-flywheel/wiring/contract.js.map +1 -0
  85. package/dist/electron-build/agents/goal-flywheel/wiring/index.js +111 -0
  86. package/dist/electron-build/agents/goal-flywheel/wiring/index.js.map +1 -0
  87. package/dist/electron-build/agents/goal-flywheel/wiring/monitor.js +264 -0
  88. package/dist/electron-build/agents/goal-flywheel/wiring/monitor.js.map +1 -0
  89. package/dist/electron-build/agents/goal-flywheel/wiring/seams.js +612 -0
  90. package/dist/electron-build/agents/goal-flywheel/wiring/seams.js.map +1 -0
  91. package/dist/electron-build/agents/goal-flywheel/work-contract.js +488 -0
  92. package/dist/electron-build/agents/goal-flywheel/work-contract.js.map +1 -0
  93. package/dist/electron-build/agents/goal-flywheel/work-monitor.js +501 -0
  94. package/dist/electron-build/agents/goal-flywheel/work-monitor.js.map +1 -0
  95. package/dist/electron-build/agents/goal-flywheel-wiring.js +1962 -0
  96. package/dist/electron-build/agents/goal-flywheel-wiring.js.map +1 -0
  97. package/dist/electron-build/agents/goal-state-reducer.js +414 -0
  98. package/dist/electron-build/agents/goal-state-reducer.js.map +1 -0
  99. package/dist/electron-build/agents/goal-store.js +35 -1
  100. package/dist/electron-build/agents/goal-store.js.map +1 -1
  101. package/dist/electron-build/agents/model-policy.js +706 -0
  102. package/dist/electron-build/agents/model-policy.js.map +1 -0
  103. package/dist/electron-build/agents/network-pulse.js +307 -19
  104. package/dist/electron-build/agents/network-pulse.js.map +1 -1
  105. package/dist/electron-build/agents/pi-sdk-tools.js +84 -33
  106. package/dist/electron-build/agents/pi-sdk-tools.js.map +1 -1
  107. package/dist/electron-build/agents/pi-sdk-types.js.map +1 -1
  108. package/dist/electron-build/agents/pi-sdk.js +156 -41
  109. package/dist/electron-build/agents/pi-sdk.js.map +1 -1
  110. package/dist/electron-build/agents/run-store.js +75 -6
  111. package/dist/electron-build/agents/run-store.js.map +1 -1
  112. package/dist/electron-build/agents/skill-readiness.js +52 -9
  113. package/dist/electron-build/agents/skill-readiness.js.map +1 -1
  114. package/dist/electron-build/agents/task/task-runner.js +16 -3
  115. package/dist/electron-build/agents/task/task-runner.js.map +1 -1
  116. package/dist/electron-build/agents/workflow-pivot-loop.js +19 -12
  117. package/dist/electron-build/agents/workflow-pivot-loop.js.map +1 -1
  118. package/dist/electron-build/llm/config-store.js +146 -6
  119. package/dist/electron-build/llm/config-store.js.map +1 -1
  120. package/dist/electron-build/llm/connection-probe.js +764 -0
  121. package/dist/electron-build/llm/connection-probe.js.map +1 -0
  122. package/dist/electron-build/llm/custom-provider-store.js +272 -0
  123. package/dist/electron-build/llm/custom-provider-store.js.map +1 -0
  124. package/dist/electron-build/llm/data/provider-catalog-baked.js +23 -0
  125. package/dist/electron-build/llm/data/provider-catalog-baked.js.map +1 -0
  126. package/dist/electron-build/llm/model-catalog.js +778 -0
  127. package/dist/electron-build/llm/model-catalog.js.map +1 -0
  128. package/dist/electron-build/llm/model-discovery.js +1202 -0
  129. package/dist/electron-build/llm/model-discovery.js.map +1 -0
  130. package/dist/electron-build/llm/model-selection.js +1315 -0
  131. package/dist/electron-build/llm/model-selection.js.map +1 -0
  132. package/dist/electron-build/llm/pi-ai.js +70 -11
  133. package/dist/electron-build/llm/pi-ai.js.map +1 -1
  134. package/dist/electron-build/llm/provider-catalog.js +969 -0
  135. package/dist/electron-build/llm/provider-catalog.js.map +1 -0
  136. package/dist/electron-build/llm/provider-registry.js +950 -0
  137. package/dist/electron-build/llm/provider-registry.js.map +1 -0
  138. package/dist/electron-build/llm/tool-name.js +266 -0
  139. package/dist/electron-build/llm/tool-name.js.map +1 -0
  140. package/dist/electron-build/orbitdb/cid-database.js +83 -17
  141. package/dist/electron-build/orbitdb/cid-database.js.map +1 -1
  142. package/dist/electron-build/orbitdb/ipfs-node.js +31 -2
  143. package/dist/electron-build/orbitdb/ipfs-node.js.map +1 -1
  144. package/dist/electron-build/utils/dual-source-facts.js +236 -0
  145. package/dist/electron-build/utils/dual-source-facts.js.map +1 -0
  146. package/dist/electron-build/utils/dual-source.js +347 -0
  147. package/dist/electron-build/utils/dual-source.js.map +1 -0
  148. package/dist/electron-build/utils/update-manager.js +328 -104
  149. package/dist/electron-build/utils/update-manager.js.map +1 -1
  150. package/dist/electron-build/utils/update-state.js +9 -11
  151. package/dist/electron-build/utils/update-state.js.map +1 -1
  152. package/dist/electron-build/utils/version-identity.js +193 -0
  153. package/dist/electron-build/utils/version-identity.js.map +1 -0
  154. package/dist/electron-build/utils/version-info.js +57 -31
  155. package/dist/electron-build/utils/version-info.js.map +1 -1
  156. package/dist/index.js +385 -108
  157. package/dist/ios/bolloon-web.json +10 -0
  158. package/dist/ios/chain-explorer.js +617 -0
  159. package/dist/ios/explorer.html +163 -0
  160. package/dist/ios/index.html +96 -0
  161. package/dist/ios/mobile-agent.js +2 -2
  162. package/dist/ios/mobile-contacts.js +362 -0
  163. package/dist/ios/mobile-core.js +3102 -310
  164. package/dist/ios/mobile-privacy.js +185 -0
  165. package/dist/ios/mobile-tasks.js +339 -0
  166. package/dist/ios/mobile-update.js +1442 -0
  167. package/dist/ios/mobile.css +19 -0
  168. package/dist/ios/mobile.html +96 -0
  169. package/dist/ios/mobile.js +1013 -41
  170. package/dist/ios/routes-chain-index.js +108 -0
  171. package/dist/ios/routes-contacts.js +420 -0
  172. package/dist/ios/routes-llm-config.js +344 -52
  173. package/dist/ios/routes-mobile-tasks.js +353 -0
  174. package/dist/ios/routes-onchain-trade.js +99 -0
  175. package/dist/ios/routes-x402-info.js +1 -0
  176. package/dist/ios/server.js +921 -0
  177. package/dist/ios/sw.js +1 -1
  178. package/dist/ios/task-frame-server.js +211 -0
  179. package/dist/llm/config-store.js +146 -6
  180. package/dist/llm/connection-probe.js +744 -0
  181. package/dist/llm/custom-provider-store.js +224 -0
  182. package/dist/llm/data/provider-catalog-baked.js +19 -0
  183. package/dist/llm/model-catalog.js +717 -0
  184. package/dist/llm/model-discovery.js +1137 -0
  185. package/dist/llm/model-selection.js +1241 -0
  186. package/dist/llm/pi-ai.js +70 -11
  187. package/dist/llm/provider-catalog.js +898 -0
  188. package/dist/llm/provider-registry.js +917 -0
  189. package/dist/llm/tool-name.js +220 -0
  190. package/dist/orbitdb/cid-database.js +81 -16
  191. package/dist/orbitdb/ipfs-node.js +31 -2
  192. package/dist/setup/onboard.js +34 -8
  193. package/dist/utils/dual-source-facts.js +223 -0
  194. package/dist/utils/dual-source.js +297 -0
  195. package/dist/utils/update-cli.js +16 -21
  196. package/dist/utils/update-health.js +35 -5
  197. package/dist/utils/update-manager.js +325 -96
  198. package/dist/utils/update-state.js +13 -10
  199. package/dist/utils/version-identity.js +176 -0
  200. package/dist/utils/version-info.js +27 -22
  201. package/dist/web/bolloon-web.json +10 -0
  202. package/dist/web/mobile-contacts.js +44 -11
  203. package/dist/web/mobile-core.js +2901 -580
  204. package/dist/web/mobile-tasks.js +339 -0
  205. package/dist/web/mobile-update.js +1442 -0
  206. package/dist/web/mobile.css +19 -0
  207. package/dist/web/mobile.html +64 -0
  208. package/dist/web/mobile.js +838 -35
  209. package/dist/web/routes-llm-config.js +344 -52
  210. package/dist/web/routes-mobile-tasks.js +353 -0
  211. package/dist/web/server.js +163 -4
  212. package/dist/web/sw.js +1 -1
  213. package/package.json +3 -1
  214. 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
- openaiTools = tools;
211
- const toolDescriptions = tools.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');
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
- 'Authorization': `Bearer ${apiKey}`
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
- const response = await fetch(`${this.getBaseUrl()}/models/${this.mapModel()}:generateContent?key=${apiKey}`, {
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