@bolloon/bolloon-agent 0.2.11 → 0.2.13
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 +495 -467
- package/bin/bolloon-cli.cjs +183 -183
- package/bin/bolloon-daemon.sh +207 -0
- package/bin/bolloon.cjs +0 -0
- package/bin/ipfs +0 -0
- package/dist/agents/agent-manifest-protocol.js +52 -0
- package/dist/agents/chat-segmenter.js +298 -0
- package/dist/agents/constraint-layer.js +19 -19
- package/dist/agents/judgment-protocol.js +479 -0
- package/dist/agents/parse-tool-call.js +304 -0
- package/dist/agents/peer-manifest-loader.js +210 -0
- package/dist/agents/pi-sdk-session-factory.js +110 -0
- package/dist/agents/pi-sdk-session-manager.js +297 -0
- package/dist/agents/pi-sdk-tools.js +1288 -0
- package/dist/agents/pi-sdk-types.js +13 -0
- package/dist/agents/pi-sdk.js +553 -1306
- package/dist/agents/react-loop.js +120 -0
- package/dist/agents/session-store.js +171 -0
- package/dist/agents/shell-guard.js +2 -2
- package/dist/agents/tool-registry.js +136 -0
- package/dist/agents/workflow-pivot-loop.js +200 -22
- package/dist/bollharness/src/scripts/context_router.js +7 -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 +26 -13
- package/dist/bollharness-integration/integration.js +71 -0
- package/dist/bollharness-integration/llm-judgment-engine.js +134 -134
- package/dist/bollharness-integration/skill-adapter.js +57 -127
- package/dist/bootstrap/chat-archiver.js +276 -0
- package/dist/bootstrap/context-collector.js +6 -3
- package/dist/bootstrap/event-log.js +160 -0
- package/dist/bootstrap/lifecycle-hooks.js +15 -1
- package/dist/bootstrap/memory-compressor.js +170 -0
- package/dist/bootstrap/persona-loader.js +94 -0
- package/dist/bootstrap/project-state.js +159 -0
- package/dist/bootstrap/remote-mirror.js +97 -0
- package/dist/bootstrap/session-window.js +121 -0
- package/dist/bootstrap/vector-index.js +248 -0
- package/dist/cli/loading-tui.js +40 -0
- package/dist/cli-entry.js +41 -37
- package/dist/context-compaction/auto-compact.js +7 -7
- package/dist/electron/config.js +21 -0
- package/dist/electron/config.js.map +1 -0
- package/dist/electron/dialogs.js +108 -0
- package/dist/electron/dialogs.js.map +1 -0
- package/dist/electron/first-run.js +170 -0
- package/dist/electron/first-run.js.map +1 -0
- package/dist/electron/ipc.js +20 -0
- package/dist/electron/ipc.js.map +1 -0
- package/dist/electron/logger.js +114 -0
- package/dist/electron/logger.js.map +1 -0
- package/dist/electron/main.js +63 -0
- package/dist/electron/main.js.map +1 -0
- package/dist/electron/menu.js +145 -0
- package/dist/electron/menu.js.map +1 -0
- package/dist/electron/paths.js +75 -0
- package/dist/electron/paths.js.map +1 -0
- package/dist/electron/server.js +119 -0
- package/dist/electron/server.js.map +1 -0
- package/dist/electron/tray.js +111 -0
- package/dist/electron/tray.js.map +1 -0
- package/dist/electron/window.js +111 -0
- package/dist/electron/window.js.map +1 -0
- package/dist/electron-preload.js +26 -6
- package/dist/electron-preload.js.map +1 -1
- package/dist/electron.js +6 -168
- package/dist/electron.js.map +1 -1
- package/dist/index.js +323 -266
- package/dist/llm/config-store.js +24 -8
- package/dist/llm/llm-judgment-client.js +102 -102
- package/dist/llm/pi-ai.js +137 -85
- 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-visitor.md +19 -19
- 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/hibs_reminders.md +15 -15
- package/dist/llm/system-prompt/layers/core/identity.md +37 -37
- 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/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/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/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/local-inbox-bus.js +73 -0
- package/dist/network/p2p-outbox.js +161 -0
- package/dist/network/peer-fs.js +420 -0
- package/dist/network/peer-resource-bridge.js +216 -0
- package/dist/pi-ecosystem-judgment/causal-judge.js +51 -51
- package/dist/pi-ecosystem-judgment/cleanup.js +126 -0
- package/dist/pi-ecosystem-judgment/distill-prompt.js +42 -42
- package/dist/pi-ecosystem-judgment/distillation.js +14 -14
- package/dist/pi-ecosystem-judgment/human-value-store.js +45 -11
- 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/security/tool-gate.js +11 -0
- package/dist/web/api-config.html +520 -520
- package/dist/web/client-loop-status.js +220 -0
- package/dist/web/client.js +1677 -244
- package/dist/web/client.js.map +7 -0
- package/dist/web/components/wallet-viem.mjs +118 -118
- package/dist/web/index.html +375 -374
- package/dist/web/input-validator.js +103 -0
- package/dist/web/manifest.json +20 -20
- package/dist/web/routes-judgments.js +738 -0
- package/dist/web/routes-llm-config.js +279 -0
- package/dist/web/routes-tasks.js +222 -0
- package/dist/web/server-sse.js +121 -0
- package/dist/web/server-storage.js +154 -0
- package/dist/web/server-types.js +15 -0
- package/dist/web/server-v3-p2p.js +224 -0
- package/dist/web/server.js +1070 -1307
- package/dist/web/style.css +4742 -4737
- package/dist/web/util/safe-name.js +32 -0
- package/package.json +162 -160
- package/scripts/build-cli.js +215 -215
- package/scripts/build-web.ts +130 -125
- package/scripts/postinstall.js +152 -152
- package/bin/bolloon.js +0 -157
- package/dist/constraint-runtime/src/_archive_helper.js +0 -9
- package/dist/constraint-runtime/src/agent/coordinator.js +0 -48
- package/dist/constraint-runtime/src/agent/index.js +0 -1
- package/dist/constraint-runtime/src/assistant/index.js +0 -12
- package/dist/constraint-runtime/src/bootstrap/index.js +0 -12
- package/dist/constraint-runtime/src/bootstrap_graph.js +0 -13
- package/dist/constraint-runtime/src/bridge/index.js +0 -12
- package/dist/constraint-runtime/src/buddy/index.js +0 -12
- package/dist/constraint-runtime/src/cli/index.js +0 -12
- package/dist/constraint-runtime/src/command_graph.js +0 -10
- package/dist/constraint-runtime/src/commands.js +0 -60
- package/dist/constraint-runtime/src/components/index.js +0 -12
- package/dist/constraint-runtime/src/constants/index.js +0 -12
- package/dist/constraint-runtime/src/constraint/budget.js +0 -22
- package/dist/constraint-runtime/src/constraint/index.js +0 -2
- package/dist/constraint-runtime/src/constraint/permission.js +0 -20
- package/dist/constraint-runtime/src/context.js +0 -30
- package/dist/constraint-runtime/src/coordinator/index.js +0 -12
- package/dist/constraint-runtime/src/cost_hook.js +0 -4
- package/dist/constraint-runtime/src/cost_tracker.js +0 -8
- package/dist/constraint-runtime/src/deferred_init.js +0 -10
- package/dist/constraint-runtime/src/direct_modes.js +0 -6
- package/dist/constraint-runtime/src/dynamic-tool-loader.js +0 -85
- package/dist/constraint-runtime/src/entrypoints/index.js +0 -12
- package/dist/constraint-runtime/src/execution_registry.js +0 -44
- package/dist/constraint-runtime/src/history.js +0 -9
- package/dist/constraint-runtime/src/hooks/index.js +0 -12
- package/dist/constraint-runtime/src/index.js +0 -26
- package/dist/constraint-runtime/src/ink.js +0 -4
- package/dist/constraint-runtime/src/keybindings/index.js +0 -12
- package/dist/constraint-runtime/src/memdir/index.js +0 -12
- package/dist/constraint-runtime/src/migrations/index.js +0 -12
- package/dist/constraint-runtime/src/models.js +0 -1
- package/dist/constraint-runtime/src/moreright/index.js +0 -12
- package/dist/constraint-runtime/src/native_ts/index.js +0 -12
- package/dist/constraint-runtime/src/output_styles/index.js +0 -12
- package/dist/constraint-runtime/src/parity_audit.js +0 -12
- package/dist/constraint-runtime/src/plugins/index.js +0 -12
- package/dist/constraint-runtime/src/port_manifest.js +0 -11
- package/dist/constraint-runtime/src/prefetch.js +0 -9
- package/dist/constraint-runtime/src/query.js +0 -1
- package/dist/constraint-runtime/src/remote/index.js +0 -12
- package/dist/constraint-runtime/src/remote_runtime.js +0 -9
- package/dist/constraint-runtime/src/runtime/index.js +0 -1
- package/dist/constraint-runtime/src/runtime/session.js +0 -35
- package/dist/constraint-runtime/src/schemas/index.js +0 -12
- package/dist/constraint-runtime/src/screens/index.js +0 -12
- package/dist/constraint-runtime/src/server/index.js +0 -12
- package/dist/constraint-runtime/src/services/index.js +0 -12
- package/dist/constraint-runtime/src/session_store.js +0 -22
- package/dist/constraint-runtime/src/setup.js +0 -30
- package/dist/constraint-runtime/src/skills/index.js +0 -1
- package/dist/constraint-runtime/src/skills/skill-registry.js +0 -28
- package/dist/constraint-runtime/src/state/index.js +0 -12
- package/dist/constraint-runtime/src/system_init.js +0 -20
- package/dist/constraint-runtime/src/thinking/engine.js +0 -42
- package/dist/constraint-runtime/src/thinking/index.js +0 -1
- package/dist/constraint-runtime/src/tool_pool.js +0 -8
- package/dist/constraint-runtime/src/tools/OpenCLI/execAdapter.js +0 -7
- package/dist/constraint-runtime/src/tools/OpenCLI/listAdapters.js +0 -7
- package/dist/constraint-runtime/src/tools/OpenCLI/runCommand.js +0 -7
- package/dist/constraint-runtime/src/tools/SafeSDK/confirmTransaction.js +0 -6
- package/dist/constraint-runtime/src/tools/SafeSDK/createTransaction.js +0 -8
- package/dist/constraint-runtime/src/tools/SafeSDK/executeTransaction.js +0 -6
- package/dist/constraint-runtime/src/tools/SafeSDK/getBalance.js +0 -6
- package/dist/constraint-runtime/src/tools/SafeSDK/getPendingTransactions.js +0 -6
- package/dist/constraint-runtime/src/tools/SafeSDK/proposeTransaction.js +0 -6
- package/dist/constraint-runtime/src/tools.js +0 -80
- package/dist/constraint-runtime/src/transcript.js +0 -19
- package/dist/constraint-runtime/src/types/index.js +0 -12
- package/dist/constraint-runtime/src/upstream_proxy/index.js +0 -12
- package/dist/constraint-runtime/src/utils/index.js +0 -12
- package/dist/constraint-runtime/src/vim/index.js +0 -12
- package/dist/constraint-runtime/src/voice/index.js +0 -12
- package/dist/constraint-runtime/tests/agent.test.js +0 -16
- package/dist/constraint-runtime/tests/constraint.test.js +0 -41
- package/dist/constraint-runtime/tests/skill.test.js +0 -19
- package/dist/constraint-runtime/tests/thinking.test.js +0 -22
- 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/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
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vector-index.ts — 简化版 TF-IDF 文本检索 (Layer 4)
|
|
3
|
+
*
|
|
4
|
+
* 2026-07-07 新增. 解决:
|
|
5
|
+
* - 远端/本地月度归档 + 长文档无法语义检索
|
|
6
|
+
* - LLM prompt 缺历史上下文时只能 slice(-6) 看最近 6 条
|
|
7
|
+
* - 不引入 faiss / hnswlib 等重型依赖 (npm 包爆炸)
|
|
8
|
+
*
|
|
9
|
+
* 设计:
|
|
10
|
+
* - 倒排索引 + TF-IDF cosine similarity (够用, 不引向量库)
|
|
11
|
+
* - 英文按词切, 中文按字符 bigram 切 (混合分词)
|
|
12
|
+
* - 索引文件: ~/.bolloon/index/<indexName>.json
|
|
13
|
+
* - 单文档 < 4KB, 总文档 < 10000 时性能足够 (< 50ms 检索)
|
|
14
|
+
*
|
|
15
|
+
* 触发:
|
|
16
|
+
* - server.ts: buildIndex 启动时建一次, 增量 addDocument
|
|
17
|
+
* - server.ts: searchIndex(query, topK=3) → 注入 prompt
|
|
18
|
+
*/
|
|
19
|
+
import * as fs from 'fs/promises';
|
|
20
|
+
import * as path from 'path';
|
|
21
|
+
import * as os from 'os';
|
|
22
|
+
// ============== 路径 ==============
|
|
23
|
+
/** ~/.bolloon/index/<indexName>.json */
|
|
24
|
+
export function getIndexPath(indexName, home) {
|
|
25
|
+
const root = path.join(home || os.homedir(), '.bolloon', 'index');
|
|
26
|
+
return path.join(root, `${indexName.replace(/[^a-zA-Z0-9_-]/g, '_')}.json`);
|
|
27
|
+
}
|
|
28
|
+
// ============== 分词 (中英混合) ==============
|
|
29
|
+
/**
|
|
30
|
+
* 简易分词:
|
|
31
|
+
* - 英文/数字: 连续字母数字
|
|
32
|
+
* - 中文: 每个 char 单字 + bigram (覆盖常见短语)
|
|
33
|
+
* - 全部转小写, 去标点
|
|
34
|
+
*/
|
|
35
|
+
export function tokenize(text) {
|
|
36
|
+
if (!text)
|
|
37
|
+
return [];
|
|
38
|
+
const lower = text.toLowerCase();
|
|
39
|
+
const tokens = [];
|
|
40
|
+
// 1. 提取英文/数字词
|
|
41
|
+
const enMatches = lower.match(/[a-z0-9]+/g);
|
|
42
|
+
if (enMatches)
|
|
43
|
+
tokens.push(...enMatches);
|
|
44
|
+
// 2. 中文按 bigram (覆盖 "项目" "事件" 等常见短语)
|
|
45
|
+
// 用 [\u4e00-\u9fff] 检测中文
|
|
46
|
+
const chineseChars = [];
|
|
47
|
+
for (const ch of lower) {
|
|
48
|
+
if (/[\u4e00-\u9fff]/.test(ch))
|
|
49
|
+
chineseChars.push(ch);
|
|
50
|
+
}
|
|
51
|
+
for (let i = 0; i < chineseChars.length; i++) {
|
|
52
|
+
tokens.push(chineseChars[i]); // 单字
|
|
53
|
+
if (i + 1 < chineseChars.length) {
|
|
54
|
+
tokens.push(chineseChars[i] + chineseChars[i + 1]); // bigram
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return tokens.filter(t => t.length > 0);
|
|
58
|
+
}
|
|
59
|
+
// ============== 索引构建 ==============
|
|
60
|
+
/**
|
|
61
|
+
* 完整重建索引 (初次启动时调一次). 索引文件覆盖写.
|
|
62
|
+
*/
|
|
63
|
+
export async function buildIndex(opts) {
|
|
64
|
+
const index = {
|
|
65
|
+
name: opts.indexName,
|
|
66
|
+
postings: {},
|
|
67
|
+
docFreq: {},
|
|
68
|
+
docNorms: {},
|
|
69
|
+
docs: {},
|
|
70
|
+
totalDocs: 0,
|
|
71
|
+
avgDocLen: 0,
|
|
72
|
+
updatedAt: new Date().toISOString(),
|
|
73
|
+
};
|
|
74
|
+
let totalLen = 0;
|
|
75
|
+
for (const doc of opts.documents) {
|
|
76
|
+
const tokens = tokenize(doc.text);
|
|
77
|
+
totalLen += tokens.length;
|
|
78
|
+
index.docs[doc.id] = doc;
|
|
79
|
+
index.docNorms[doc.id] = 0; // 后面算
|
|
80
|
+
// 词频统计 (本 doc)
|
|
81
|
+
const tf = {};
|
|
82
|
+
for (const t of tokens) {
|
|
83
|
+
tf[t] = (tf[t] || 0) + 1;
|
|
84
|
+
}
|
|
85
|
+
for (const [term, count] of Object.entries(tf)) {
|
|
86
|
+
if (!index.postings[term])
|
|
87
|
+
index.postings[term] = [];
|
|
88
|
+
if (!index.postings[term].includes(doc.id))
|
|
89
|
+
index.postings[term].push(doc.id);
|
|
90
|
+
index.docFreq[term] = (index.docFreq[term] || 0) + 1;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
index.totalDocs = opts.documents.length;
|
|
94
|
+
index.avgDocLen = index.totalDocs > 0 ? totalLen / index.totalDocs : 0;
|
|
95
|
+
// 计算 docNorms (TF-IDF 向量长度)
|
|
96
|
+
for (const docId of Object.keys(index.docs)) {
|
|
97
|
+
const tokens = tokenize(index.docs[docId].text);
|
|
98
|
+
const tf = {};
|
|
99
|
+
for (const t of tokens)
|
|
100
|
+
tf[t] = (tf[t] || 0) + 1;
|
|
101
|
+
let sum = 0;
|
|
102
|
+
for (const [term, count] of Object.entries(tf)) {
|
|
103
|
+
const idf = Math.log((index.totalDocs + 1) / ((index.docFreq[term] || 0) + 0.5));
|
|
104
|
+
sum += Math.pow(count * idf, 2);
|
|
105
|
+
}
|
|
106
|
+
index.docNorms[docId] = Math.sqrt(sum);
|
|
107
|
+
}
|
|
108
|
+
const filePath = getIndexPath(opts.indexName, opts.home);
|
|
109
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
110
|
+
await fs.writeFile(filePath, JSON.stringify(index), 'utf-8');
|
|
111
|
+
return { path: filePath, totalDocs: index.totalDocs };
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* 读索引. 不存在 → 返回 null.
|
|
115
|
+
*/
|
|
116
|
+
export async function loadIndex(indexName, home) {
|
|
117
|
+
const filePath = getIndexPath(indexName, home);
|
|
118
|
+
try {
|
|
119
|
+
const raw = await fs.readFile(filePath, 'utf-8');
|
|
120
|
+
const parsed = JSON.parse(raw);
|
|
121
|
+
if (!parsed || typeof parsed !== 'object' || !parsed.postings)
|
|
122
|
+
return null;
|
|
123
|
+
return parsed;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* 加单条文档到索引 (增量). 不存在 → 自动建空索引.
|
|
131
|
+
*/
|
|
132
|
+
export async function addDocument(opts) {
|
|
133
|
+
let index = await loadIndex(opts.indexName, opts.home);
|
|
134
|
+
if (!index) {
|
|
135
|
+
await buildIndex({ indexName: opts.indexName, documents: [opts.doc], home: opts.home });
|
|
136
|
+
return (await loadIndex(opts.indexName, opts.home));
|
|
137
|
+
}
|
|
138
|
+
// 增量更新
|
|
139
|
+
const tokens = tokenize(opts.doc.text);
|
|
140
|
+
if (index.docs[opts.doc.id]) {
|
|
141
|
+
// 已存在 → 简单覆盖 (不维护精确 docNorms, 重建)
|
|
142
|
+
const oldDoc = index.docs[opts.doc.id];
|
|
143
|
+
const oldTokens = tokenize(oldDoc.text);
|
|
144
|
+
for (const t of oldTokens) {
|
|
145
|
+
if (index.postings[t]) {
|
|
146
|
+
index.postings[t] = index.postings[t].filter(id => id !== opts.doc.id);
|
|
147
|
+
if (index.postings[t].length === 0)
|
|
148
|
+
delete index.postings[t];
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
index.docs[opts.doc.id] = opts.doc;
|
|
153
|
+
const tf = {};
|
|
154
|
+
for (const t of tokens)
|
|
155
|
+
tf[t] = (tf[t] || 0) + 1;
|
|
156
|
+
for (const [term, count] of Object.entries(tf)) {
|
|
157
|
+
if (!index.postings[term])
|
|
158
|
+
index.postings[term] = [];
|
|
159
|
+
if (!index.postings[term].includes(opts.doc.id)) {
|
|
160
|
+
index.postings[term].push(opts.doc.id);
|
|
161
|
+
index.docFreq[term] = (index.docFreq[term] || 0) + 1;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
index.totalDocs = Object.keys(index.docs).length;
|
|
165
|
+
// 简化: 不重算所有 docNorms, 只算本条 (足够增量场景)
|
|
166
|
+
let sum = 0;
|
|
167
|
+
for (const [term, count] of Object.entries(tf)) {
|
|
168
|
+
const idf = Math.log((index.totalDocs + 1) / ((index.docFreq[term] || 0) + 0.5));
|
|
169
|
+
sum += Math.pow(count * idf, 2);
|
|
170
|
+
}
|
|
171
|
+
index.docNorms[opts.doc.id] = Math.sqrt(sum);
|
|
172
|
+
index.updatedAt = new Date().toISOString();
|
|
173
|
+
const filePath = getIndexPath(opts.indexName, opts.home);
|
|
174
|
+
await fs.writeFile(filePath, JSON.stringify(index), 'utf-8');
|
|
175
|
+
return index;
|
|
176
|
+
}
|
|
177
|
+
// ============== 检索 ==============
|
|
178
|
+
/**
|
|
179
|
+
* TF-IDF cosine similarity top-K 检索.
|
|
180
|
+
*/
|
|
181
|
+
export async function searchIndex(opts) {
|
|
182
|
+
const index = await loadIndex(opts.indexName, opts.home);
|
|
183
|
+
if (!index || index.totalDocs === 0)
|
|
184
|
+
return [];
|
|
185
|
+
const queryTokens = tokenize(opts.query);
|
|
186
|
+
if (queryTokens.length === 0)
|
|
187
|
+
return [];
|
|
188
|
+
// 查询向量
|
|
189
|
+
const queryTf = {};
|
|
190
|
+
for (const t of queryTokens)
|
|
191
|
+
queryTf[t] = (queryTf[t] || 0) + 1;
|
|
192
|
+
let queryNorm = 0;
|
|
193
|
+
const queryVec = {};
|
|
194
|
+
for (const [term, count] of Object.entries(queryTf)) {
|
|
195
|
+
const idf = Math.log((index.totalDocs + 1) / ((index.docFreq[term] || 0) + 0.5));
|
|
196
|
+
const w = count * idf;
|
|
197
|
+
queryVec[term] = w;
|
|
198
|
+
queryNorm += w * w;
|
|
199
|
+
}
|
|
200
|
+
queryNorm = Math.sqrt(queryNorm);
|
|
201
|
+
if (queryNorm === 0)
|
|
202
|
+
return [];
|
|
203
|
+
// 候选 doc 集合 (所有包含 query term 的 doc)
|
|
204
|
+
const candidates = new Set();
|
|
205
|
+
for (const term of Object.keys(queryTf)) {
|
|
206
|
+
const posting = index.postings[term] || [];
|
|
207
|
+
for (const id of posting)
|
|
208
|
+
candidates.add(id);
|
|
209
|
+
}
|
|
210
|
+
// 计算 cosine
|
|
211
|
+
const scores = [];
|
|
212
|
+
for (const docId of candidates) {
|
|
213
|
+
const docTokens = tokenize(index.docs[docId]?.text || '');
|
|
214
|
+
const docTf = {};
|
|
215
|
+
for (const t of docTokens)
|
|
216
|
+
docTf[t] = (docTf[t] || 0) + 1;
|
|
217
|
+
let dot = 0;
|
|
218
|
+
for (const term of Object.keys(queryTf)) {
|
|
219
|
+
const dw = (docTf[term] || 0) * Math.log((index.totalDocs + 1) / ((index.docFreq[term] || 0) + 0.5));
|
|
220
|
+
dot += queryVec[term] * dw;
|
|
221
|
+
}
|
|
222
|
+
const docNorm = index.docNorms[docId] || 0;
|
|
223
|
+
if (docNorm === 0)
|
|
224
|
+
continue;
|
|
225
|
+
const score = dot / (queryNorm * docNorm);
|
|
226
|
+
if (score > 0)
|
|
227
|
+
scores.push({ id: docId, score });
|
|
228
|
+
}
|
|
229
|
+
scores.sort((a, b) => b.score - a.score);
|
|
230
|
+
const topK = opts.topK ?? 3;
|
|
231
|
+
return scores.slice(0, topK).map(s => ({
|
|
232
|
+
id: s.id,
|
|
233
|
+
score: s.score,
|
|
234
|
+
text: index.docs[s.id]?.text || '',
|
|
235
|
+
metadata: index.docs[s.id]?.metadata,
|
|
236
|
+
}));
|
|
237
|
+
}
|
|
238
|
+
// ============== 删除 ==============
|
|
239
|
+
export async function deleteIndex(indexName, home) {
|
|
240
|
+
const filePath = getIndexPath(indexName, home);
|
|
241
|
+
try {
|
|
242
|
+
await fs.unlink(filePath);
|
|
243
|
+
}
|
|
244
|
+
catch (e) {
|
|
245
|
+
if (e?.code !== 'ENOENT')
|
|
246
|
+
throw e;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const HIDE = '\x1b[?25l';
|
|
2
|
+
const SHOW = '\x1b[?25h';
|
|
3
|
+
const CLEAR = '\x1b[2K';
|
|
4
|
+
const CYAN = '\x1b[36m';
|
|
5
|
+
const YELLOW = '\x1b[33m';
|
|
6
|
+
const GREEN = '\x1b[32m';
|
|
7
|
+
const RED = '\x1b[31m';
|
|
8
|
+
const GRAY = '\x1b[90m';
|
|
9
|
+
const RESET = '\x1b[0m';
|
|
10
|
+
export class LoadingTUI {
|
|
11
|
+
write;
|
|
12
|
+
timer = null;
|
|
13
|
+
running = false;
|
|
14
|
+
constructor() {
|
|
15
|
+
this.write = process.stdout.write.bind(process.stdout);
|
|
16
|
+
}
|
|
17
|
+
start(msg = 'Bolloon loading...') {
|
|
18
|
+
this.running = true;
|
|
19
|
+
this.write(HIDE);
|
|
20
|
+
const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
21
|
+
let i = 0;
|
|
22
|
+
this.timer = setInterval(() => {
|
|
23
|
+
if (!this.running)
|
|
24
|
+
return;
|
|
25
|
+
this.write(`\r${CLEAR}\r ${YELLOW}${frames[i++ % frames.length]}${RESET} ${msg}`);
|
|
26
|
+
}, 100);
|
|
27
|
+
}
|
|
28
|
+
stop(ok = true) {
|
|
29
|
+
this.running = false;
|
|
30
|
+
if (this.timer)
|
|
31
|
+
clearInterval(this.timer);
|
|
32
|
+
this.timer = null;
|
|
33
|
+
this.write(`\r${CLEAR}\r`);
|
|
34
|
+
if (ok)
|
|
35
|
+
this.write(` ${GREEN}✓${RESET} ${CYAN}Bolloon${RESET} ${GRAY}ready${RESET}\n`);
|
|
36
|
+
else
|
|
37
|
+
this.write(` ${RED}✗${RESET} ${CYAN}Bolloon${RESET} ${GRAY}startup failed${RESET}\n`);
|
|
38
|
+
this.write(SHOW);
|
|
39
|
+
}
|
|
40
|
+
}
|
package/dist/cli-entry.js
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import { spawn } from 'child_process';
|
|
14
14
|
import * as path from 'path';
|
|
15
15
|
import * as fs from 'fs';
|
|
16
|
+
import { fileURLToPath } from 'url';
|
|
16
17
|
const isWindows = process.platform === 'win32';
|
|
17
18
|
// ANSI 颜色
|
|
18
19
|
const RESET = '\x1b[0m';
|
|
@@ -21,53 +22,56 @@ const CYAN = '\x1b[36m';
|
|
|
21
22
|
const YELLOW = '\x1b[33m';
|
|
22
23
|
const GREEN = '\x1b[32m';
|
|
23
24
|
const MAGENTA = '\x1b[35m';
|
|
24
|
-
// 版本信息
|
|
25
|
-
const VERSION = '0.
|
|
25
|
+
// 版本信息 — 与 package.json:version 同步, 否则 banner 会显示过时版本误导用户
|
|
26
|
+
const VERSION = '0.2.13';
|
|
26
27
|
function log(msg, color = RESET) {
|
|
27
28
|
console.log(`${color}${msg}${RESET}`);
|
|
28
29
|
}
|
|
29
30
|
function printBanner() {
|
|
30
|
-
console.log(`
|
|
31
|
-
${CYAN}${BOLD}
|
|
32
|
-
╔═══════════════════════════════════════════╗
|
|
33
|
-
║ 🤖 Bolloon Agent ${VERSION} ║
|
|
34
|
-
║ P2P AI Document Processor ║
|
|
35
|
-
╚═══════════════════════════════════════════╝${RESET}
|
|
31
|
+
console.log(`
|
|
32
|
+
${CYAN}${BOLD}
|
|
33
|
+
╔═══════════════════════════════════════════╗
|
|
34
|
+
║ 🤖 Bolloon Agent ${VERSION} ║
|
|
35
|
+
║ P2P AI Document Processor ║
|
|
36
|
+
╚═══════════════════════════════════════════╝${RESET}
|
|
36
37
|
`);
|
|
37
38
|
}
|
|
38
39
|
function printHelp() {
|
|
39
|
-
console.log(`
|
|
40
|
-
${BOLD}用法:${RESET}
|
|
41
|
-
bolloon [选项] [命令] [参数]
|
|
42
|
-
|
|
43
|
-
${BOLD}选项:${RESET}
|
|
44
|
-
--gui, -g 启动图形界面 (Electron)
|
|
45
|
-
--web, -w 启动 Web UI (浏览器)
|
|
46
|
-
--cli, -c 启动命令行界面
|
|
47
|
-
--version, -v 显示版本信息
|
|
48
|
-
--help, -h 显示帮助信息
|
|
49
|
-
|
|
50
|
-
${BOLD}命令:${RESET}
|
|
51
|
-
bolloon --read <file> 读取文档
|
|
52
|
-
bolloon --summarize <file> 总结文档
|
|
53
|
-
bolloon --improve <file> <req> 改进文档
|
|
54
|
-
|
|
55
|
-
${BOLD}示例:${RESET}
|
|
56
|
-
bolloon # 启动图形界面
|
|
57
|
-
bolloon --web # 启动 Web UI
|
|
58
|
-
bolloon --read 想法.md # 读取文档
|
|
59
|
-
bolloon --cli # 命令行模式
|
|
60
|
-
|
|
61
|
-
${BOLD}环境变量:${RESET}
|
|
62
|
-
MINIMAX_API_KEY MiniMax API 密钥
|
|
63
|
-
OPENAI_API_KEY OpenAI API 密钥
|
|
64
|
-
ANTHROPIC_API_KEY Anthropic API 密钥
|
|
65
|
-
PORT Web 服务端口 (默认 54188)
|
|
40
|
+
console.log(`
|
|
41
|
+
${BOLD}用法:${RESET}
|
|
42
|
+
bolloon [选项] [命令] [参数]
|
|
43
|
+
|
|
44
|
+
${BOLD}选项:${RESET}
|
|
45
|
+
--gui, -g 启动图形界面 (Electron)
|
|
46
|
+
--web, -w 启动 Web UI (浏览器)
|
|
47
|
+
--cli, -c 启动命令行界面
|
|
48
|
+
--version, -v 显示版本信息
|
|
49
|
+
--help, -h 显示帮助信息
|
|
50
|
+
|
|
51
|
+
${BOLD}命令:${RESET}
|
|
52
|
+
bolloon --read <file> 读取文档
|
|
53
|
+
bolloon --summarize <file> 总结文档
|
|
54
|
+
bolloon --improve <file> <req> 改进文档
|
|
55
|
+
|
|
56
|
+
${BOLD}示例:${RESET}
|
|
57
|
+
bolloon # 启动图形界面
|
|
58
|
+
bolloon --web # 启动 Web UI
|
|
59
|
+
bolloon --read 想法.md # 读取文档
|
|
60
|
+
bolloon --cli # 命令行模式
|
|
61
|
+
|
|
62
|
+
${BOLD}环境变量:${RESET}
|
|
63
|
+
MINIMAX_API_KEY MiniMax API 密钥
|
|
64
|
+
OPENAI_API_KEY OpenAI API 密钥
|
|
65
|
+
ANTHROPIC_API_KEY Anthropic API 密钥
|
|
66
|
+
PORT Web 服务端口 (默认 54188)
|
|
66
67
|
`);
|
|
67
68
|
}
|
|
68
69
|
function getDistDir() {
|
|
69
|
-
//
|
|
70
|
-
|
|
70
|
+
// 2026-07-01: ESM 模块无 __dirname, 用 import.meta.url + path.dirname 拿当前文件所在目录.
|
|
71
|
+
// 对于打包后的应用, 这是 dist 目录; 对于 tsx 跑 src/index.ts 时, 是 src/ 目录
|
|
72
|
+
// (后续 getMainScript 会优先用 dist/cli-entry.js, 不依赖这里的返回值)
|
|
73
|
+
const __filename_esm = fileURLToPath(import.meta.url);
|
|
74
|
+
return path.dirname(__filename_esm);
|
|
71
75
|
}
|
|
72
76
|
function getMainScript() {
|
|
73
77
|
const distDir = getDistDir();
|
|
@@ -45,13 +45,13 @@ async function writeCache(scope, key, summary) {
|
|
|
45
45
|
console.warn('[compactor] cache write failed (silent):', err);
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
-
const SUMMARIZE_SYSTEM = `你是一个对话历史压缩助手.
|
|
49
|
-
你的任务: 把给定的对话历史压缩成 1-2 句话的摘要, 保留所有出现过的 tool names.
|
|
50
|
-
要求:
|
|
51
|
-
- 保留所有用户的关键需求
|
|
52
|
-
- 保留所有调用过的 tool names (例如 read_file, shell_exec, use_skill 等)
|
|
53
|
-
- 保留关键决策和发现
|
|
54
|
-
- 不要添加原对话中没有的信息
|
|
48
|
+
const SUMMARIZE_SYSTEM = `你是一个对话历史压缩助手.
|
|
49
|
+
你的任务: 把给定的对话历史压缩成 1-2 句话的摘要, 保留所有出现过的 tool names.
|
|
50
|
+
要求:
|
|
51
|
+
- 保留所有用户的关键需求
|
|
52
|
+
- 保留所有调用过的 tool names (例如 read_file, shell_exec, use_skill 等)
|
|
53
|
+
- 保留关键决策和发现
|
|
54
|
+
- 不要添加原对话中没有的信息
|
|
55
55
|
- 输出纯文本, 不要 JSON, 不要 markdown 标题`;
|
|
56
56
|
export async function autoCompact(history, opts = {}) {
|
|
57
57
|
try {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isDev = exports.MAIN_WINDOW_MIN = exports.MAIN_WINDOW_DEFAULT = exports.WEB_SERVER_STARTUP_TIMEOUT_MS = exports.DEFAULT_HOST = exports.DEFAULT_PORT = void 0;
|
|
4
|
+
exports.preferredPort = preferredPort;
|
|
5
|
+
/**
|
|
6
|
+
* 常量配置 (env 解析在这里集中, 不散在 main 流程)
|
|
7
|
+
*/
|
|
8
|
+
const electron_1 = require("electron");
|
|
9
|
+
exports.DEFAULT_PORT = 54188;
|
|
10
|
+
/** Hard-pin to loopback; LAN exposure must be explicit. */
|
|
11
|
+
exports.DEFAULT_HOST = '127.0.0.1';
|
|
12
|
+
exports.WEB_SERVER_STARTUP_TIMEOUT_MS = 15_000;
|
|
13
|
+
exports.MAIN_WINDOW_DEFAULT = { width: 1200, height: 800 };
|
|
14
|
+
exports.MAIN_WINDOW_MIN = { width: 800, height: 600 };
|
|
15
|
+
function preferredPort() {
|
|
16
|
+
const raw = process.env.ELECTRON_PORT || process.env.PORT;
|
|
17
|
+
const n = parseInt(raw || '', 10);
|
|
18
|
+
return Number.isFinite(n) && n > 0 && n < 65536 ? n : exports.DEFAULT_PORT;
|
|
19
|
+
}
|
|
20
|
+
exports.isDev = process.env.NODE_ENV === 'development' || !electron_1.app.isPackaged;
|
|
21
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/electron/config.ts"],"names":[],"mappings":";;;AAcA,sCAIC;AAlBD;;GAEG;AACH,uCAA+B;AAElB,QAAA,YAAY,GAAG,KAAK,CAAC;AAClC,2DAA2D;AAC9C,QAAA,YAAY,GAAG,WAAW,CAAC;AAE3B,QAAA,6BAA6B,GAAG,MAAM,CAAC;AAEvC,QAAA,mBAAmB,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;AACnD,QAAA,eAAe,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;AAE3D,SAAgB,aAAa;IAC3B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;IAC1D,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAClC,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,oBAAY,CAAC;AACrE,CAAC;AAEY,QAAA,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,IAAI,CAAC,cAAG,CAAC,UAAU,CAAC"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.registerDialogIpc = registerDialogIpc;
|
|
37
|
+
/**
|
|
38
|
+
* 文件 dialog 桥 (open / save / dir) + 安全的 fs 桥 (read / write / exists)
|
|
39
|
+
*
|
|
40
|
+
* 5MB read 上限保护 — 渲染进程直接 fs.readFile 没法做限制, 走主进程就有界
|
|
41
|
+
* 所有 handler 解析 event.sender 拿到 window, 让 dialog 模态在该窗口上
|
|
42
|
+
*/
|
|
43
|
+
const electron_1 = require("electron");
|
|
44
|
+
const fs = __importStar(require("fs"));
|
|
45
|
+
const path = __importStar(require("path"));
|
|
46
|
+
const logger_1 = require("./logger");
|
|
47
|
+
const MAX_READ_BYTES = 5 * 1024 * 1024; // 5MB
|
|
48
|
+
function windowFor(event) {
|
|
49
|
+
return electron_1.BrowserWindow.fromWebContents(event.sender);
|
|
50
|
+
}
|
|
51
|
+
function resolveSafe(target) {
|
|
52
|
+
// 不去硬限制路径 — user 给 renderer 暴露 fs 已经信任了, 这里只 normalize
|
|
53
|
+
return path.resolve(target);
|
|
54
|
+
}
|
|
55
|
+
function registerDialogIpc() {
|
|
56
|
+
electron_1.ipcMain.handle('dialog:open-file', async (event, opts = {}) => {
|
|
57
|
+
const win = windowFor(event);
|
|
58
|
+
const result = await electron_1.dialog.showOpenDialog(win, {
|
|
59
|
+
title: opts.title,
|
|
60
|
+
defaultPath: opts.defaultPath,
|
|
61
|
+
filters: opts.filters,
|
|
62
|
+
properties: opts.properties ?? ['openFile'],
|
|
63
|
+
});
|
|
64
|
+
return { canceled: result.canceled, filePaths: result.filePaths };
|
|
65
|
+
});
|
|
66
|
+
electron_1.ipcMain.handle('dialog:save-file', async (event, opts = {}) => {
|
|
67
|
+
const win = windowFor(event);
|
|
68
|
+
const result = await electron_1.dialog.showSaveDialog(win, {
|
|
69
|
+
title: opts.title,
|
|
70
|
+
defaultPath: opts.defaultPath,
|
|
71
|
+
filters: opts.filters,
|
|
72
|
+
});
|
|
73
|
+
return { canceled: result.canceled, filePath: result.filePath };
|
|
74
|
+
});
|
|
75
|
+
electron_1.ipcMain.handle('dialog:open-directory', async (event, opts = {}) => {
|
|
76
|
+
const win = windowFor(event);
|
|
77
|
+
const result = await electron_1.dialog.showOpenDialog(win, {
|
|
78
|
+
title: opts.title,
|
|
79
|
+
defaultPath: opts.defaultPath,
|
|
80
|
+
properties: ['openDirectory', 'createDirectory'],
|
|
81
|
+
});
|
|
82
|
+
return { canceled: result.canceled, filePaths: result.filePaths };
|
|
83
|
+
});
|
|
84
|
+
electron_1.ipcMain.handle('fs:read-text-file', async (_event, opts) => {
|
|
85
|
+
const target = resolveSafe(opts.path);
|
|
86
|
+
const stat = fs.statSync(target);
|
|
87
|
+
if (stat.size > MAX_READ_BYTES) {
|
|
88
|
+
throw new Error(`文件过大: ${stat.size} > ${MAX_READ_BYTES} bytes`);
|
|
89
|
+
}
|
|
90
|
+
return fs.readFileSync(target, { encoding: opts.encoding ?? 'utf8' });
|
|
91
|
+
});
|
|
92
|
+
electron_1.ipcMain.handle('fs:write-text-file', async (_event, opts) => {
|
|
93
|
+
const target = resolveSafe(opts.path);
|
|
94
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
95
|
+
fs.writeFileSync(target, opts.content, { encoding: opts.encoding ?? 'utf8' });
|
|
96
|
+
});
|
|
97
|
+
electron_1.ipcMain.handle('fs:path-exists', async (_event, opts) => {
|
|
98
|
+
try {
|
|
99
|
+
fs.accessSync(resolveSafe(opts.path));
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
(0, logger_1.log)('dialog + fs IPC handlers registered');
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=dialogs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dialogs.js","sourceRoot":"","sources":["../../src/electron/dialogs.ts"],"names":[],"mappings":"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"}
|