@bolloon/bolloon-agent 0.1.34 → 0.1.36
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/.auto-evolve-calls +1 -0
- package/.last-auto-evolve-baseline +1 -0
- package/.playwright-mcp/page-2026-06-16T07-51-45-706Z.yml +130 -0
- package/.playwright-mcp/page-2026-06-16T07-56-44-116Z.yml +131 -0
- package/Bolloon.md +144 -0
- package/Dive-into/CITATION.cff +17 -0
- package/Dive-into/LICENSE +25 -0
- package/Dive-into/README.md +598 -0
- package/Dive-into/README_zh.md +599 -0
- package/Dive-into/assets/context.png +0 -0
- package/Dive-into/assets/extensibility.png +0 -0
- package/Dive-into/assets/iteration.png +0 -0
- package/Dive-into/assets/layered_architecture.png +0 -0
- package/Dive-into/assets/main_structure.png +0 -0
- package/Dive-into/assets/permission.png +0 -0
- package/Dive-into/assets/session_compact.png +0 -0
- package/Dive-into/assets/subagent.png +0 -0
- package/Dive-into/paper/Dive_into_Claude_Code.pdf +0 -0
- package/README.md +1 -1
- package/dist/agents/p2p-chat-tools.js +6 -6
- package/dist/agents/permission-mode.js +115 -0
- package/dist/agents/pi-sdk.js +687 -25
- package/dist/agents/pre-tool-validator.js +194 -0
- package/dist/agents/workflow-pivot-loop.js +113 -12
- package/dist/bollharness/src/scripts/checks/check_doc_freshness.js +1 -1
- package/dist/bollharness/src/scripts/checks/check_doc_links.js +1 -1
- package/dist/bollharness/src/scripts/context_router.js +1 -1
- package/dist/bollharness/src/scripts/deploy-guard.js +1 -1
- package/dist/bollharness/src/scripts/guard_router.js +1 -1
- package/dist/bollharness/src/scripts/hooks/_hook_output.js +1 -1
- package/dist/bollharness/src/scripts/hooks/risk-tracker.js +1 -1
- package/dist/bollharness-integration/context-router.js +2 -2
- package/dist/bollharness-integration/guard-checker.js +1 -1
- package/dist/bootstrap/bootstrap.js +117 -0
- package/dist/bootstrap/context-collector.js +312 -0
- package/dist/bootstrap/context-hierarchy.js +218 -0
- package/dist/bootstrap/lifecycle-hooks.js +171 -0
- package/dist/bootstrap/project-context.js +158 -0
- package/dist/context-compaction/auto-compact.js +144 -0
- package/dist/context-compaction/budget-gate.js +28 -0
- package/dist/context-compaction/budget-reduce.js +35 -0
- package/dist/context-compaction/context-collapse.js +66 -0
- package/dist/context-compaction/index.js +21 -0
- package/dist/context-compaction/microcompact.js +51 -0
- package/dist/context-compaction/pipeline.js +123 -0
- package/dist/context-compaction/snip.js +45 -0
- package/dist/context-compaction/token-estimator.js +35 -0
- package/dist/context-compaction/types.js +19 -0
- package/dist/heartbeat/HealthMonitor.js +3 -2
- package/dist/index.js +49 -2
- package/dist/llm/llm-judgment-client.js +32 -30
- package/dist/llm/pi-ai.js +125 -28
- package/dist/llm/system-prompt/health.js +129 -0
- package/dist/llm/system-prompt/registry.js +246 -0
- package/dist/llm/system-prompt/strip-hibsml.js +51 -0
- package/dist/llm/tool-manifest/ask_user_input.js +35 -0
- package/dist/llm/tool-manifest/bash.js +23 -0
- package/dist/llm/tool-manifest/create_file.js +24 -0
- package/dist/llm/tool-manifest/fetch_sports_data.js +26 -0
- package/dist/llm/tool-manifest/image_search.js +24 -0
- package/dist/llm/tool-manifest/index.js +69 -0
- package/dist/llm/tool-manifest/mcp.js +43 -0
- package/dist/llm/tool-manifest/message_compose.js +31 -0
- package/dist/llm/tool-manifest/places.js +83 -0
- package/dist/llm/tool-manifest/present_files.js +21 -0
- package/dist/llm/tool-manifest/recipe.js +40 -0
- package/dist/llm/tool-manifest/recommend_apps.js +23 -0
- package/dist/llm/tool-manifest/str_replace.js +27 -0
- package/dist/llm/tool-manifest/types.js +7 -0
- package/dist/llm/tool-manifest/view.js +24 -0
- package/dist/llm/tool-manifest/weather.js +27 -0
- package/dist/llm/tool-manifest/web.js +51 -0
- package/dist/network/p2p-direct.js +23 -0
- package/dist/network/source-intent-broadcaster.js +203 -0
- package/dist/network/source-intent.js +100 -0
- package/dist/pi-ecosystem-judgment/adaptive-scan.js +279 -0
- package/dist/pi-ecosystem-judgment/causal-judge.js +449 -0
- package/dist/pi-ecosystem-judgment/detect-hook.js +168 -0
- package/dist/pi-ecosystem-judgment/distill-prompt.js +226 -0
- package/dist/pi-ecosystem-judgment/evolve-judgment.js +170 -0
- package/dist/pi-ecosystem-judgment/human-value-pipeline.js +21 -0
- package/dist/pi-ecosystem-judgment/human-value-store.js +283 -22
- package/dist/pi-ecosystem-judgment/injection-gate.js +208 -0
- package/dist/pi-ecosystem-judgment/monitor-gate.js +188 -0
- package/dist/pi-ecosystem-judgment/value-injection.js +8 -2
- package/dist/security/builtin-guards.js +124 -0
- package/dist/security/context-router-tool.js +106 -0
- package/dist/security/input-scanner.js +223 -0
- package/dist/security/react-harness.js +143 -0
- package/dist/security/tool-gate.js +235 -0
- package/dist/utils/auto-evolve-policy.js +117 -0
- package/dist/utils/clamp.js +7 -0
- package/dist/utils/double.js +6 -0
- package/dist/web/client.js +3810 -3830
- package/dist/web/components/p2p/P2PModal.js +188 -0
- package/dist/web/components/p2p/index.js +264 -226
- package/dist/web/components/p2p/p2p-modal.js +657 -0
- package/dist/web/components/p2p/p2p-tools.js +248 -0
- package/dist/web/index.html +60 -49
- package/dist/web/server.js +827 -124
- package/dist/web/style.css +531 -249
- package/dist/web/ui/message-renderer.js +463 -0
- package/dist/web/ui/step-timeline.js +375 -0
- package/lefthook.yml +33 -0
- package/package.json +3 -2
- package/scripts/auto-evolve-loop.ts +481 -0
- package/scripts/auto-evolve-oneshot.sh +155 -0
- package/scripts/auto-evolve-snapshot.sh +136 -0
- package/scripts/build-web.ts +35 -1
- package/scripts/detect-schema-changes.sh +48 -0
- package/scripts/diff-reviewer.ts +159 -0
- package/scripts/validate-system-prompt.ts +142 -0
- package/scripts/weekly-report.ts +364 -0
- package/src/agents/p2p-chat-tools.ts +6 -6
- package/src/agents/permission-mode.ts +127 -0
- package/src/agents/pi-sdk.ts +741 -30
- package/src/agents/pre-tool-validator.ts +213 -0
- package/src/agents/workflow-pivot-loop.ts +110 -19
- package/src/bollharness/CLAUDE.md +1 -1
- package/src/bollharness/README.md +2 -2
- package/src/bollharness/README.zh-CN.md +2 -2
- package/src/bollharness/reference/boll-reference/scripts/hooks/find-boll-root.sh +2 -2
- package/src/bollharness/scripts/context-fragments/truth-source-hierarchy.md +2 -2
- package/src/bollharness/scripts/context-fragments/version-sources.md +1 -1
- package/src/bollharness/scripts/hooks/find-project-root.sh +4 -4
- package/src/bollharness/src/scripts/checks/check_doc_freshness.ts +1 -1
- package/src/bollharness/src/scripts/checks/check_doc_links.ts +1 -1
- package/src/bollharness/src/scripts/context_router.ts +1 -1
- package/src/bollharness/src/scripts/deploy-guard.ts +1 -1
- package/src/bollharness/src/scripts/guard_router.ts +1 -1
- package/src/bollharness/src/scripts/hooks/_hook_output.ts +1 -1
- package/src/bollharness/src/scripts/hooks/risk-tracker.ts +1 -1
- package/src/bollharness/templates/scaffold/.gitignore.append +1 -1
- package/src/bollharness/templates/scaffold/CLAUDE.md +2 -2
- package/src/bollharness-integration/context-router.ts +2 -2
- package/src/bollharness-integration/guard-checker.ts +1 -1
- package/src/bootstrap/bootstrap.ts +135 -0
- package/src/bootstrap/context-collector.ts +371 -0
- package/src/bootstrap/context-hierarchy.ts +283 -0
- package/src/bootstrap/lifecycle-hooks.ts +289 -0
- package/src/bootstrap/project-context.ts +171 -0
- package/src/context-compaction/auto-compact.ts +153 -0
- package/src/context-compaction/budget-gate.ts +32 -0
- package/src/context-compaction/budget-reduce.ts +37 -0
- package/src/context-compaction/context-collapse.ts +72 -0
- package/src/context-compaction/index.ts +24 -0
- package/src/context-compaction/microcompact.ts +54 -0
- package/src/context-compaction/pipeline.ts +133 -0
- package/src/context-compaction/snip.ts +51 -0
- package/src/context-compaction/token-estimator.ts +36 -0
- package/src/context-compaction/types.ts +99 -0
- package/src/heartbeat/HealthMonitor.ts +3 -2
- package/src/index.ts +47 -2
- package/src/llm/llm-judgment-client.ts +36 -35
- package/src/llm/pi-ai.ts +135 -29
- package/src/llm/system-prompt/health.ts +159 -0
- package/src/llm/system-prompt/layers/channel/local.md +14 -0
- package/src/llm/system-prompt/layers/channel/p2p-agent.md +18 -0
- package/src/llm/system-prompt/layers/channel/p2p-visitor.md +19 -0
- package/src/llm/system-prompt/layers/core/artifacts_storage.md +89 -0
- package/src/llm/system-prompt/layers/core/evenhandedness.md +21 -0
- package/src/llm/system-prompt/layers/core/hibs_reminders.md +15 -0
- package/src/llm/system-prompt/layers/core/identity.md +37 -0
- package/src/llm/system-prompt/layers/core/knowledge.md +17 -0
- package/src/llm/system-prompt/layers/core/memory_system.md +12 -0
- package/src/llm/system-prompt/layers/core/network_filesystem.md +28 -0
- package/src/llm/system-prompt/layers/core/refusal.md +37 -0
- package/src/llm/system-prompt/layers/core/tone.md +31 -0
- package/src/llm/system-prompt/layers/core/tools.thin.md +13 -0
- package/src/llm/system-prompt/layers/core/wellbeing.md +41 -0
- package/src/llm/system-prompt/layers/role/architect.md +20 -0
- package/src/llm/system-prompt/layers/role/expert.md +19 -0
- package/src/llm/system-prompt/layers/role/implementer.md +15 -0
- package/src/llm/system-prompt/layers/role/security.md +15 -0
- package/src/llm/system-prompt/layers/tool/artifacts.md +72 -0
- package/src/llm/system-prompt/layers/tool/bash.md +25 -0
- package/src/llm/system-prompt/layers/tool/hibs_api.md +171 -0
- package/src/llm/system-prompt/layers/tool/image_search.md +70 -0
- package/src/llm/system-prompt/layers/tool/manifest.md +89 -0
- package/src/llm/system-prompt/layers/tool/mcp_apps.md +53 -0
- package/src/llm/system-prompt/layers/tool/web_search.md +83 -0
- package/src/llm/system-prompt/registry.ts +325 -0
- package/src/llm/system-prompt/strip-hibsml.ts +52 -0
- package/src/llm/tool-manifest/ask_user_input.ts +37 -0
- package/src/llm/tool-manifest/bash.ts +25 -0
- package/src/llm/tool-manifest/create_file.ts +26 -0
- package/src/llm/tool-manifest/fetch_sports_data.ts +28 -0
- package/src/llm/tool-manifest/image_search.ts +26 -0
- package/src/llm/tool-manifest/index.ts +88 -0
- package/src/llm/tool-manifest/mcp.ts +46 -0
- package/src/llm/tool-manifest/message_compose.ts +33 -0
- package/src/llm/tool-manifest/places.ts +86 -0
- package/src/llm/tool-manifest/present_files.ts +23 -0
- package/src/llm/tool-manifest/recipe.ts +42 -0
- package/src/llm/tool-manifest/recommend_apps.ts +25 -0
- package/src/llm/tool-manifest/str_replace.ts +29 -0
- package/src/llm/tool-manifest/types.ts +52 -0
- package/src/llm/tool-manifest/view.ts +26 -0
- package/src/llm/tool-manifest/weather.ts +29 -0
- package/src/llm/tool-manifest/web.ts +54 -0
- package/src/network/p2p-direct.ts +22 -0
- package/src/network/source-intent-broadcaster.ts +242 -0
- package/src/network/source-intent.ts +167 -0
- package/src/security/builtin-guards.ts +162 -0
- package/src/security/context-router-tool.ts +122 -0
- package/src/security/input-scanner.ts +287 -0
- package/src/security/react-harness.ts +177 -0
- package/src/security/tool-gate.ts +294 -0
- package/src/utils/auto-evolve-policy.ts +138 -0
- package/src/utils/clamp.ts +5 -0
- package/src/web/client.js +105 -2187
- package/src/web/client.ts +4326 -0
- package/src/web/index.html +60 -49
- package/src/web/server.ts +894 -148
- package/src/web/style.css +531 -249
- package/src/web/ui/message-renderer.ts +540 -0
- package/src/web/ui/step-timeline.ts +394 -0
- package/staging/auto-evolve/clean-001/.review-verdict +9 -0
- package/staging/auto-evolve/clean-001/clean-001.patch +14 -0
- package/staging/auto-evolve/e2e-001/.patch-id +1 -0
- package/staging/auto-evolve/e2e-001/.review-verdict +12 -0
- package/staging/auto-evolve/e2e-001/e2e-001.patch +11 -0
- package/staging/auto-evolve/test-bad/.review-verdict +12 -0
- package/staging/auto-evolve/test-bad/test-bad.patch +11 -0
- package/test-results/.last-run.json +6 -0
- package/test-results/src-test-web-loop-status-b-5734c-atus-bar-/346/230/276/347/244/272-spinner-/344/270/215/346/230/276/347/244/272/345/276/252/347/216/257/350/256/241/346/225/260/error-context.md +285 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ToolManifest } from './types.js';
|
|
2
|
+
|
|
3
|
+
export const message_compose_v1: ToolManifest = {
|
|
4
|
+
id: 'message_compose_v1',
|
|
5
|
+
name: 'message_compose_v1',
|
|
6
|
+
oneLine: '起草目标导向的消息 (email/textMessage/other).',
|
|
7
|
+
description: '分析情境类型 (工作分歧、谈判、跟进、传达坏消息、请求某事、设定边界、道歉、拒绝、提供反馈、冷启动接触、回应反馈、澄清误解、委派、庆祝) 并识别竞争目标. 多种方法 (高风险/模糊) 生成 2-3 种策略.',
|
|
8
|
+
whenToUse: [
|
|
9
|
+
'用户要你起草一封邮件/消息',
|
|
10
|
+
'高风险沟通 (谈判、道歉、设定边界)',
|
|
11
|
+
'需要适配渠道 (邮件 vs Slack vs 短信)',
|
|
12
|
+
],
|
|
13
|
+
whenNotToUse: [
|
|
14
|
+
'用户只是要写笔记/便签',
|
|
15
|
+
'对话中直接回复',
|
|
16
|
+
],
|
|
17
|
+
parameters: [
|
|
18
|
+
{ name: 'kind', type: 'enum', required: true, description: 'email | textMessage | other', enumValues: ['email', 'textMessage', 'other'] },
|
|
19
|
+
{ name: 'summary_title', type: 'string', required: true, description: '消息的摘要标题' },
|
|
20
|
+
{ name: 'variants', type: 'array', required: true, description: '至少 1 个变体', minItems: 1, items: {
|
|
21
|
+
name: 'variant', type: 'object', required: true, description: '变体', properties: [
|
|
22
|
+
{ name: 'label', type: 'string', required: true, description: '变体标签' },
|
|
23
|
+
{ name: 'body', type: 'string', required: true, description: '消息内容' },
|
|
24
|
+
{ name: 'subject', type: 'string', required: false, description: '邮件主题 (仅 email)' },
|
|
25
|
+
],
|
|
26
|
+
} },
|
|
27
|
+
],
|
|
28
|
+
callExample: `[TOOL:message_compose_v1]
|
|
29
|
+
[P:kind]email
|
|
30
|
+
[P:summary_title]Follow-up on Q3 review
|
|
31
|
+
[P:variants]${'${'}JSON.stringify([{"label":"direct","subject":"Quick follow-up","body":"..."}])[ENDTOOL]`,
|
|
32
|
+
layerId: 'tool.manifest',
|
|
33
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { ToolManifest } from './types.js';
|
|
2
|
+
|
|
3
|
+
export const places_search: ToolManifest = {
|
|
4
|
+
id: 'places_search',
|
|
5
|
+
name: 'places_search',
|
|
6
|
+
oneLine: '使用 Google Places 搜索地点/商户/餐厅/景点 (多查询).',
|
|
7
|
+
description: '单次调用支持多个查询. 多个查询可用于: 高效的行程规划, 拆解广泛或抽象的请求. 包含更广泛的区域以避免同名地点冲突.',
|
|
8
|
+
whenToUse: [
|
|
9
|
+
'用户问某地有什么 (餐厅/景点/酒店)',
|
|
10
|
+
'行程规划 (多地点)',
|
|
11
|
+
'需要 place_id 以便后续在地图展示',
|
|
12
|
+
],
|
|
13
|
+
whenNotToUse: [
|
|
14
|
+
'需要地点坐标 (问 GPS)',
|
|
15
|
+
'只问天气 (用 weather_fetch)',
|
|
16
|
+
],
|
|
17
|
+
parameters: [
|
|
18
|
+
{ name: 'queries', type: 'array', required: true, description: '1-10 个查询', minItems: 1, maxItems: 10, items: {
|
|
19
|
+
name: 'q', type: 'object', required: true, description: '单查询', properties: [
|
|
20
|
+
{ name: 'query', type: 'string', required: true, description: '自然语言搜索' },
|
|
21
|
+
{ name: 'max_results', type: 'integer', required: false, description: '1-10, 默认 5', minimum: 1, maximum: 10, default: 5 }
|
|
22
|
+
],
|
|
23
|
+
} },
|
|
24
|
+
{ name: 'location_bias_lat', type: 'number', required: false, description: '可选纬度' },
|
|
25
|
+
{ name: 'location_bias_lng', type: 'number', required: false, description: '可选经度' },
|
|
26
|
+
{ name: 'location_bias_radius', type: 'number', required: false, description: '米 (默认 5000)', default: 5000 }
|
|
27
|
+
],
|
|
28
|
+
callExample: `[TOOL:places_search]
|
|
29
|
+
[P:queries]${'${'}JSON.stringify([{"query":"ramen restaurants Tokyo"}])[ENDTOOL]`,
|
|
30
|
+
layerId: 'tool.manifest',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const places_map_display_v0: ToolManifest = {
|
|
34
|
+
id: 'places_map_display_v0',
|
|
35
|
+
name: 'places_map_display_v0',
|
|
36
|
+
oneLine: '在地图上展示地点, 附上你的推荐和内行小贴士.',
|
|
37
|
+
description: '工作流: 先用 places_search 获取 place_id, 然后用 place_id 引用调用本工具. 两种模式: 简单标记 (locations) 或行程 (days).',
|
|
38
|
+
whenToUse: [
|
|
39
|
+
'用户需要看地点在地图上',
|
|
40
|
+
'行程规划, 需要可视化',
|
|
41
|
+
],
|
|
42
|
+
whenNotToUse: [
|
|
43
|
+
'只问地点信息 (用 places_search 文字回答)',
|
|
44
|
+
],
|
|
45
|
+
parameters: [
|
|
46
|
+
{ name: 'locations', type: 'array', required: false, description: '简单标记模式', minItems: 1, maxItems: 50, items: {
|
|
47
|
+
name: 'loc', type: 'object', required: true, description: '地点', properties: [
|
|
48
|
+
{ name: 'name', type: 'string', required: true, description: '地点名' },
|
|
49
|
+
{ name: 'latitude', type: 'number', required: true, description: '纬度' },
|
|
50
|
+
{ name: 'longitude', type: 'number', required: true, description: '经度' },
|
|
51
|
+
{ name: 'place_id', type: 'string', required: false, description: '从 places_search 复制' },
|
|
52
|
+
{ name: 'notes', type: 'string', required: false, description: '你的小贴士' },
|
|
53
|
+
{ name: 'address', type: 'string', required: false, description: '自定义地点的地址 (没有 place_id 时用)' },
|
|
54
|
+
{ name: 'arrival_time', type: 'string', required: false, description: '到达时间 (用于行程, e.g. "8:00 AM")' },
|
|
55
|
+
{ name: 'duration_minutes', type: 'integer', required: false, description: '停留时长 (分钟)' },
|
|
56
|
+
],
|
|
57
|
+
} },
|
|
58
|
+
{ name: 'days', type: 'array', required: false, description: '行程模式', minItems: 1, maxItems: 30, items: {
|
|
59
|
+
name: 'day', type: 'object', required: true, description: '单日', properties: [
|
|
60
|
+
{ name: 'day_number', type: 'integer', required: true, description: '天数 (从 1 开始)', minimum: 1 },
|
|
61
|
+
{ name: 'title', type: 'string', required: false, description: '日期标题' },
|
|
62
|
+
{ name: 'narrative', type: 'string', required: false, description: '该日叙述' },
|
|
63
|
+
{ name: 'locations', type: 'array', required: true, description: '该日地点', minItems: 1, maxItems: 50, items: {
|
|
64
|
+
name: 'loc', type: 'object', required: true, description: '地点', properties: [
|
|
65
|
+
{ name: 'name', type: 'string', required: true, description: '地点名' },
|
|
66
|
+
{ name: 'latitude', type: 'number', required: true, description: '纬度' },
|
|
67
|
+
{ name: 'longitude', type: 'number', required: true, description: '经度' },
|
|
68
|
+
{ name: 'place_id', type: 'string', required: false, description: '从 places_search 复制' },
|
|
69
|
+
{ name: 'notes', type: 'string', required: false, description: '你的小贴士' },
|
|
70
|
+
{ name: 'address', type: 'string', required: false, description: '自定义地点地址' },
|
|
71
|
+
{ name: 'arrival_time', type: 'string', required: false, description: '到达时间' },
|
|
72
|
+
{ name: 'duration_minutes', type: 'integer', required: false, description: '停留时长 (分钟)' },
|
|
73
|
+
],
|
|
74
|
+
} },
|
|
75
|
+
],
|
|
76
|
+
} },
|
|
77
|
+
{ name: 'mode', type: 'enum', required: false, description: 'markers | itinerary', enumValues: ['markers', 'itinerary'] },
|
|
78
|
+
{ name: 'travel_mode', type: 'enum', required: false, description: 'driving | walking | transit | bicycling', enumValues: ['driving', 'walking', 'transit', 'bicycling'] },
|
|
79
|
+
{ name: 'show_route', type: 'boolean', required: false, description: '是否显示路线' },
|
|
80
|
+
{ name: 'title', type: 'string', required: false, description: '行程标题' },
|
|
81
|
+
{ name: 'narrative', type: 'string', required: false, description: '行程叙述' },
|
|
82
|
+
],
|
|
83
|
+
callExample: `[TOOL:places_map_display_v0]
|
|
84
|
+
[P:locations]${'${'}JSON.stringify([{"name":"Senso-ji","latitude":35.7148,"longitude":139.7967,"place_id":"ChIJ..."}])[ENDTOOL]`,
|
|
85
|
+
layerId: 'tool.manifest',
|
|
86
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ToolManifest } from './types.js';
|
|
2
|
+
|
|
3
|
+
export const present_files: ToolManifest = {
|
|
4
|
+
id: 'present_files',
|
|
5
|
+
name: 'present_files',
|
|
6
|
+
oneLine: '让文件对用户可见, 客户端界面中查看和渲染.',
|
|
7
|
+
description: '接收来自容器文件系统的文件路径数组, 返回客户端可访问文件的输出路径. 输出路径按与输入路径相同的顺序返回. 多个文件可在单次调用中高效呈现. 如果文件不在输出目录中, 会自动复制到该目录.',
|
|
8
|
+
whenToUse: [
|
|
9
|
+
'让用户可以查看、下载或与文件交互',
|
|
10
|
+
'一次展示多个相关文件',
|
|
11
|
+
'创建了应向用户展示的文件之后',
|
|
12
|
+
],
|
|
13
|
+
whenNotToUse: [
|
|
14
|
+
'只是为了自己的处理而需要读取文件内容',
|
|
15
|
+
'临时或中间文件',
|
|
16
|
+
],
|
|
17
|
+
parameters: [
|
|
18
|
+
{ name: 'filepaths', type: 'array', required: true, description: '至少 1 个文件路径', minItems: 1, items: { name: 'path', type: 'string', required: true, description: '容器内路径' } },
|
|
19
|
+
],
|
|
20
|
+
callExample: `[TOOL:present_files]
|
|
21
|
+
[P:filepaths]${'${'}JSON.stringify(["/home/bolloon/report.md"])[ENDTOOL]`,
|
|
22
|
+
layerId: 'tool.manifest',
|
|
23
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ToolManifest } from './types.js';
|
|
2
|
+
|
|
3
|
+
export const recipe_display_v0: ToolManifest = {
|
|
4
|
+
id: 'recipe_display_v0',
|
|
5
|
+
name: 'recipe_display_v0',
|
|
6
|
+
oneLine: '显示带可调整份量的交互式食谱.',
|
|
7
|
+
description: '用户要求食谱、烹饪说明或食物准备指南时使用. 该组件允许用户通过调整份量控件按比例缩放所有食材的用量.',
|
|
8
|
+
whenToUse: [
|
|
9
|
+
'用户问食谱',
|
|
10
|
+
'需要比例缩放 (份量调整)',
|
|
11
|
+
],
|
|
12
|
+
whenNotToUse: [
|
|
13
|
+
'用户只要食材列表 (用文字)',
|
|
14
|
+
'用户问餐厅推荐 (用 places_search)',
|
|
15
|
+
],
|
|
16
|
+
parameters: [
|
|
17
|
+
{ name: 'title', type: 'string', required: true, description: '食谱名称' },
|
|
18
|
+
{ name: 'base_servings', type: 'integer', required: false, description: '基础份数 (默认 4)' },
|
|
19
|
+
{ name: 'description', type: 'string', required: false, description: '简短描述' },
|
|
20
|
+
{ name: 'ingredients', type: 'array', required: true, description: '食材', items: {
|
|
21
|
+
name: 'ing', type: 'object', required: true, description: '食材', properties: [
|
|
22
|
+
{ name: 'id', type: 'string', required: true, description: '唯一 ID' },
|
|
23
|
+
{ name: 'amount', type: 'number', required: true, description: '数量', minimum: 0 },
|
|
24
|
+
{ name: 'unit', type: 'enum', required: false, description: 'g/kg/ml/l/tsp/tbsp/cup/fl_oz/oz/lb/pinch', enumValues: ['g','kg','ml','l','tsp','tbsp','cup','fl_oz','oz','lb','pinch'] },
|
|
25
|
+
{ name: 'name', type: 'string', required: true, description: '显示名 (整体可数项, 把 counting noun 放在这里)' },
|
|
26
|
+
],
|
|
27
|
+
} },
|
|
28
|
+
{ name: 'steps', type: 'array', required: true, description: '步骤', items: {
|
|
29
|
+
name: 's', type: 'object', required: true, description: '步骤', properties: [
|
|
30
|
+
{ name: 'id', type: 'string', required: true, description: '唯一 ID' },
|
|
31
|
+
{ name: 'title', type: 'string', required: true, description: '步骤摘要' },
|
|
32
|
+
{ name: 'content', type: 'string', required: true, description: '完整指令 (用 {id} 引用食材)' },
|
|
33
|
+
{ name: 'timer_seconds', type: 'integer', required: false, description: '等待/烹饪计时秒数', minimum: 0 }
|
|
34
|
+
],
|
|
35
|
+
} },
|
|
36
|
+
{ name: 'notes', type: 'string', required: false, description: '附加说明' },
|
|
37
|
+
],
|
|
38
|
+
callExample: `[TOOL:recipe_display_v0]
|
|
39
|
+
[P:title]Pasta
|
|
40
|
+
[P:ingredients]${'${'}JSON.stringify([{"id":"a1","amount":500,"name":"pasta"}])[ENDTOOL]`,
|
|
41
|
+
layerId: 'tool.manifest',
|
|
42
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ToolManifest } from './types.js';
|
|
2
|
+
|
|
3
|
+
export const recommend_bolloon_apps: ToolManifest = {
|
|
4
|
+
id: 'recommend_bolloon_apps',
|
|
5
|
+
name: 'recommend_bolloon_apps',
|
|
6
|
+
oneLine: '推荐 1-3 个 Bolloon 应用或扩展.',
|
|
7
|
+
description: '当用户正在处理的事情可能更适合用 Bolloon 聊天以外的应用来完成时, 展示此建议. 仅推荐与用户当前用例相关的应用, 并按相关性排序.',
|
|
8
|
+
whenToUse: [
|
|
9
|
+
'编码任务 (Bolloon Code)',
|
|
10
|
+
'知识工作 (Cowork)',
|
|
11
|
+
'处理电子表格 (Excel) 或幻灯片 (PowerPoint)',
|
|
12
|
+
'浏览器自动化 (Chrome)',
|
|
13
|
+
],
|
|
14
|
+
whenNotToUse: [
|
|
15
|
+
'用户已明确不想离开对话',
|
|
16
|
+
'没有相关应用',
|
|
17
|
+
],
|
|
18
|
+
parameters: [
|
|
19
|
+
{ name: 'app_ids', type: 'array', required: true, description: '应用 ID 数组', items: {
|
|
20
|
+
name: 'id', type: 'string', required: true, description: '应用 ID (如 desktop/ios/android/code_terminal/code_vscode/code_jetbrains/code_slack/excel/powerpoint/chrome)',
|
|
21
|
+
} },
|
|
22
|
+
],
|
|
23
|
+
callExample: '[TOOL:recommend_bolloon_apps] [P:app_ids] ["code_vscode","excel"] [ENDTOOL]',
|
|
24
|
+
layerId: 'tool.manifest',
|
|
25
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ToolManifest } from './types.js';
|
|
2
|
+
|
|
3
|
+
export const str_replace: ToolManifest = {
|
|
4
|
+
id: 'str_replace',
|
|
5
|
+
name: 'str_replace',
|
|
6
|
+
oneLine: '将文件中的唯一字符串替换为另一个.',
|
|
7
|
+
description: 'old_str 必须与原始文件内容完全匹配且只出现一次. 从 view 输出复制时, 不要包含行号前缀(空格 + 行号 + 制表符). 在编辑前立即查看文件; 任何成功的 str_replace 之后, 该文件之前的 view 输出已失效 — 在对同一文件进行进一步编辑之前请重新查看. /mnt/* 路径只读, 需先复制到可写位置.',
|
|
8
|
+
whenToUse: [
|
|
9
|
+
'编辑已有文件的小改动',
|
|
10
|
+
'精确替换单段文本',
|
|
11
|
+
],
|
|
12
|
+
whenNotToUse: [
|
|
13
|
+
'创建新文件 (用 create_file)',
|
|
14
|
+
'完全重写文件 (用 create_file + 删除)',
|
|
15
|
+
],
|
|
16
|
+
parameters: [
|
|
17
|
+
{ name: 'description', type: 'string', required: true, description: '为什么我要做这个编辑' },
|
|
18
|
+
{ name: 'old_str', type: 'string', required: true, description: '要被替换的字符串 (必须唯一)' },
|
|
19
|
+
{ name: 'new_str', type: 'string', required: true, description: '新字符串 (空字符串 = 删除)', default: '' },
|
|
20
|
+
{ name: 'path', type: 'string', required: true, description: '文件路径' },
|
|
21
|
+
],
|
|
22
|
+
callExample: `[TOOL:str_replace]
|
|
23
|
+
[P:description]修复 typo
|
|
24
|
+
[P:old_str]recieve
|
|
25
|
+
[P:new_str]receive
|
|
26
|
+
[P:path]/home/bolloon/main.py
|
|
27
|
+
[ENDTOOL]`,
|
|
28
|
+
layerId: 'tool.manifest',
|
|
29
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tool-manifest/types.ts — 工具清单的类型
|
|
3
|
+
*
|
|
4
|
+
* 设计原则: schema 在代码侧(结构化数据), description/when-to-use 在代码侧,
|
|
5
|
+
* prompt 里只嵌"调用格式 + 名字 + 一句话描述" — 节省 LLM 注意力.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface ToolParameter {
|
|
9
|
+
name: string;
|
|
10
|
+
type: 'string' | 'integer' | 'number' | 'boolean' | 'array' | 'object' | 'enum';
|
|
11
|
+
required: boolean;
|
|
12
|
+
description: string;
|
|
13
|
+
/** 枚举值 (type='enum' 时) */
|
|
14
|
+
enumValues?: string[];
|
|
15
|
+
/** 默认值 (LLM 不传时用) */
|
|
16
|
+
default?: string | number | boolean;
|
|
17
|
+
/** 嵌套对象的字段 (type='object' 时) */
|
|
18
|
+
properties?: ToolParameter[];
|
|
19
|
+
/** 数组元素 (type='array' 时) */
|
|
20
|
+
items?: ToolParameter;
|
|
21
|
+
/** 数组最小项数 (type='array' 时) */
|
|
22
|
+
minItems?: number;
|
|
23
|
+
/** 数组最大项数 (type='array' 时) */
|
|
24
|
+
maxItems?: number;
|
|
25
|
+
/** 数字最小值 (type='integer'/'number' 时) */
|
|
26
|
+
minimum?: number;
|
|
27
|
+
/** 数字最大值 (type='integer'/'number' 时) */
|
|
28
|
+
maximum?: number;
|
|
29
|
+
/** 字符串格式约束 (e.g. 'uri', 'date-time') */
|
|
30
|
+
format?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface ToolManifest {
|
|
34
|
+
/** 工具 ID, 跟 prompt 里调用的 {name} 一致 */
|
|
35
|
+
id: string;
|
|
36
|
+
/** 显示名 */
|
|
37
|
+
name: string;
|
|
38
|
+
/** 一句话描述 (进 prompt) */
|
|
39
|
+
oneLine: string;
|
|
40
|
+
/** 详细描述 (代码侧, 不进 prompt) */
|
|
41
|
+
description: string;
|
|
42
|
+
/** 何时使用 (进 prompt) */
|
|
43
|
+
whenToUse: string[];
|
|
44
|
+
/** 何时不使用 (进 prompt) */
|
|
45
|
+
whenNotToUse: string[];
|
|
46
|
+
/** 输入参数 schema (代码侧, 不进 prompt) */
|
|
47
|
+
parameters: ToolParameter[];
|
|
48
|
+
/** 一个调用示例 (进 prompt, 1-3 行) */
|
|
49
|
+
callExample: string;
|
|
50
|
+
/** 在 system-prompt 里对应的 layer ID (可选) */
|
|
51
|
+
layerId?: string;
|
|
52
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ToolManifest } from './types.js';
|
|
2
|
+
|
|
3
|
+
export const view: ToolManifest = {
|
|
4
|
+
id: 'view',
|
|
5
|
+
name: 'view',
|
|
6
|
+
oneLine: '查看文本、图像和目录列表.',
|
|
7
|
+
description: '支持的路径类型: 目录 (列出文件和目录, 最多 2 层深度, 忽略隐藏项和 node_modules); 图像文件 (.jpg, .jpeg, .png, .gif, .webp) 以可视方式显示; 文本文件显示带行号的内容 (前缀仅用于显示 — 不要在 str_replace 的 old_str 中包含它). 可以指定 view_range 来查看特定行.',
|
|
8
|
+
whenToUse: [
|
|
9
|
+
'读取已有文件的内容',
|
|
10
|
+
'看图像文件',
|
|
11
|
+
'列目录',
|
|
12
|
+
],
|
|
13
|
+
whenNotToUse: [
|
|
14
|
+
'创建新文件 (用 create_file)',
|
|
15
|
+
],
|
|
16
|
+
parameters: [
|
|
17
|
+
{ name: 'description', type: 'string', required: true, description: '为什么我要查看' },
|
|
18
|
+
{ name: 'path', type: 'string', required: true, description: '绝对路径' },
|
|
19
|
+
{ name: 'view_range', type: 'array', required: false, description: '[start, end] 1-indexed, end=-1 表示到末尾', minItems: 2, maxItems: 2, items: { name: 'r', type: 'integer', required: true, description: '行号' } }
|
|
20
|
+
],
|
|
21
|
+
callExample: `[TOOL:view]
|
|
22
|
+
[P:description]读 README
|
|
23
|
+
[P:path]/home/bolloon/README.md
|
|
24
|
+
[ENDTOOL]`,
|
|
25
|
+
layerId: 'tool.manifest',
|
|
26
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ToolManifest } from './types.js';
|
|
2
|
+
|
|
3
|
+
export const weather_fetch: ToolManifest = {
|
|
4
|
+
id: 'weather_fetch',
|
|
5
|
+
name: 'weather_fetch',
|
|
6
|
+
oneLine: '显示天气信息 (用用户家庭位置确定温度单位).',
|
|
7
|
+
description: '使用用户的家庭位置来确定温度单位: 美国用户使用华氏度, 其他用户使用摄氏度.',
|
|
8
|
+
whenToUse: [
|
|
9
|
+
'用户询问特定地点的天气',
|
|
10
|
+
'用户询问"我该带雨伞/外套吗"',
|
|
11
|
+
'用户在规划户外活动',
|
|
12
|
+
'用户询问"[城市]怎么样"(天气语境)',
|
|
13
|
+
],
|
|
14
|
+
whenNotToUse: [
|
|
15
|
+
'气候或历史天气问题',
|
|
16
|
+
'闲聊天气但未指定地点',
|
|
17
|
+
],
|
|
18
|
+
parameters: [
|
|
19
|
+
{ name: 'location_name', type: 'string', required: true, description: '人类可读地点名' },
|
|
20
|
+
{ name: 'latitude', type: 'number', required: true, description: '纬度' },
|
|
21
|
+
{ name: 'longitude', type: 'number', required: true, description: '经度' },
|
|
22
|
+
],
|
|
23
|
+
callExample: `[TOOL:weather_fetch]
|
|
24
|
+
[P:location_name]San Francisco, CA
|
|
25
|
+
[P:latitude]37.78
|
|
26
|
+
[P:longitude]-122.41
|
|
27
|
+
[ENDTOOL]`,
|
|
28
|
+
layerId: 'tool.manifest',
|
|
29
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { ToolManifest } from './types.js';
|
|
2
|
+
|
|
3
|
+
export const web_search: ToolManifest = {
|
|
4
|
+
id: 'web_search',
|
|
5
|
+
name: 'web_search',
|
|
6
|
+
oneLine: '搜索 Web (返回前 10 条结果).',
|
|
7
|
+
description: '当需要当前信息或信息可能自知识截止以来已发生变化时使用. 1-6 词查询最佳. 默认改写; 引用应是个罕见的例外.',
|
|
8
|
+
whenToUse: [
|
|
9
|
+
'当前状态 (谁担任某职位、什么政策生效)',
|
|
10
|
+
'时效性信息 (股价、新闻)',
|
|
11
|
+
'不识别的实体 (默认搜索)',
|
|
12
|
+
],
|
|
13
|
+
whenNotToUse: [
|
|
14
|
+
'永恒信息/成熟技术事实 (直接答)',
|
|
15
|
+
'已故人物 (不会变)',
|
|
16
|
+
],
|
|
17
|
+
parameters: [
|
|
18
|
+
{ name: 'query', type: 'string', required: true, description: '搜索查询 (1-6 词最佳)' },
|
|
19
|
+
],
|
|
20
|
+
callExample: `[TOOL:web_search]
|
|
21
|
+
[P:query]S&P 500 current price
|
|
22
|
+
[ENDTOOL]`,
|
|
23
|
+
layerId: 'tool.web_search',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const web_fetch: ToolManifest = {
|
|
27
|
+
id: 'web_fetch',
|
|
28
|
+
name: 'web_fetch',
|
|
29
|
+
oneLine: '获取指定 URL 网页的内容.',
|
|
30
|
+
description: '此函数只能获取用户直接提供的或由 web_search 和 web_fetch 工具的结果中返回的 EXACT URL. 此工具无法访问需要身份验证的内容, 例如私有 Google Docs 或登录墙后的页面. URL 必须包含协议.',
|
|
31
|
+
whenToUse: [
|
|
32
|
+
'web_search 摘要不够, 需要读完整文章',
|
|
33
|
+
'用户提供 URL 让你读',
|
|
34
|
+
],
|
|
35
|
+
whenNotToUse: [
|
|
36
|
+
'需要身份验证的页面',
|
|
37
|
+
'web_search 已经足够时',
|
|
38
|
+
],
|
|
39
|
+
parameters: [
|
|
40
|
+
{ name: 'url', type: 'string', required: true, description: '完整 URL (含协议, https://...)', format: 'uri' },
|
|
41
|
+
{ name: 'allowed_domains', type: 'array', required: false, description: '仅允许的域名白名单 (如 ["example.com","*.github.com"])', items: { name: 'd', type: 'string', required: true, description: '域名' } },
|
|
42
|
+
{ name: 'blocked_domains', type: 'array', required: false, description: '黑名单域名', items: { name: 'd', type: 'string', required: true, description: '域名' } },
|
|
43
|
+
{ name: 'html_extraction_method', type: 'string', required: false, description: 'HTML 提取方法 (e.g. "text"/"markdown")' },
|
|
44
|
+
{ name: 'is_zdr', type: 'boolean', required: false, description: '是否 Zero Data Retention 请求 (true 时不记录 URL)' },
|
|
45
|
+
{ name: 'text_content_token_limit', type: 'integer', required: false, description: 'token 限制', minimum: 0 },
|
|
46
|
+
{ name: 'web_fetch_pdf_extract_text', type: 'boolean', required: false, description: '是否提取 PDF 文本' },
|
|
47
|
+
{ name: 'web_fetch_rate_limit_key', type: 'string', required: false, description: '速率限制键' },
|
|
48
|
+
{ name: 'web_fetch_rate_limit_dark_launch', type: 'boolean', required: false, description: '速率限制暗启动模式' },
|
|
49
|
+
],
|
|
50
|
+
callExample: `[TOOL:web_fetch]
|
|
51
|
+
[P:url]https://example.com/article
|
|
52
|
+
[ENDTOOL]`,
|
|
53
|
+
layerId: 'tool.manifest',
|
|
54
|
+
};
|
|
@@ -94,6 +94,28 @@ export class P2PDirect extends EventEmitter {
|
|
|
94
94
|
conn.on('data', (chunk: Buffer | Uint8Array) => {
|
|
95
95
|
const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
96
96
|
console.log(`[P2PDirect:${this.name}] 收到数据 from ${remotePubKeyHex.substring(0,12)}... (${buf.length} bytes)`);
|
|
97
|
+
// P-Action 3: untrusted-input scanner (默认 silence-on-fail + log-only)
|
|
98
|
+
// 包装层 跨机器 @-mention 代发 (已 WORKING) 不能 block-on-suspicion
|
|
99
|
+
try {
|
|
100
|
+
// 动态 import 避免循环依赖 + 启动时加载
|
|
101
|
+
// (lazy require to keep cold-start fast)
|
|
102
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
103
|
+
const { scanInput, writeScanAudit, shouldHardBlock } = require('../security/input-scanner.js') as typeof import('../security/input-scanner.js');
|
|
104
|
+
const result = scanInput(buf, { source: 'p2p' });
|
|
105
|
+
if (shouldHardBlock(result)) {
|
|
106
|
+
console.warn(`[P2PDirect:${this.name}] 阻断恶意消息 from ${remotePubKeyHex.substring(0,12)}... (verdict=${result.verdict}, threats=${result.threats.length})`);
|
|
107
|
+
writeScanAudit(result, { fromPublicKey: remotePubKeyHex, blocked: true }).catch(() => { /* silent */ });
|
|
108
|
+
return; // 不 emit('data'), 跨机中转不传播
|
|
109
|
+
}
|
|
110
|
+
if (result.verdict !== 'pass') {
|
|
111
|
+
// log-only: 仍然 emit('data'), 但写 audit 留痕
|
|
112
|
+
writeScanAudit(result, { fromPublicKey: remotePubKeyHex, blocked: false }).catch(() => { /* silent */ });
|
|
113
|
+
console.log(`[P2PDirect:${this.name}] 输入扫描 verdict=${result.verdict} (${result.threats.length} threats) from ${remotePubKeyHex.substring(0,12)}... (audit-only)`);
|
|
114
|
+
}
|
|
115
|
+
} catch (err) {
|
|
116
|
+
// scanner 自身挂掉 → 静默, 不阻断
|
|
117
|
+
console.warn(`[P2PDirect:${this.name}] input scanner failed (silent, fail-safe):`, err);
|
|
118
|
+
}
|
|
97
119
|
this.emit('data', {
|
|
98
120
|
data: buf,
|
|
99
121
|
fromPublicKey: remotePubKeyHex,
|