@bolloon/bolloon-agent 0.4.13 → 0.4.15
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 +127 -127
- package/bin/bolloon-cli.cjs +183 -183
- package/bin/bolloon-daemon.sh +207 -0
- package/bin/bolloon.cjs +0 -0
- package/dist/agents/agent-gateway.js +130 -0
- package/dist/agents/constraint-layer.js +19 -19
- package/dist/agents/gateway-group.js +261 -0
- package/dist/agents/gateway-network.js +278 -0
- package/dist/agents/judgment-protocol.js +14 -14
- package/dist/agents/pi-sdk-tools.js +117 -0
- package/dist/agents/pi-sdk-types.js +12 -12
- package/dist/agents/pi-sdk.js +101 -101
- package/dist/agents/skill-organizer.js +19 -19
- package/dist/agents/workflow-pivot-loop.js +2 -2
- package/dist/agents/x402/x402Pay.js +4 -0
- package/dist/bollharness/src/scripts/deploy-guard.js +8 -8
- package/dist/bollharness-integration/context-router-judgment.js +4 -4
- package/dist/bollharness-integration/context-router.js +292 -292
- package/dist/bollharness-integration/gate-state-machine.js +13 -13
- package/dist/bollharness-integration/llm-judgment-engine.js +134 -134
- package/dist/bollharness-integration/skill-adapter.js +21 -21
- package/dist/bootstrap/chat-archiver.js +14 -14
- package/dist/bootstrap/context-os.js +24 -24
- package/dist/bootstrap/memory-compressor.js +13 -13
- package/dist/cli-entry.js +36 -36
- package/dist/constraint-runtime/reference_data/archive_surface_snapshot.json +63 -0
- package/dist/constraint-runtime/reference_data/commands_snapshot.json +1037 -0
- package/dist/constraint-runtime/reference_data/subsystems/assistant.json +8 -0
- package/dist/constraint-runtime/reference_data/subsystems/bootstrap.json +8 -0
- package/dist/constraint-runtime/reference_data/subsystems/bridge.json +32 -0
- package/dist/constraint-runtime/reference_data/subsystems/buddy.json +13 -0
- package/dist/constraint-runtime/reference_data/subsystems/cli.json +26 -0
- package/dist/constraint-runtime/reference_data/subsystems/components.json +32 -0
- package/dist/constraint-runtime/reference_data/subsystems/constants.json +28 -0
- package/dist/constraint-runtime/reference_data/subsystems/coordinator.json +8 -0
- package/dist/constraint-runtime/reference_data/subsystems/entrypoints.json +15 -0
- package/dist/constraint-runtime/reference_data/subsystems/hooks.json +32 -0
- package/dist/constraint-runtime/reference_data/subsystems/keybindings.json +21 -0
- package/dist/constraint-runtime/reference_data/subsystems/memdir.json +15 -0
- package/dist/constraint-runtime/reference_data/subsystems/migrations.json +18 -0
- package/dist/constraint-runtime/reference_data/subsystems/moreright.json +8 -0
- package/dist/constraint-runtime/reference_data/subsystems/native_ts.json +11 -0
- package/dist/constraint-runtime/reference_data/subsystems/outputStyles.json +8 -0
- package/dist/constraint-runtime/reference_data/subsystems/plugins.json +9 -0
- package/dist/constraint-runtime/reference_data/subsystems/remote.json +11 -0
- package/dist/constraint-runtime/reference_data/subsystems/schemas.json +8 -0
- package/dist/constraint-runtime/reference_data/subsystems/screens.json +10 -0
- package/dist/constraint-runtime/reference_data/subsystems/server.json +10 -0
- package/dist/constraint-runtime/reference_data/subsystems/services.json +32 -0
- package/dist/constraint-runtime/reference_data/subsystems/skills.json +27 -0
- package/dist/constraint-runtime/reference_data/subsystems/state.json +13 -0
- package/dist/constraint-runtime/reference_data/subsystems/types.json +18 -0
- package/dist/constraint-runtime/reference_data/subsystems/upstreamproxy.json +9 -0
- package/dist/constraint-runtime/reference_data/subsystems/utils.json +32 -0
- package/dist/constraint-runtime/reference_data/subsystems/vim.json +12 -0
- package/dist/constraint-runtime/reference_data/subsystems/voice.json +8 -0
- package/dist/constraint-runtime/reference_data/tools_snapshot.json +922 -0
- package/dist/constraint-runtime/tools/PolymarketSDK/econ-integration.d.ts +55 -0
- package/dist/constraint-runtime/tools/PolymarketSDK/econ-integration.js +59 -0
- package/dist/context-compaction/auto-compact.js +7 -7
- package/dist/electron/config.js.map +1 -0
- package/dist/electron/dialogs.js.map +1 -0
- package/dist/electron/first-run.js +54 -54
- package/dist/electron/first-run.js.map +1 -0
- package/dist/electron/ipc.js.map +1 -0
- package/dist/electron/logger.js.map +1 -0
- package/dist/electron/main.js.map +1 -0
- package/dist/electron/menu.js.map +1 -0
- package/dist/electron/paths.js.map +1 -0
- package/dist/electron/server.js.map +1 -0
- package/dist/electron/tray.js.map +1 -0
- package/dist/electron/window.js.map +1 -0
- package/dist/electron-build/electron/first-run.js +54 -54
- package/dist/electron-preload.js.map +1 -1
- package/dist/electron.js.map +1 -1
- package/dist/index.js +112 -112
- package/dist/llm/llm-judgment-client.js +102 -102
- package/dist/llm/pi-ai.js +48 -48
- package/dist/llm/system-prompt/layers/channel/human-async.md +41 -41
- package/dist/llm/system-prompt/layers/channel/local.md +14 -14
- package/dist/llm/system-prompt/layers/channel/p2p-agent.md +18 -18
- package/dist/llm/system-prompt/layers/channel/p2p-peer-sync.md +51 -51
- package/dist/llm/system-prompt/layers/channel/p2p-proactive.md +43 -43
- package/dist/llm/system-prompt/layers/channel/p2p-visitor.md +19 -19
- package/dist/llm/system-prompt/layers/channel/session-handoff.md +61 -61
- package/dist/llm/system-prompt/layers/core/artifacts_storage.md +89 -89
- package/dist/llm/system-prompt/layers/core/evenhandedness.md +21 -21
- package/dist/llm/system-prompt/layers/core/external-engagement.md +73 -73
- package/dist/llm/system-prompt/layers/core/hibs_reminders.md +15 -15
- package/dist/llm/system-prompt/layers/core/identity.md +48 -48
- package/dist/llm/system-prompt/layers/core/knowledge.md +17 -17
- package/dist/llm/system-prompt/layers/core/memory_system.md +12 -12
- package/dist/llm/system-prompt/layers/core/network_filesystem.md +28 -28
- package/dist/llm/system-prompt/layers/core/refusal.md +37 -37
- package/dist/llm/system-prompt/layers/core/tone.md +31 -31
- package/dist/llm/system-prompt/layers/core/tools.thin.md +13 -13
- package/dist/llm/system-prompt/layers/core/wellbeing.md +41 -41
- package/dist/llm/system-prompt/layers/role/architect.md +20 -20
- package/dist/llm/system-prompt/layers/role/expert.md +19 -19
- package/dist/llm/system-prompt/layers/role/implementer.md +15 -15
- package/dist/llm/system-prompt/layers/role/security.md +15 -15
- package/dist/llm/system-prompt/layers/tool/artifacts.md +72 -72
- package/dist/llm/system-prompt/layers/tool/bash.md +25 -25
- package/dist/llm/system-prompt/layers/tool/goal_handoff.md +77 -77
- package/dist/llm/system-prompt/layers/tool/hibs_api.md +171 -171
- package/dist/llm/system-prompt/layers/tool/image_search.md +70 -70
- package/dist/llm/system-prompt/layers/tool/manifest.md +89 -89
- package/dist/llm/system-prompt/layers/tool/mcp_apps.md +53 -53
- package/dist/llm/system-prompt/layers/tool/p2p_request.md +61 -61
- package/dist/llm/system-prompt/layers/tool/web_search.md +83 -83
- package/dist/llm/tool-manifest/ask_user_input.js +1 -1
- package/dist/llm/tool-manifest/bash.js +3 -3
- package/dist/llm/tool-manifest/create_file.js +4 -4
- package/dist/llm/tool-manifest/fetch_sports_data.js +3 -3
- package/dist/llm/tool-manifest/image_search.js +2 -2
- package/dist/llm/tool-manifest/index.js +59 -0
- package/dist/llm/tool-manifest/mcp.js +2 -2
- package/dist/llm/tool-manifest/message_compose.js +3 -3
- package/dist/llm/tool-manifest/places.js +2 -2
- package/dist/llm/tool-manifest/present_files.js +1 -1
- package/dist/llm/tool-manifest/recipe.js +2 -2
- package/dist/llm/tool-manifest/str_replace.js +5 -5
- package/dist/llm/tool-manifest/view.js +3 -3
- package/dist/llm/tool-manifest/weather.js +4 -4
- package/dist/llm/tool-manifest/web.js +4 -4
- package/dist/network/p2p.js +78 -4
- package/dist/orbitdb/cid-database.js +39 -10
- package/dist/pi-ecosystem-judgment/causal-judge.js +51 -51
- package/dist/pi-ecosystem-judgment/distill-prompt.js +42 -42
- package/dist/pi-ecosystem-judgment/distillation.js +14 -14
- package/dist/pi-ecosystem-judgment/index.js +1 -1
- package/dist/pi-ecosystem-judgment/monitor-gate.js +28 -28
- package/dist/pi-ecosystem-judgment/value-injection.js +102 -102
- package/dist/security/context-router-tool.js +15 -15
- package/dist/utils/auto-update.js.map +1 -0
- package/dist/web/a2ui-client.js +1594 -223
- package/dist/web/api-config.html +779 -779
- package/dist/web/client-hearth.js +10 -10
- package/dist/web/client.js +273 -0
- package/dist/web/client.js.map +7 -0
- package/dist/web/components/wallet-viem.mjs +118 -118
- package/dist/web/index.html +502 -485
- package/dist/web/manifest.json +20 -20
- package/dist/web/mobile-agent.js +397 -0
- package/dist/web/mobile-core.js +86235 -0
- package/dist/web/mobile-data.js +346 -0
- package/dist/web/mobile-http-api.js +71 -0
- package/dist/web/mobile-p2p.js +250 -0
- package/dist/web/mobile-payments.js +80 -0
- package/dist/web/mobile-wallet.js +226 -0
- package/dist/web/mobile.css +483 -6
- package/dist/web/mobile.html +99 -50
- package/dist/web/mobile.js +1040 -187
- package/dist/web/server.js +196 -13
- package/dist/web/style.css +5062 -4946
- package/package.json +201 -198
- package/scripts/build-cli.js +215 -215
- package/scripts/build-web.ts +162 -149
- package/scripts/postinstall.js +152 -152
- package/bin/bolloon.js +0 -157
- package/dist/agents/python-exec.js +0 -115
- package/dist/pi-ecosystem-colony/index.js +0 -365
- package/dist/social/ant-colony/AdaptiveHeartbeat.js +0 -101
- package/dist/social/ant-colony/PheromoneEngine.js +0 -227
- package/dist/social/ant-colony/index.js +0 -6
- package/dist/social/ant-colony/types.js +0 -24
- package/dist/storage/trajectory.js +0 -101
- package/dist/test/ai-judgment-test.js +0 -80
- package/dist/test/bollharness-integration.test.js +0 -318
- package/dist/test/channel-agent-multi-dialogue.js +0 -205
- package/dist/test/channel-heartbeat-agent-test.js +0 -201
- package/dist/test/constraint-layer.test.js +0 -164
- package/dist/test/diap-identity-test.js +0 -172
- package/dist/test/diap-quick-test.js +0 -62
- package/dist/test/global-shared-context.test.js +0 -315
- package/dist/test/harness-judgment-injection.test.js +0 -246
- package/dist/test/harness-workflow-integrator-test.js +0 -228
- package/dist/test/human-value-store.test.js +0 -243
- package/dist/test/hybrid-integration-test.js +0 -118
- package/dist/test/hybrid-messenger-verify.js +0 -55
- package/dist/test/iroh-bistream-debug.js +0 -38
- package/dist/test/iroh-communication.test.js +0 -66
- package/dist/test/iroh-debug-test.js +0 -57
- package/dist/test/iroh-diap-test.js +0 -71
- package/dist/test/iroh-direct-connect.js +0 -55
- package/dist/test/iroh-e2e-fixed.js +0 -89
- package/dist/test/iroh-e2e-same-process.js +0 -63
- package/dist/test/iroh-e2e.js +0 -66
- package/dist/test/iroh-final-e2e.js +0 -72
- package/dist/test/iroh-relay-test.js +0 -37
- package/dist/test/iroh-simple-test.js +0 -41
- package/dist/test/iroh-transport-verify.js +0 -54
- package/dist/test/iroh-transport.test.js +0 -37
- package/dist/test/iroh-two-nodes.js +0 -70
- package/dist/test/iroh-verify.js +0 -44
- package/dist/test/judgment-decision.test.js +0 -219
- package/dist/test/llm-judgment-integration.test.js +0 -220
- package/dist/test/p2p-agent-complex-dialogue.js +0 -385
- package/dist/test/p2p-agent-dialogue.js +0 -341
- package/dist/test/p2p-agent-full-bidirectional.js +0 -510
- package/dist/test/p2p-agent-harness-flow.js +0 -437
- package/dist/test/p2p-agent-harness-single.js +0 -143
- package/dist/test/p2p-ai-dialogue-test.js +0 -318
- package/dist/test/p2p-cid-connect-test.js +0 -195
- package/dist/test/p2p-connect-receiver.js +0 -69
- package/dist/test/p2p-doc-transfer.js +0 -110
- package/dist/test/p2p-identity-page-test.js +0 -77
- package/dist/test/p2p-iroh-test.js +0 -171
- package/dist/test/p2p-minimal-test.js +0 -241
- package/dist/test/p2p-node-1.js +0 -148
- package/dist/test/p2p-node-2.js +0 -148
- package/dist/test/p2p-server.js +0 -281
- package/dist/test/p2p-two-nodes-test.js +0 -438
- package/dist/test/pi-sdk.test.js +0 -44
- package/dist/test/set-persona.js +0 -40
- package/dist/test/simple.test.js +0 -9
- package/dist/test/storage-integration.test.js +0 -150
- package/dist/test/subagent-manager.test.js +0 -276
- package/dist/test/test-gate-flow.test.js +0 -81
- package/dist/test/workflow-engine.test.js +0 -87
- package/dist/test/workflow-pivot-loop.test.js +0 -246
|
@@ -48,6 +48,65 @@ export function getToolsByLayer(layerId) {
|
|
|
48
48
|
*
|
|
49
49
|
* 不包含: 完整 parameters schema (那是 PiAI 客户端在调用时读)
|
|
50
50
|
*/
|
|
51
|
+
/**
|
|
52
|
+
* 把 ToolManifest 转成 OpenAI function calling 格式 (tools 数组)
|
|
53
|
+
* 用于 native tool_choice: "auto" 模式, 让 LLM 选择调用.
|
|
54
|
+
*
|
|
55
|
+
* 注意: 递归处理嵌套参数 (type='object' 的 properties / type='array' 的 items)
|
|
56
|
+
*/
|
|
57
|
+
export function formatForOpenAI(tools) {
|
|
58
|
+
const list = tools ?? ALL;
|
|
59
|
+
return list.map((t) => {
|
|
60
|
+
const properties = {};
|
|
61
|
+
const required = [];
|
|
62
|
+
for (const p of t.parameters) {
|
|
63
|
+
properties[p.name] = convertParameter(p);
|
|
64
|
+
if (p.required)
|
|
65
|
+
required.push(p.name);
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
type: 'function',
|
|
69
|
+
function: {
|
|
70
|
+
name: t.id,
|
|
71
|
+
description: t.oneLine,
|
|
72
|
+
parameters: {
|
|
73
|
+
type: 'object',
|
|
74
|
+
properties,
|
|
75
|
+
required,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
function convertParameter(p) {
|
|
82
|
+
const schema = { type: p.type === 'enum' ? 'string' : p.type };
|
|
83
|
+
if (p.description)
|
|
84
|
+
schema.description = p.description;
|
|
85
|
+
if (p.enumValues)
|
|
86
|
+
schema.enum = p.enumValues;
|
|
87
|
+
if (p.default !== undefined)
|
|
88
|
+
schema.default = p.default;
|
|
89
|
+
if (p.minimum !== undefined)
|
|
90
|
+
schema.minimum = p.minimum;
|
|
91
|
+
if (p.maximum !== undefined)
|
|
92
|
+
schema.maximum = p.maximum;
|
|
93
|
+
if (p.format)
|
|
94
|
+
schema.format = p.format;
|
|
95
|
+
if (p.type === 'object' && p.properties) {
|
|
96
|
+
schema.properties = {};
|
|
97
|
+
for (const sub of p.properties) {
|
|
98
|
+
schema.properties[sub.name] = convertParameter(sub);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (p.type === 'array' && p.items) {
|
|
102
|
+
schema.items = convertParameter(p.items);
|
|
103
|
+
if (p.minItems !== undefined)
|
|
104
|
+
schema.minItems = p.minItems;
|
|
105
|
+
if (p.maxItems !== undefined)
|
|
106
|
+
schema.maxItems = p.maxItems;
|
|
107
|
+
}
|
|
108
|
+
return schema;
|
|
109
|
+
}
|
|
51
110
|
export function formatForPrompt(tools) {
|
|
52
111
|
const list = tools ?? ALL;
|
|
53
112
|
const lines = [
|
|
@@ -15,7 +15,7 @@ export const search_mcp_registry = {
|
|
|
15
15
|
parameters: [
|
|
16
16
|
{ name: 'keywords', type: 'array', required: true, description: '搜索关键词', minItems: 1, items: { name: 'kw', type: 'string', required: true, description: '关键词' } }
|
|
17
17
|
],
|
|
18
|
-
callExample: `[TOOL:search_mcp_registry]
|
|
18
|
+
callExample: `[TOOL:search_mcp_registry]
|
|
19
19
|
[P:keywords]${'${'}JSON.stringify(["calendar","schedule"])[ENDTOOL]`,
|
|
20
20
|
layerId: 'tool.mcp_apps',
|
|
21
21
|
};
|
|
@@ -37,7 +37,7 @@ export const suggest_connectors = {
|
|
|
37
37
|
parameters: [
|
|
38
38
|
{ name: 'uuids', type: 'array', required: true, description: '从 search_mcp_registry 结果的 directoryUuid 复制', minItems: 1, items: { name: 'u', type: 'string', required: true, description: 'uuid' } }
|
|
39
39
|
],
|
|
40
|
-
callExample: `[TOOL:suggest_connectors]
|
|
40
|
+
callExample: `[TOOL:suggest_connectors]
|
|
41
41
|
[P:uuids]${'${'}JSON.stringify(["uuid-from-search-result"])[ENDTOOL]`,
|
|
42
42
|
layerId: 'tool.mcp_apps',
|
|
43
43
|
};
|
|
@@ -23,9 +23,9 @@ export const message_compose_v1 = {
|
|
|
23
23
|
],
|
|
24
24
|
} },
|
|
25
25
|
],
|
|
26
|
-
callExample: `[TOOL:message_compose_v1]
|
|
27
|
-
[P:kind]email
|
|
28
|
-
[P:summary_title]Follow-up on Q3 review
|
|
26
|
+
callExample: `[TOOL:message_compose_v1]
|
|
27
|
+
[P:kind]email
|
|
28
|
+
[P:summary_title]Follow-up on Q3 review
|
|
29
29
|
[P:variants]${'${'}JSON.stringify([{"label":"direct","subject":"Quick follow-up","body":"..."}])[ENDTOOL]`,
|
|
30
30
|
layerId: 'tool.manifest',
|
|
31
31
|
};
|
|
@@ -23,7 +23,7 @@ export const places_search = {
|
|
|
23
23
|
{ name: 'location_bias_lng', type: 'number', required: false, description: '可选经度' },
|
|
24
24
|
{ name: 'location_bias_radius', type: 'number', required: false, description: '米 (默认 5000)', default: 5000 }
|
|
25
25
|
],
|
|
26
|
-
callExample: `[TOOL:places_search]
|
|
26
|
+
callExample: `[TOOL:places_search]
|
|
27
27
|
[P:queries]${'${'}JSON.stringify([{"query":"ramen restaurants Tokyo"}])[ENDTOOL]`,
|
|
28
28
|
layerId: 'tool.manifest',
|
|
29
29
|
};
|
|
@@ -77,7 +77,7 @@ export const places_map_display_v0 = {
|
|
|
77
77
|
{ name: 'title', type: 'string', required: false, description: '行程标题' },
|
|
78
78
|
{ name: 'narrative', type: 'string', required: false, description: '行程叙述' },
|
|
79
79
|
],
|
|
80
|
-
callExample: `[TOOL:places_map_display_v0]
|
|
80
|
+
callExample: `[TOOL:places_map_display_v0]
|
|
81
81
|
[P:locations]${'${'}JSON.stringify([{"name":"Senso-ji","latitude":35.7148,"longitude":139.7967,"place_id":"ChIJ..."}])[ENDTOOL]`,
|
|
82
82
|
layerId: 'tool.manifest',
|
|
83
83
|
};
|
|
@@ -15,7 +15,7 @@ export const present_files = {
|
|
|
15
15
|
parameters: [
|
|
16
16
|
{ name: 'filepaths', type: 'array', required: true, description: '至少 1 个文件路径', minItems: 1, items: { name: 'path', type: 'string', required: true, description: '容器内路径' } },
|
|
17
17
|
],
|
|
18
|
-
callExample: `[TOOL:present_files]
|
|
18
|
+
callExample: `[TOOL:present_files]
|
|
19
19
|
[P:filepaths]${'${'}JSON.stringify(["/home/bolloon/report.md"])[ENDTOOL]`,
|
|
20
20
|
layerId: 'tool.manifest',
|
|
21
21
|
};
|
|
@@ -33,8 +33,8 @@ export const recipe_display_v0 = {
|
|
|
33
33
|
} },
|
|
34
34
|
{ name: 'notes', type: 'string', required: false, description: '附加说明' },
|
|
35
35
|
],
|
|
36
|
-
callExample: `[TOOL:recipe_display_v0]
|
|
37
|
-
[P:title]Pasta
|
|
36
|
+
callExample: `[TOOL:recipe_display_v0]
|
|
37
|
+
[P:title]Pasta
|
|
38
38
|
[P:ingredients]${'${'}JSON.stringify([{"id":"a1","amount":500,"name":"pasta"}])[ENDTOOL]`,
|
|
39
39
|
layerId: 'tool.manifest',
|
|
40
40
|
};
|
|
@@ -17,11 +17,11 @@ export const str_replace = {
|
|
|
17
17
|
{ name: 'new_str', type: 'string', required: true, description: '新字符串 (空字符串 = 删除)', default: '' },
|
|
18
18
|
{ name: 'path', type: 'string', required: true, description: '文件路径' },
|
|
19
19
|
],
|
|
20
|
-
callExample: `[TOOL:str_replace]
|
|
21
|
-
[P:description]修复 typo
|
|
22
|
-
[P:old_str]recieve
|
|
23
|
-
[P:new_str]receive
|
|
24
|
-
[P:path]/home/bolloon/main.py
|
|
20
|
+
callExample: `[TOOL:str_replace]
|
|
21
|
+
[P:description]修复 typo
|
|
22
|
+
[P:old_str]recieve
|
|
23
|
+
[P:new_str]receive
|
|
24
|
+
[P:path]/home/bolloon/main.py
|
|
25
25
|
[ENDTOOL]`,
|
|
26
26
|
layerId: 'tool.manifest',
|
|
27
27
|
};
|
|
@@ -16,9 +16,9 @@ export const view = {
|
|
|
16
16
|
{ name: 'path', type: 'string', required: true, description: '绝对路径' },
|
|
17
17
|
{ 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: '行号' } }
|
|
18
18
|
],
|
|
19
|
-
callExample: `[TOOL:view]
|
|
20
|
-
[P:description]读 README
|
|
21
|
-
[P:path]/home/bolloon/README.md
|
|
19
|
+
callExample: `[TOOL:view]
|
|
20
|
+
[P:description]读 README
|
|
21
|
+
[P:path]/home/bolloon/README.md
|
|
22
22
|
[ENDTOOL]`,
|
|
23
23
|
layerId: 'tool.manifest',
|
|
24
24
|
};
|
|
@@ -18,10 +18,10 @@ export const weather_fetch = {
|
|
|
18
18
|
{ name: 'latitude', type: 'number', required: true, description: '纬度' },
|
|
19
19
|
{ name: 'longitude', type: 'number', required: true, description: '经度' },
|
|
20
20
|
],
|
|
21
|
-
callExample: `[TOOL:weather_fetch]
|
|
22
|
-
[P:location_name]San Francisco, CA
|
|
23
|
-
[P:latitude]37.78
|
|
24
|
-
[P:longitude]-122.41
|
|
21
|
+
callExample: `[TOOL:weather_fetch]
|
|
22
|
+
[P:location_name]San Francisco, CA
|
|
23
|
+
[P:latitude]37.78
|
|
24
|
+
[P:longitude]-122.41
|
|
25
25
|
[ENDTOOL]`,
|
|
26
26
|
layerId: 'tool.manifest',
|
|
27
27
|
};
|
|
@@ -15,8 +15,8 @@ export const web_search = {
|
|
|
15
15
|
parameters: [
|
|
16
16
|
{ name: 'query', type: 'string', required: true, description: '搜索查询 (1-6 词最佳)' },
|
|
17
17
|
],
|
|
18
|
-
callExample: `[TOOL:web_search]
|
|
19
|
-
[P:query]S&P 500 current price
|
|
18
|
+
callExample: `[TOOL:web_search]
|
|
19
|
+
[P:query]S&P 500 current price
|
|
20
20
|
[ENDTOOL]`,
|
|
21
21
|
layerId: 'tool.web_search',
|
|
22
22
|
};
|
|
@@ -44,8 +44,8 @@ export const web_fetch = {
|
|
|
44
44
|
{ name: 'web_fetch_rate_limit_key', type: 'string', required: false, description: '速率限制键' },
|
|
45
45
|
{ name: 'web_fetch_rate_limit_dark_launch', type: 'boolean', required: false, description: '速率限制暗启动模式' },
|
|
46
46
|
],
|
|
47
|
-
callExample: `[TOOL:web_fetch]
|
|
48
|
-
[P:url]https://example.com/article
|
|
47
|
+
callExample: `[TOOL:web_fetch]
|
|
48
|
+
[P:url]https://example.com/article
|
|
49
49
|
[ENDTOOL]`,
|
|
50
50
|
layerId: 'tool.manifest',
|
|
51
51
|
};
|
package/dist/network/p2p.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createLibp2p } from 'libp2p';
|
|
2
2
|
import { tcp } from '@libp2p/tcp';
|
|
3
|
+
import { webSockets } from '@libp2p/websockets';
|
|
3
4
|
import { multiaddr as createMultiaddr } from '@multiformats/multiaddr';
|
|
4
5
|
import { circuitRelayTransport } from '@libp2p/circuit-relay-v2';
|
|
5
6
|
import { autoNAT } from '@libp2p/autonat';
|
|
@@ -101,9 +102,18 @@ export class P2PNetwork {
|
|
|
101
102
|
// 新增: 消息存储层
|
|
102
103
|
messageStore = null;
|
|
103
104
|
offlineDeliveryInterval = null;
|
|
105
|
+
// 2026-08-15: 手机 data.* 同步提供者 (如 LLM 配置)。由上层 (server/测试) 注入, 网络层不 import config-store.
|
|
106
|
+
dataProviders = new Map();
|
|
104
107
|
constructor() {
|
|
105
108
|
this.peerStorePath = PEER_STORE_PATH;
|
|
106
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* 注册 data.* 协议提供者 (手机同步请求 → 返回 payload 字符串, null = 不响应)。
|
|
112
|
+
* 例: registerDataProvider('data.llm-config', async () => JSON.stringify(llmConfig))
|
|
113
|
+
*/
|
|
114
|
+
registerDataProvider(type, fn) {
|
|
115
|
+
this.dataProviders.set(type, fn);
|
|
116
|
+
}
|
|
107
117
|
async enablePersistence() {
|
|
108
118
|
try {
|
|
109
119
|
const { JsonMessageStore } = await import('./storage/adapters/json-adapter.js');
|
|
@@ -151,7 +161,8 @@ export class P2PNetwork {
|
|
|
151
161
|
? new TextEncoder().encode(`${type}:${payload}`)
|
|
152
162
|
: payload;
|
|
153
163
|
const ma = createMultiaddr(`/p2p/${peerId}`);
|
|
154
|
-
|
|
164
|
+
// libp2p 3.x: dialProtocol 返回 Stream 本体 (非 {stream})
|
|
165
|
+
const stream = await this.node.dialProtocol(ma, '/agent/message');
|
|
155
166
|
stream.send(data);
|
|
156
167
|
return true;
|
|
157
168
|
}
|
|
@@ -165,7 +176,39 @@ export class P2PNetwork {
|
|
|
165
176
|
const enableAutoNat = config?.enableAutoNat ?? true;
|
|
166
177
|
const enableUPnP = config?.enableUPnP ?? true;
|
|
167
178
|
const transports = [tcp()];
|
|
179
|
+
// 2026-08-15: 加 websockets 传输 — 让手机端 (WebView) 能通过 wss/ws 连桌面节点
|
|
180
|
+
try {
|
|
181
|
+
transports.push(webSockets());
|
|
182
|
+
}
|
|
183
|
+
catch (e) {
|
|
184
|
+
console.warn(`[P2P] Failed to add websockets transport:`, e);
|
|
185
|
+
}
|
|
168
186
|
const services = {};
|
|
187
|
+
// 2026-08-15: relay 传输需要 identify 服务 (libp2p 3.x 依赖检查)
|
|
188
|
+
try {
|
|
189
|
+
const { identify } = await import('@libp2p/identify');
|
|
190
|
+
services.identify = identify();
|
|
191
|
+
}
|
|
192
|
+
catch (e) {
|
|
193
|
+
console.warn(`[P2P] Failed to setup identify:`, e);
|
|
194
|
+
}
|
|
195
|
+
// 2026-08-15: 加密 + 多路复用 (与手机端 websockets 节点互通必需)
|
|
196
|
+
let connectionEncrypters = [];
|
|
197
|
+
let streamMuxers = [];
|
|
198
|
+
try {
|
|
199
|
+
const { noise } = await import('@chainsafe/libp2p-noise');
|
|
200
|
+
connectionEncrypters = [noise()];
|
|
201
|
+
}
|
|
202
|
+
catch (e) {
|
|
203
|
+
console.warn(`[P2P] Failed to setup noise encrypter:`, e);
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
206
|
+
const { yamux } = await import('@chainsafe/libp2p-yamux');
|
|
207
|
+
streamMuxers = [yamux()];
|
|
208
|
+
}
|
|
209
|
+
catch (e) {
|
|
210
|
+
console.warn(`[P2P] Failed to setup yamux muxer:`, e);
|
|
211
|
+
}
|
|
169
212
|
if (enableRelay) {
|
|
170
213
|
try {
|
|
171
214
|
const relayTransport = circuitRelayTransport();
|
|
@@ -193,9 +236,11 @@ export class P2PNetwork {
|
|
|
193
236
|
}
|
|
194
237
|
this.node = await createLibp2p({
|
|
195
238
|
addresses: {
|
|
196
|
-
listen: ['/ip4/0.0.0.0/tcp/0']
|
|
239
|
+
listen: ['/ip4/0.0.0.0/tcp/0', '/ip4/0.0.0.0/tcp/0/ws']
|
|
197
240
|
},
|
|
198
241
|
transports,
|
|
242
|
+
connectionEncrypters,
|
|
243
|
+
streamMuxers,
|
|
199
244
|
services
|
|
200
245
|
});
|
|
201
246
|
this.node.addEventListener('peer-relay-registry', (evt) => {
|
|
@@ -420,7 +465,7 @@ export class P2PNetwork {
|
|
|
420
465
|
if (!this.node)
|
|
421
466
|
return;
|
|
422
467
|
const network = this;
|
|
423
|
-
this.node.handle('/agent/message', async (
|
|
468
|
+
this.node.handle('/agent/message', async (stream, connection) => {
|
|
424
469
|
try {
|
|
425
470
|
const chunks = [];
|
|
426
471
|
for await (const chunk of stream) {
|
|
@@ -544,6 +589,23 @@ export class P2PNetwork {
|
|
|
544
589
|
if (handler) {
|
|
545
590
|
handler(data, fromPeerId, did);
|
|
546
591
|
}
|
|
592
|
+
else if (type.startsWith('data.') && network.dataProviders.has(type)) {
|
|
593
|
+
// 2026-08-15: data.* 提供者 (如 data.llm-config) — 由上层注册, 返回 payload 回给请求方
|
|
594
|
+
try {
|
|
595
|
+
const provider = network.dataProviders.get(type);
|
|
596
|
+
const replyPayload = await provider(payload, fromPeerId, did);
|
|
597
|
+
if (replyPayload != null) {
|
|
598
|
+
// 回 data.llm-config.reply 语义: <type>.reply (不带 DID 前缀, 手机端解析按 type:payload 兼容)
|
|
599
|
+
const replyType = type + '.reply';
|
|
600
|
+
const encoded = new TextEncoder().encode(`${replyType}:${replyPayload}`);
|
|
601
|
+
console.log(`[P2P] data provider ${type} → reply ${replyType} (${replyPayload.length}B) to ${fromPeerId.slice(0, 10)}`);
|
|
602
|
+
await network.sendRawMessage(fromPeerId, encoded);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
catch (e) {
|
|
606
|
+
console.error(`[P2P] data provider ${type} error:`, e);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
547
609
|
else if (type === 'RESP' && requestId) {
|
|
548
610
|
// Handle response message - resolve the pending request
|
|
549
611
|
const pending = network.pendingResponses.get(requestId);
|
|
@@ -572,8 +634,20 @@ export class P2PNetwork {
|
|
|
572
634
|
async sendRawMessage(peerId, data) {
|
|
573
635
|
if (!this.node)
|
|
574
636
|
throw new Error('Node not initialized');
|
|
637
|
+
// libp2p 3.x: 优先复用已建立连接 (手机经 ws 连接, 不能反向 tcp dial)
|
|
638
|
+
const conns = this.node.getConnections?.() || [];
|
|
639
|
+
for (const c of conns) {
|
|
640
|
+
if (c.remotePeer.toString() === peerId) {
|
|
641
|
+
// dialProtocol 返回 Stream 本体 (非 {stream})
|
|
642
|
+
const stream = await this.node.dialProtocol(c.remotePeer, '/agent/message');
|
|
643
|
+
stream.send(data);
|
|
644
|
+
await stream.close().catch(() => { });
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
575
648
|
const ma = createMultiaddr(`/p2p/${peerId}`);
|
|
576
|
-
|
|
649
|
+
// libp2p 3.x: dialProtocol 返回 Stream 本体 (非 {stream})
|
|
650
|
+
const stream = await this.node.dialProtocol(ma, '/agent/message');
|
|
577
651
|
stream.send(data);
|
|
578
652
|
}
|
|
579
653
|
storeOfflineMessage(peerId, data) {
|
|
@@ -151,15 +151,9 @@ export class OrbitDBAdapter {
|
|
|
151
151
|
await this.node.helia.blockstore.put(CID.parse(rec.id), dagCbor.encode(rec));
|
|
152
152
|
return `bolloon-cid://${rec.id}`;
|
|
153
153
|
}
|
|
154
|
-
/**
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
* 返回的 store 是通用适配 (put=keyvalue / add=events).
|
|
158
|
-
*/
|
|
159
|
-
async openStore(name, type = 'keyvalue') {
|
|
160
|
-
await this.ensure();
|
|
161
|
-
const raw = (await this._orbitdb.open(name, { type }));
|
|
162
|
-
const store = {
|
|
154
|
+
/** 打开 store 的通用适配 (keyvalue/events 统一成 OrbitDBStore) */
|
|
155
|
+
wrapStore(raw) {
|
|
156
|
+
return {
|
|
163
157
|
address: raw.address,
|
|
164
158
|
put: async (key, value) => { await raw.put(key, JSON.parse(JSON.stringify(value))); },
|
|
165
159
|
add: async (value) => { await raw.add(JSON.parse(JSON.stringify(value))); },
|
|
@@ -190,7 +184,42 @@ export class OrbitDBAdapter {
|
|
|
190
184
|
};
|
|
191
185
|
},
|
|
192
186
|
};
|
|
193
|
-
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* 2026-08-08: 在同一 OrbitDB 实例上打开附加 store。
|
|
190
|
+
* events 类型 = append-only 事件流 (WAL 复制 / 轨迹流用).
|
|
191
|
+
* opts.accessController: 群组用 write:['*'] (任何人可写).
|
|
192
|
+
*/
|
|
193
|
+
async openStore(name, type = 'keyvalue', opts) {
|
|
194
|
+
await this.ensure();
|
|
195
|
+
const options = { type };
|
|
196
|
+
if (opts?.accessController)
|
|
197
|
+
options.accessController = opts.accessController;
|
|
198
|
+
const raw = (await this._orbitdb.open(name, options));
|
|
199
|
+
return this.wrapStore(raw);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* 2026-08-14: 按地址打开远端 store (Agent Gateway 共享网络 / 群组)。
|
|
203
|
+
* replica=true → 只读副本: 拉取复制但不写回 (自动加入网络不污染他人 registry)。
|
|
204
|
+
* replica=false → 可写 (群组: events store 配 write:'*' 时成员可广播)。
|
|
205
|
+
*/
|
|
206
|
+
async openStoreByAddress(address, type = 'keyvalue', opts) {
|
|
207
|
+
await this.ensure();
|
|
208
|
+
try {
|
|
209
|
+
const options = { type };
|
|
210
|
+
if (opts?.replica === false)
|
|
211
|
+
options.replica = false;
|
|
212
|
+
else
|
|
213
|
+
options.replica = true;
|
|
214
|
+
if (opts?.accessController)
|
|
215
|
+
options.accessController = opts.accessController;
|
|
216
|
+
const raw = (await this._orbitdb.open(address, options));
|
|
217
|
+
return this.wrapStore(raw);
|
|
218
|
+
}
|
|
219
|
+
catch (err) {
|
|
220
|
+
console.warn(`[orbitdb] openStoreByAddress 失败: ${String(err?.message || err).slice(0, 160)}`);
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
194
223
|
}
|
|
195
224
|
async close() {
|
|
196
225
|
try {
|
|
@@ -81,21 +81,21 @@ function getLLM() {
|
|
|
81
81
|
}
|
|
82
82
|
return cachedModel;
|
|
83
83
|
}
|
|
84
|
-
const CORRELATION_PROMPT = `你是"判断力关联分析器"。给定两条 judgment:
|
|
85
|
-
A: {a}
|
|
86
|
-
B: {b}
|
|
87
|
-
|
|
88
|
-
它们经常在同一对话里被同时注入 (共现 {co} 次).
|
|
89
|
-
判断 A 与 B 的因果关系:
|
|
90
|
-
- "A→B": A 引发 B (A 概念在 B 之前)
|
|
91
|
-
- "B→A": B 引发 A
|
|
92
|
-
- "common_cause": 共同原因 (e.g. 都是某场景触发)
|
|
93
|
-
- "unclear": 关系不明确
|
|
94
|
-
|
|
95
|
-
输出严格 JSON:
|
|
96
|
-
{
|
|
97
|
-
"direction": "A→B" | "B→A" | "common_cause" | "unclear",
|
|
98
|
-
"explanation": "≤100 字解释, 含 1 个具体例"
|
|
84
|
+
const CORRELATION_PROMPT = `你是"判断力关联分析器"。给定两条 judgment:
|
|
85
|
+
A: {a}
|
|
86
|
+
B: {b}
|
|
87
|
+
|
|
88
|
+
它们经常在同一对话里被同时注入 (共现 {co} 次).
|
|
89
|
+
判断 A 与 B 的因果关系:
|
|
90
|
+
- "A→B": A 引发 B (A 概念在 B 之前)
|
|
91
|
+
- "B→A": B 引发 A
|
|
92
|
+
- "common_cause": 共同原因 (e.g. 都是某场景触发)
|
|
93
|
+
- "unclear": 关系不明确
|
|
94
|
+
|
|
95
|
+
输出严格 JSON:
|
|
96
|
+
{
|
|
97
|
+
"direction": "A→B" | "B→A" | "common_cause" | "unclear",
|
|
98
|
+
"explanation": "≤100 字解释, 含 1 个具体例"
|
|
99
99
|
}`;
|
|
100
100
|
async function explainPair(judgmentA, judgmentB, coOccurrence) {
|
|
101
101
|
const fallback = { direction: 'unclear', explanation: '(LLM 不可用, 仅显示统计)' };
|
|
@@ -213,21 +213,21 @@ export async function runCorrelationAnalysis(opts = {}) {
|
|
|
213
213
|
}
|
|
214
214
|
return out;
|
|
215
215
|
}
|
|
216
|
-
const INTERVENTION_PROMPT = `你是"判断力干预分析器"。判断力库有一条 judgment, 用户想评估它的边际贡献.
|
|
217
|
-
给定:
|
|
218
|
-
- judgment: {judgment}
|
|
219
|
-
- 上次用过的场景 (user 输入 + AI 回复): {scenario}
|
|
220
|
-
- 同时存在的相邻 judgment (供参考): {peers}
|
|
221
|
-
|
|
222
|
-
模拟反事实推理: 如果库**没有**这条 judgment, AI 在同一场景下回答会怎么变?
|
|
223
|
-
|
|
224
|
-
输出严格 JSON:
|
|
225
|
-
{
|
|
226
|
-
"causalEffect": 0.0-1.0, // 0 = 无影响, 1 = 行为完全变
|
|
227
|
-
"reasoning": "2-3 步推理, 含 1 个具体例",
|
|
228
|
-
"confidence": 0.0-1.0
|
|
229
|
-
}
|
|
230
|
-
|
|
216
|
+
const INTERVENTION_PROMPT = `你是"判断力干预分析器"。判断力库有一条 judgment, 用户想评估它的边际贡献.
|
|
217
|
+
给定:
|
|
218
|
+
- judgment: {judgment}
|
|
219
|
+
- 上次用过的场景 (user 输入 + AI 回复): {scenario}
|
|
220
|
+
- 同时存在的相邻 judgment (供参考): {peers}
|
|
221
|
+
|
|
222
|
+
模拟反事实推理: 如果库**没有**这条 judgment, AI 在同一场景下回答会怎么变?
|
|
223
|
+
|
|
224
|
+
输出严格 JSON:
|
|
225
|
+
{
|
|
226
|
+
"causalEffect": 0.0-1.0, // 0 = 无影响, 1 = 行为完全变
|
|
227
|
+
"reasoning": "2-3 步推理, 含 1 个具体例",
|
|
228
|
+
"confidence": 0.0-1.0
|
|
229
|
+
}
|
|
230
|
+
|
|
231
231
|
注意: causalEffect < 0 也合法 (如"没有这条 AI 反而更好" — 库污染)`;
|
|
232
232
|
export async function runIntervention(judgmentId, opts = {}) {
|
|
233
233
|
const fallback = {
|
|
@@ -273,27 +273,27 @@ export async function runIntervention(judgmentId, opts = {}) {
|
|
|
273
273
|
return fallback;
|
|
274
274
|
}
|
|
275
275
|
}
|
|
276
|
-
const COUNTERFACTUAL_PROMPT = `你是"判断力反事实审计员"。某次 AI 回复违反了注入的 judgment. 判断是库设计问题还是 LLM 偶然违规.
|
|
277
|
-
|
|
278
|
-
事件:
|
|
279
|
-
- 用户: {userInput}
|
|
280
|
-
- AI 回复: {aiReply}
|
|
281
|
-
- 违反原则: {principles}
|
|
282
|
-
|
|
283
|
-
构造 3 个反事实 scenario:
|
|
284
|
-
1. 删去最相关那条 judgment
|
|
285
|
-
2. 把那条 judgment 改成反向 (例如"必须"→"避免")
|
|
286
|
-
3. 删去整个 channel 的 judgment 库 (空库)
|
|
287
|
-
|
|
288
|
-
每个 scenario 模拟 AI 在该库下的回答, 判断还会不会违规.
|
|
289
|
-
|
|
290
|
-
输出严格 JSON:
|
|
291
|
-
{
|
|
292
|
-
"scenarios": [
|
|
293
|
-
{ "modification": "...", "outcomeCompliant": true/false, "explanation": "≤100 字" }
|
|
294
|
-
],
|
|
295
|
-
"verdict": "库设计合理" | "建议调库" | "需更多数据",
|
|
296
|
-
"recomendaciones": "≤200 字, ≤3 条建议"
|
|
276
|
+
const COUNTERFACTUAL_PROMPT = `你是"判断力反事实审计员"。某次 AI 回复违反了注入的 judgment. 判断是库设计问题还是 LLM 偶然违规.
|
|
277
|
+
|
|
278
|
+
事件:
|
|
279
|
+
- 用户: {userInput}
|
|
280
|
+
- AI 回复: {aiReply}
|
|
281
|
+
- 违反原则: {principles}
|
|
282
|
+
|
|
283
|
+
构造 3 个反事实 scenario:
|
|
284
|
+
1. 删去最相关那条 judgment
|
|
285
|
+
2. 把那条 judgment 改成反向 (例如"必须"→"避免")
|
|
286
|
+
3. 删去整个 channel 的 judgment 库 (空库)
|
|
287
|
+
|
|
288
|
+
每个 scenario 模拟 AI 在该库下的回答, 判断还会不会违规.
|
|
289
|
+
|
|
290
|
+
输出严格 JSON:
|
|
291
|
+
{
|
|
292
|
+
"scenarios": [
|
|
293
|
+
{ "modification": "...", "outcomeCompliant": true/false, "explanation": "≤100 字" }
|
|
294
|
+
],
|
|
295
|
+
"verdict": "库设计合理" | "建议调库" | "需更多数据",
|
|
296
|
+
"recomendaciones": "≤200 字, ≤3 条建议"
|
|
297
297
|
}`;
|
|
298
298
|
export async function runCounterfactualAudit(opts) {
|
|
299
299
|
const fallback = {
|
|
@@ -4,39 +4,39 @@
|
|
|
4
4
|
* - 演化对齐: 判定新判断力与已有判断力的关系 (merge/contradict/unrelated)
|
|
5
5
|
*/
|
|
6
6
|
import { getModel } from '../llm/pi-ai.js';
|
|
7
|
-
const DISTILL_SYSTEM_PROMPT = `你是一个"判断力蒸馏器"。从给定的对话片段中,提取出**一条**可以长期复用的判断力原则。
|
|
8
|
-
|
|
9
|
-
要求:
|
|
10
|
-
- 长度 30-80 字(中文字符),软目标 50 字
|
|
11
|
-
- 用陈述句,不要"我觉得/我想要"这种主观前缀
|
|
12
|
-
- 要有可操作性,能被未来的自己/AI 引用
|
|
13
|
-
- 如果对话里没有值得提炼的判断力,返回 {"value": null}
|
|
14
|
-
|
|
15
|
-
输出格式(严格 JSON,无其他文字):
|
|
16
|
-
{
|
|
17
|
-
"value": "<30-80 字的判断力>" | null,
|
|
18
|
-
"category": "rule" | "preference" | "trajectory" | "reward",
|
|
19
|
-
"confidence": 0.0-1.0,
|
|
20
|
-
"evidence": "<原文中支持这句话的关键句,不超过 30 字>"
|
|
7
|
+
const DISTILL_SYSTEM_PROMPT = `你是一个"判断力蒸馏器"。从给定的对话片段中,提取出**一条**可以长期复用的判断力原则。
|
|
8
|
+
|
|
9
|
+
要求:
|
|
10
|
+
- 长度 30-80 字(中文字符),软目标 50 字
|
|
11
|
+
- 用陈述句,不要"我觉得/我想要"这种主观前缀
|
|
12
|
+
- 要有可操作性,能被未来的自己/AI 引用
|
|
13
|
+
- 如果对话里没有值得提炼的判断力,返回 {"value": null}
|
|
14
|
+
|
|
15
|
+
输出格式(严格 JSON,无其他文字):
|
|
16
|
+
{
|
|
17
|
+
"value": "<30-80 字的判断力>" | null,
|
|
18
|
+
"category": "rule" | "preference" | "trajectory" | "reward",
|
|
19
|
+
"confidence": 0.0-1.0,
|
|
20
|
+
"evidence": "<原文中支持这句话的关键句,不超过 30 字>"
|
|
21
21
|
}`;
|
|
22
|
-
const EVOLVE_SYSTEM_PROMPT = `你是"判断力演化对齐器"。对比一条新判断力与已有判断力,判定关系。
|
|
23
|
-
|
|
24
|
-
新判断力:
|
|
25
|
-
{new_value}
|
|
26
|
-
|
|
27
|
-
已有判断力列表(最多 10 条):
|
|
28
|
-
{existing_list}
|
|
29
|
-
|
|
30
|
-
对每条已有判断力,判定:
|
|
31
|
-
- "merge": 新判断力是这条的更新版/具体版/纠正版 → 旧条应被 superseded
|
|
32
|
-
- "contradict": 新判断力与这条方向相反(例如"保守"vs"激进") → 旧条应被 superseded
|
|
33
|
-
- "unrelated": 两者主题不同,各自保留
|
|
34
|
-
|
|
35
|
-
输出严格 JSON:
|
|
36
|
-
{
|
|
37
|
-
"relations": [
|
|
38
|
-
{"id": "...", "relation": "merge" | "contradict" | "unrelated", "reason": "≤20 字"}
|
|
39
|
-
]
|
|
22
|
+
const EVOLVE_SYSTEM_PROMPT = `你是"判断力演化对齐器"。对比一条新判断力与已有判断力,判定关系。
|
|
23
|
+
|
|
24
|
+
新判断力:
|
|
25
|
+
{new_value}
|
|
26
|
+
|
|
27
|
+
已有判断力列表(最多 10 条):
|
|
28
|
+
{existing_list}
|
|
29
|
+
|
|
30
|
+
对每条已有判断力,判定:
|
|
31
|
+
- "merge": 新判断力是这条的更新版/具体版/纠正版 → 旧条应被 superseded
|
|
32
|
+
- "contradict": 新判断力与这条方向相反(例如"保守"vs"激进") → 旧条应被 superseded
|
|
33
|
+
- "unrelated": 两者主题不同,各自保留
|
|
34
|
+
|
|
35
|
+
输出严格 JSON:
|
|
36
|
+
{
|
|
37
|
+
"relations": [
|
|
38
|
+
{"id": "...", "relation": "merge" | "contradict" | "unrelated", "reason": "≤20 字"}
|
|
39
|
+
]
|
|
40
40
|
}`;
|
|
41
41
|
let cachedModel = null;
|
|
42
42
|
function getDistillModel() {
|
|
@@ -56,13 +56,13 @@ export async function detectIfWorthStoring(turns) {
|
|
|
56
56
|
if (!model)
|
|
57
57
|
return fallback;
|
|
58
58
|
const conversation = formatTurns(turns);
|
|
59
|
-
const prompt = `请判断以下对话是否包含"值得长期保留的判断力"(用户的偏好/规则/原则/价值观)。
|
|
60
|
-
如果包含,返回 {"worth": true, "reason": "≤20 字理由"}
|
|
61
|
-
如果不包含,返回 {"worth": false, "reason": "≤20 字理由"}
|
|
62
|
-
|
|
63
|
-
对话:
|
|
64
|
-
${conversation}
|
|
65
|
-
|
|
59
|
+
const prompt = `请判断以下对话是否包含"值得长期保留的判断力"(用户的偏好/规则/原则/价值观)。
|
|
60
|
+
如果包含,返回 {"worth": true, "reason": "≤20 字理由"}
|
|
61
|
+
如果不包含,返回 {"worth": false, "reason": "≤20 字理由"}
|
|
62
|
+
|
|
63
|
+
对话:
|
|
64
|
+
${conversation}
|
|
65
|
+
|
|
66
66
|
输出严格 JSON:`;
|
|
67
67
|
try {
|
|
68
68
|
const res = await withRetry(() => model.chat(prompt, '判断力检测专家'));
|
|
@@ -84,9 +84,9 @@ export async function distillFromConversation(turns) {
|
|
|
84
84
|
if (!model)
|
|
85
85
|
return fallback;
|
|
86
86
|
const conversation = formatTurns(turns);
|
|
87
|
-
const userPrompt = `对话上下文(最多 10 轮):
|
|
88
|
-
${conversation}
|
|
89
|
-
|
|
87
|
+
const userPrompt = `对话上下文(最多 10 轮):
|
|
88
|
+
${conversation}
|
|
89
|
+
|
|
90
90
|
输出:`;
|
|
91
91
|
try {
|
|
92
92
|
const res = await withRetry(() => model.chat(userPrompt, DISTILL_SYSTEM_PROMPT));
|