@bolloon/bolloon-agent 0.3.35 → 0.3.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/pi-sdk-tools.js +2 -1
- package/dist/cli/ink-app.js +44 -1
- package/dist/cli/mention-data.js +23 -0
- package/dist/cli-entry.js +113 -6
- package/dist/electron/config.js +9 -14
- package/dist/electron/dialogs.js +16 -53
- package/dist/electron/first-run.js +24 -65
- package/dist/electron/ipc.js +10 -14
- package/dist/electron/logger.js +7 -44
- package/dist/electron/main.js +42 -45
- package/dist/electron/menu.js +13 -18
- package/dist/electron/paths.js +12 -54
- package/dist/electron/server.js +18 -57
- package/dist/electron/tray.js +15 -53
- package/dist/electron/window.js +22 -61
- package/dist/electron-build/electron/config.js +21 -0
- package/dist/electron-build/electron/config.js.map +1 -0
- package/dist/electron-build/electron/dialogs.js +108 -0
- package/dist/electron-build/electron/dialogs.js.map +1 -0
- package/dist/electron-build/electron/first-run.js +170 -0
- package/dist/electron-build/electron/first-run.js.map +1 -0
- package/dist/electron-build/electron/ipc.js +20 -0
- package/dist/electron-build/electron/ipc.js.map +1 -0
- package/dist/electron-build/electron/logger.js +114 -0
- package/dist/electron-build/electron/logger.js.map +1 -0
- package/dist/electron-build/electron/main.js +79 -0
- package/dist/electron-build/electron/main.js.map +1 -0
- package/dist/electron-build/electron/menu.js +145 -0
- package/dist/electron-build/electron/menu.js.map +1 -0
- package/dist/electron-build/electron/paths.js +75 -0
- package/dist/electron-build/electron/paths.js.map +1 -0
- package/dist/electron-build/electron/server.js +119 -0
- package/dist/electron-build/electron/server.js.map +1 -0
- package/dist/electron-build/electron/tray.js +111 -0
- package/dist/electron-build/electron/tray.js.map +1 -0
- package/dist/electron-build/electron/window.js +111 -0
- package/dist/electron-build/electron/window.js.map +1 -0
- package/dist/electron-build/electron-preload.js +32 -0
- package/dist/electron-build/electron-preload.js.map +1 -0
- package/dist/electron-build/electron.js +8 -0
- package/dist/electron-build/electron.js.map +1 -0
- package/dist/electron-build/utils/auto-update.js +598 -0
- package/dist/electron-build/utils/auto-update.js.map +1 -0
- package/dist/electron-preload.js +16 -19
- package/dist/electron.js +1 -4
- package/dist/index.js +426 -0
- package/dist/utils/auto-update.js +12 -51
- package/package.json +5 -4
package/dist/electron.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
1
|
/**
|
|
4
2
|
* Electron 入口 shim — 真正逻辑在 src/electron/main.ts
|
|
5
3
|
* (保留 src/electron.ts 平铺入口, 不动 package.json 的 dist/electron.js 解析)
|
|
6
4
|
*/
|
|
7
|
-
|
|
8
|
-
//# sourceMappingURL=electron.js.map
|
|
5
|
+
import './electron/main';
|
package/dist/index.js
CHANGED
|
@@ -581,12 +581,438 @@ async function processInput(input, comm) {
|
|
|
581
581
|
appendLine(`${C_WARN}[队列 ${pendingQueue.length}]${RESET} 已入队, 执行完当前后自动运行`);
|
|
582
582
|
return;
|
|
583
583
|
}
|
|
584
|
+
// ==================== 2026-08-06: 系统命令组 (/model /now /ipfs /memory ...) ====================
|
|
585
|
+
const cmd = trimmed.toLowerCase();
|
|
586
|
+
// /model /login — 模型供应商选择器 (ink 交互渲染, 复用 MentionPopup)
|
|
587
|
+
if (cmd === '/model' || cmd === '/login') {
|
|
588
|
+
try {
|
|
589
|
+
const { llmConfigStore, PROVIDER_INFO } = await import('./llm/config-store.js');
|
|
590
|
+
await llmConfigStore.initialize();
|
|
591
|
+
const config = await llmConfigStore.getConfig();
|
|
592
|
+
const items = Object.entries(config.providers).map(([name, p]) => ({
|
|
593
|
+
kind: 'command',
|
|
594
|
+
label: name,
|
|
595
|
+
hint: `${String(PROVIDER_INFO[name]?.name || '').padEnd(14)} ${p.apiKey ? '🔑' : p.requiresApiKey ? '⚠ 无key' : ''} ${p.model || ''}`,
|
|
596
|
+
insert: name,
|
|
597
|
+
}));
|
|
598
|
+
globalThis.__inkOpenPicker?.(items, '选择模型供应商 (↑↓ 选择 · Enter 确认 · Esc 取消)', async (it) => {
|
|
599
|
+
try {
|
|
600
|
+
await llmConfigStore.setActiveProvider(it.label);
|
|
601
|
+
const active = await llmConfigStore.getActiveProvider();
|
|
602
|
+
appendLine(`${C_OK}✓ 已切换到 ${it.label} (${String(PROVIDER_INFO[it.label]?.name || '')})${RESET}`);
|
|
603
|
+
appendLine(`${C_DIM} 当前模型: ${config.providers[it.label]?.model || '默认'}${RESET}`);
|
|
604
|
+
}
|
|
605
|
+
catch (e) {
|
|
606
|
+
appendLine(`${C_ERROR}✗ 切换失败: ${String(e.message || e).slice(0, 150)}${RESET}`);
|
|
607
|
+
}
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
catch (e) {
|
|
611
|
+
appendLine(`${C_ERROR}/model 失败: ${String(e.message || e).slice(0, 150)}${RESET}`);
|
|
612
|
+
}
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
// /logout — 显示当前供应商 (减法: 登出 = 查看当前, 切换走 /model)
|
|
616
|
+
if (cmd === '/logout') {
|
|
617
|
+
try {
|
|
618
|
+
const { llmConfigStore, PROVIDER_INFO } = await import('./llm/config-store.js');
|
|
619
|
+
await llmConfigStore.initialize();
|
|
620
|
+
const active = await llmConfigStore.getActiveProvider();
|
|
621
|
+
const cfg = await llmConfigStore.getActiveProviderConfig();
|
|
622
|
+
appendLine(`${C_DIM}当前供应商:${RESET} ${C_ACCENT}${active}${RESET} (${String(PROVIDER_INFO[active]?.name || '')})`);
|
|
623
|
+
appendLine(`${C_DIM} 模型: ${cfg?.model || '默认'}${RESET}`);
|
|
624
|
+
appendLine(`${C_DIM} 切换: /model 打开选择器${RESET}`);
|
|
625
|
+
}
|
|
626
|
+
catch { /* 静默 */ }
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
// /now — 当前状态总览
|
|
630
|
+
if (cmd === '/now') {
|
|
631
|
+
try {
|
|
632
|
+
const cm = require('./bootstrap/context-manager.js').getContextManager();
|
|
633
|
+
const usage = cm.getUsage();
|
|
634
|
+
appendLine(`${C_ACCENT}● 当前状态${RESET}`);
|
|
635
|
+
appendLine(` ${C_DIM}智能体:${RESET} ${cliAgentName} ${cliActiveChannelId ? `(${C_DIM}ch:${cliActiveChannelId.slice(0, 12)}${RESET})` : ''}`);
|
|
636
|
+
appendLine(` ${C_DIM}运行:${RESET} ${fmtDuration(Date.now() - cliStartTime)}`);
|
|
637
|
+
appendLine(` ${C_DIM}上下文:${RESET} ${(usage.usedTokens / 1000).toFixed(0)}k / ${(usage.maxTokens / 1000).toFixed(0)}k tokens (${Math.round(usage.pct * 100)}%)${usage.stage === 'warning' ? ` ${C_WARN}⚠ 即将压缩${RESET}` : ''}`);
|
|
638
|
+
const a = await getAgent();
|
|
639
|
+
appendLine(` ${C_DIM}消息:${RESET} ${a.messageHistory?.length ?? 0} 条`);
|
|
640
|
+
}
|
|
641
|
+
catch { /* 静默 */ }
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
// /tools — 可用工具列表
|
|
645
|
+
if (cmd === '/tools') {
|
|
646
|
+
try {
|
|
647
|
+
const a = await getAgent();
|
|
648
|
+
const defs = (a.getToolDefinitions?.() ?? []);
|
|
649
|
+
const names = Array.isArray(defs) ? defs.map((d) => d.name || d.function?.name).filter(Boolean) : Object.keys(defs || {});
|
|
650
|
+
appendLine(`${C_ACCENT}可用工具 (${names.length}):${RESET}`);
|
|
651
|
+
for (const n of names.slice(0, 40))
|
|
652
|
+
appendLine(` ${C_DIM}·${RESET} ${n}`);
|
|
653
|
+
if (names.length > 40)
|
|
654
|
+
appendLine(` ${C_DIM}... 共 ${names.length} 个${RESET}`);
|
|
655
|
+
}
|
|
656
|
+
catch { /* 静默 */ }
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
// /session — 当前会话信息
|
|
660
|
+
if (cmd === '/session') {
|
|
661
|
+
try {
|
|
662
|
+
const a = await getAgent();
|
|
663
|
+
const h = a.messageHistory ?? [];
|
|
664
|
+
appendLine(`${C_ACCENT}会话:${RESET}`);
|
|
665
|
+
appendLine(` ${C_DIM}channel:${RESET} ${a.currentChannelId || '—'}`);
|
|
666
|
+
appendLine(` ${C_DIM}agent:${RESET} ${a.currentAgentId || '—'}`);
|
|
667
|
+
appendLine(` ${C_DIM}消息:${RESET} ${h.length} 条 (${h.length > 15 ? `${h.length - 15} 条已压缩` : '窗口内'})`);
|
|
668
|
+
}
|
|
669
|
+
catch { /* 静默 */ }
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
// /memory — 记忆摘要 (memory-compressor 落盘文件)
|
|
673
|
+
if (cmd === '/memory') {
|
|
674
|
+
try {
|
|
675
|
+
const { getMemoryDir } = await import('./bootstrap/memory-compressor.js');
|
|
676
|
+
const { readdir, readFile } = await import('fs/promises');
|
|
677
|
+
const { join } = await import('path');
|
|
678
|
+
const dir = getMemoryDir(cliAgentName === 'bolloon' ? 'agent' : cliAgentName);
|
|
679
|
+
const files = (await readdir(join(dir, 'sessions')).catch(() => [])).filter((f) => f.endsWith('.summary.md'));
|
|
680
|
+
appendLine(`${C_ACCENT}记忆摘要 (${files.length} 个 session):${RESET}`);
|
|
681
|
+
for (const f of files.slice(-5)) {
|
|
682
|
+
try {
|
|
683
|
+
const raw = await readFile(join(dir, 'sessions', f), 'utf-8');
|
|
684
|
+
const tail = raw.trim().split('\n').slice(-6).join(' ').slice(0, 180);
|
|
685
|
+
appendLine(` ${C_DIM}·${RESET} ${f.replace('.summary.md', '').slice(-30)}`);
|
|
686
|
+
appendLine(` ${C_DIM}${tail}${RESET}`);
|
|
687
|
+
}
|
|
688
|
+
catch { /* 跳过 */ }
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
catch { /* 静默 */ }
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
// /resume — 恢复: 最近记忆摘要 + 进行中计划
|
|
695
|
+
if (cmd === '/resume' || cmd.startsWith('/resume ')) {
|
|
696
|
+
try {
|
|
697
|
+
const { getMemoryDir, getSessionSummaryPath } = await import('./bootstrap/memory-compressor.js');
|
|
698
|
+
const { readFile, readdir } = await import('fs/promises');
|
|
699
|
+
const { join } = await import('path');
|
|
700
|
+
const dir = getMemoryDir(cliAgentName === 'bolloon' ? 'agent' : cliAgentName);
|
|
701
|
+
const files = (await readdir(join(dir, 'sessions')).catch(() => [])).filter((f) => f.endsWith('.summary.md'));
|
|
702
|
+
appendLine(`${C_ACCENT}↻ 恢复上下文:${RESET}`);
|
|
703
|
+
if (files.length > 0) {
|
|
704
|
+
const f = files[files.length - 1];
|
|
705
|
+
const raw = await readFile(join(dir, 'sessions', f), 'utf-8');
|
|
706
|
+
const block = raw.trim().split('\n').slice(-12).join('\n').slice(-1200);
|
|
707
|
+
appendLine(` ${C_DIM}最近记忆 (${f.slice(0, 24)}...):${RESET}`);
|
|
708
|
+
for (const line of block.split('\n').slice(-8))
|
|
709
|
+
appendLine(` ${C_DIM}${line.slice(0, 100)}${RESET}`);
|
|
710
|
+
}
|
|
711
|
+
else {
|
|
712
|
+
appendLine(` ${C_DIM}暂无记忆摘要${RESET}`);
|
|
713
|
+
}
|
|
714
|
+
const { listActivePlans } = await import('./agents/plan-store.js');
|
|
715
|
+
const plans = await listActivePlans();
|
|
716
|
+
if (plans.length > 0) {
|
|
717
|
+
appendLine(` ${C_DIM}进行中计划 (${plans.length}):${RESET}`);
|
|
718
|
+
for (const p of plans.slice(0, 3))
|
|
719
|
+
appendLine(` ${C_ACCENT}·${RESET} ${p.goal || p.planId} ${C_DIM}${p.status || ''}${RESET}`);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
catch { /* 静默 */ }
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
// /goal — 进行中的目标/计划
|
|
726
|
+
if (cmd === '/goal') {
|
|
727
|
+
try {
|
|
728
|
+
const { listActivePlans, planToContext } = await import('./agents/plan-store.js');
|
|
729
|
+
const plans = await listActivePlans();
|
|
730
|
+
appendLine(`${C_ACCENT}目标 (${plans.length} 个进行中):${RESET}`);
|
|
731
|
+
if (plans.length === 0) {
|
|
732
|
+
appendLine(` ${C_DIM}无进行中计划 — 可用 /plan 创建${RESET}`);
|
|
733
|
+
}
|
|
734
|
+
for (const p of plans.slice(0, 5)) {
|
|
735
|
+
appendLine(` ${C_ACCENT}●${RESET} ${p.goal || p.planId} ${C_DIM}[${p.status || 'active'}]${RESET}`);
|
|
736
|
+
const steps = Array.isArray(p.steps) ? p.steps : [];
|
|
737
|
+
const done = steps.filter((s) => s.done || s.status === 'done').length;
|
|
738
|
+
if (steps.length > 0)
|
|
739
|
+
appendLine(` ${C_DIM}${done}/${steps.length} 步完成${RESET}`);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
catch { /* 静默 */ }
|
|
743
|
+
return;
|
|
744
|
+
}
|
|
745
|
+
// /skill — 技能候选 (skill-writer 落盘)
|
|
746
|
+
if (cmd === '/skill') {
|
|
747
|
+
try {
|
|
748
|
+
const { listSkillCandidates } = await import('./agents/skill-writer.js');
|
|
749
|
+
const cands = await listSkillCandidates();
|
|
750
|
+
appendLine(`${C_ACCENT}技能候选 (${cands.length}):${RESET}`);
|
|
751
|
+
if (cands.length === 0) {
|
|
752
|
+
appendLine(` ${C_DIM}无候选 — 连续成功工具调用 ≥2 自动生成${RESET}`);
|
|
753
|
+
}
|
|
754
|
+
for (const c of cands.slice(0, 8)) {
|
|
755
|
+
appendLine(` ${C_DIM}·${RESET} ${c.name || '?'} ${C_DIM}(${c.source || ''})${RESET}`);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
catch { /* 静默 */ }
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
// /mcp — MCP 插件/工具列表
|
|
762
|
+
if (cmd === '/mcp') {
|
|
763
|
+
try {
|
|
764
|
+
const { readFile } = await import('fs/promises');
|
|
765
|
+
const { join } = await import('path');
|
|
766
|
+
let servers = {};
|
|
767
|
+
try {
|
|
768
|
+
servers = JSON.parse(await readFile(join(process.env.HOME || '/tmp', '.mcp.json'), 'utf-8')).mcpServers || {};
|
|
769
|
+
}
|
|
770
|
+
catch { /* 无 */ }
|
|
771
|
+
appendLine(`${C_ACCENT}MCP 服务器 (${Object.keys(servers).length}):${RESET}`);
|
|
772
|
+
if (Object.keys(servers).length === 0) {
|
|
773
|
+
appendLine(` ${C_DIM}无 (~/.mcp.json 未配置)${RESET}`);
|
|
774
|
+
}
|
|
775
|
+
for (const [name, s] of Object.entries(servers)) {
|
|
776
|
+
const cmdStr = s?.command || '';
|
|
777
|
+
appendLine(` ${C_DIM}·${RESET} ${name} ${C_DIM}(${String(cmdStr).slice(0, 40)})${RESET}`);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
catch { /* 静默 */ }
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
783
|
+
// /agent — 当前智能体身份
|
|
784
|
+
if (cmd === '/agent') {
|
|
785
|
+
try {
|
|
786
|
+
const a = await getAgent();
|
|
787
|
+
appendLine(`${C_ACCENT}智能体:${RESET}`);
|
|
788
|
+
appendLine(` ${C_DIM}名称:${RESET} ${cliAgentName}`);
|
|
789
|
+
appendLine(` ${C_DIM}agentId:${RESET} ${a.currentAgentId || '—'}`);
|
|
790
|
+
appendLine(` ${C_DIM}channel:${RESET} ${cliActiveChannelId || '—'}`);
|
|
791
|
+
}
|
|
792
|
+
catch { /* 静默 */ }
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
795
|
+
// /did — DID 身份
|
|
796
|
+
if (cmd === '/did') {
|
|
797
|
+
try {
|
|
798
|
+
const { loadOrCreateAgentIdentity } = await import('./agents/agent-identity.js');
|
|
799
|
+
const identity = loadOrCreateAgentIdentity(cliAgentName === 'bolloon' ? 'default-agent' : cliAgentName);
|
|
800
|
+
appendLine(`${C_ACCENT}DID 身份:${RESET}`);
|
|
801
|
+
appendLine(` ${C_DIM}did:${RESET} ${identity.did}`);
|
|
802
|
+
appendLine(` ${C_DIM}publicKey:${RESET} ${identity.publicKey?.slice(0, 32) || '—'}...`);
|
|
803
|
+
appendLine(` ${C_DIM}发布:${RESET} 可用 publish_did 工具发布到 IPFS+IPNS`);
|
|
804
|
+
}
|
|
805
|
+
catch (e) {
|
|
806
|
+
appendLine(`${C_ERROR}/did 失败: ${String(e.message || e).slice(0, 120)}${RESET}`);
|
|
807
|
+
}
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
// /ipfs — Kubo 状态
|
|
811
|
+
if (cmd === '/ipfs') {
|
|
812
|
+
try {
|
|
813
|
+
const { kuboApi } = await import('./agents/pi-sdk-tools.js');
|
|
814
|
+
const id = await kuboApi('/api/v0/id');
|
|
815
|
+
const peers = await kuboApi('/api/v0/swarm/peers');
|
|
816
|
+
const pins = await kuboApi('/api/v0/pin/ls?type=recursive');
|
|
817
|
+
appendLine(`${C_ACCENT}IPFS (Kubo):${RESET}`);
|
|
818
|
+
appendLine(` ${C_DIM}节点:${RESET} ${String(id.ID || '').slice(0, 24)}...`);
|
|
819
|
+
appendLine(` ${C_DIM}版本:${RESET} ${id.AgentVersion || ''}`);
|
|
820
|
+
appendLine(` ${C_DIM}peers:${RESET} ${peers?.Peers?.length ?? 0}`);
|
|
821
|
+
appendLine(` ${C_DIM}pins:${RESET} ${pins?.Keys ? Object.keys(pins.Keys).length : 0}`);
|
|
822
|
+
}
|
|
823
|
+
catch (e) {
|
|
824
|
+
appendLine(`${C_ERROR}/ipfs 失败: ${String(e.message || e).slice(0, 120)}${RESET}`);
|
|
825
|
+
}
|
|
826
|
+
return;
|
|
827
|
+
}
|
|
828
|
+
// /ipns — IPNS 状态 (keys + self 解析)
|
|
829
|
+
if (cmd === '/ipns') {
|
|
830
|
+
try {
|
|
831
|
+
const { kuboApi } = await import('./agents/pi-sdk-tools.js');
|
|
832
|
+
const keys = await kuboApi('/api/v0/key/list');
|
|
833
|
+
const keyList = keys?.Keys || [];
|
|
834
|
+
appendLine(`${C_ACCENT}IPNS keys (${keyList.length}):${RESET}`);
|
|
835
|
+
for (const k of keyList.slice(0, 10)) {
|
|
836
|
+
appendLine(` ${C_DIM}·${RESET} ${k.Name} ${C_DIM}${String(k.Id).slice(0, 20)}...${RESET}`);
|
|
837
|
+
}
|
|
838
|
+
try {
|
|
839
|
+
const r = await kuboApi('/api/v0/name/resolve?arg=ui-deploy&recursive=true&nocache=true', undefined, 15000);
|
|
840
|
+
appendLine(` ${C_DIM}ui-deploy →${RESET} ${r.Path || ''}`);
|
|
841
|
+
}
|
|
842
|
+
catch { /* 无 ui-deploy */ }
|
|
843
|
+
}
|
|
844
|
+
catch (e) {
|
|
845
|
+
appendLine(`${C_ERROR}/ipns 失败: ${String(e.message || e).slice(0, 120)}${RESET}`);
|
|
846
|
+
}
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
// /wallet — 钱包状态
|
|
850
|
+
if (cmd === '/wallet') {
|
|
851
|
+
try {
|
|
852
|
+
const { readFile } = await import('fs/promises');
|
|
853
|
+
const { join } = await import('path');
|
|
854
|
+
let wallets = [];
|
|
855
|
+
try {
|
|
856
|
+
wallets = JSON.parse(await readFile(join(process.env.HOME || '/tmp', '.bolloon', 'wallets.json'), 'utf-8'));
|
|
857
|
+
}
|
|
858
|
+
catch { /* 无 */ }
|
|
859
|
+
appendLine(`${C_ACCENT}钱包 (${Array.isArray(wallets) ? wallets.length : 0}):${RESET}`);
|
|
860
|
+
if (!Array.isArray(wallets) || wallets.length === 0) {
|
|
861
|
+
appendLine(` ${C_DIM}无 — 可用 wallet_create 工具创建 EVM 钱包${RESET}`);
|
|
862
|
+
}
|
|
863
|
+
for (const w of (Array.isArray(wallets) ? wallets : []).slice(0, 5)) {
|
|
864
|
+
appendLine(` ${C_DIM}·${RESET} ${w.name || w.address?.slice(0, 12) || '?'} ${C_DIM}${String(w.address || '').slice(0, 16)}...${RESET}`);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
catch { /* 静默 */ }
|
|
868
|
+
return;
|
|
869
|
+
}
|
|
870
|
+
// /email — 邮件配置状态
|
|
871
|
+
if (cmd === '/email') {
|
|
872
|
+
try {
|
|
873
|
+
const { readFile } = await import('fs/promises');
|
|
874
|
+
const { join } = await import('path');
|
|
875
|
+
let cfg = null;
|
|
876
|
+
try {
|
|
877
|
+
cfg = JSON.parse(await readFile(join(process.env.HOME || '/tmp', '.bolloon', 'smtp.json'), 'utf-8'));
|
|
878
|
+
}
|
|
879
|
+
catch { /* 无 */ }
|
|
880
|
+
appendLine(`${C_ACCENT}邮件 (SMTP):${RESET}`);
|
|
881
|
+
if (!cfg) {
|
|
882
|
+
appendLine(` ${C_DIM}未配置 smtp.json — 发件人: 天墟星剑 <2844169590@qq.com>${RESET}`);
|
|
883
|
+
}
|
|
884
|
+
else {
|
|
885
|
+
appendLine(` ${C_DIM}host:${RESET} ${cfg.host || 'smtp.qq.com'}`);
|
|
886
|
+
appendLine(` ${C_DIM}发件人:${RESET} ${cfg.from || cfg.user || '—'}`);
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
catch { /* 静默 */ }
|
|
890
|
+
return;
|
|
891
|
+
}
|
|
892
|
+
// /loop — 当前循环状态 (消息数 + token 估算)
|
|
893
|
+
if (cmd === '/loop') {
|
|
894
|
+
try {
|
|
895
|
+
const a = await getAgent();
|
|
896
|
+
const h = a.messageHistory ?? [];
|
|
897
|
+
let tokens = 0;
|
|
898
|
+
try {
|
|
899
|
+
const { estimateTokens } = require('./context-compaction/index.js');
|
|
900
|
+
tokens = estimateTokens(h);
|
|
901
|
+
}
|
|
902
|
+
catch {
|
|
903
|
+
tokens = Math.round(JSON.stringify(h).length / 4);
|
|
904
|
+
}
|
|
905
|
+
appendLine(`${C_ACCENT}Loop 状态:${RESET}`);
|
|
906
|
+
appendLine(` ${C_DIM}消息:${RESET} ${h.length} 条 (窗口 15, ${Math.max(0, h.length - 15)} 条早期压缩)`);
|
|
907
|
+
appendLine(` ${C_DIM}token:${RESET} ${(tokens / 1000).toFixed(1)}k / 1M (${((tokens / 1_000_000) * 100).toFixed(2)}%)`);
|
|
908
|
+
}
|
|
909
|
+
catch { /* 静默 */ }
|
|
910
|
+
return;
|
|
911
|
+
}
|
|
912
|
+
// /judgement — 判断力列表
|
|
913
|
+
if (cmd === '/judgement' || cmd === '/judgments') {
|
|
914
|
+
try {
|
|
915
|
+
const { loadAllJudgments } = await import('./pi-ecosystem-judgment/human-value-store.js');
|
|
916
|
+
const all = await loadAllJudgments().catch(() => []);
|
|
917
|
+
appendLine(`${C_ACCENT}判断力 (${all.length} 条):${RESET}`);
|
|
918
|
+
for (const j of all.slice(0, 8)) {
|
|
919
|
+
appendLine(` ${C_DIM}·${RESET} ${String(j.decision || '').slice(0, 70)}`);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
catch { /* 静默 */ }
|
|
923
|
+
return;
|
|
924
|
+
}
|
|
925
|
+
// /insight — Context OS 08-Insights 资产
|
|
926
|
+
if (cmd === '/insight') {
|
|
927
|
+
try {
|
|
928
|
+
const { readContextAssets, readAssetBody } = await import('./bootstrap/context-os.js');
|
|
929
|
+
const listings = await readContextAssets('08-Insights');
|
|
930
|
+
const files = listings[0]?.files || [];
|
|
931
|
+
appendLine(`${C_ACCENT}洞察 (${files.length} 篇):${RESET}`);
|
|
932
|
+
if (files.length === 0) {
|
|
933
|
+
appendLine(` ${C_DIM}无 — 价值点路由自动沉淀 insight 到 08-Insights${RESET}`);
|
|
934
|
+
}
|
|
935
|
+
for (const f of files.slice(0, 6)) {
|
|
936
|
+
const body = await readAssetBody('08-Insights', f.file).catch(() => null);
|
|
937
|
+
const firstLine = (body?.body || '').split('\n').filter(l => l.trim() && !l.startsWith('---')).slice(0, 2).join(' ').slice(0, 90);
|
|
938
|
+
appendLine(` ${C_ACCENT}·${RESET} ${f.title} ${C_DIM}${firstLine ? '— ' + firstLine : ''}${RESET}`);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
catch { /* 静默 */ }
|
|
942
|
+
return;
|
|
943
|
+
}
|
|
944
|
+
// /wiki — wiki 状态
|
|
945
|
+
if (cmd === '/wiki') {
|
|
946
|
+
try {
|
|
947
|
+
const { readFile } = await import('fs/promises');
|
|
948
|
+
const { join } = await import('path');
|
|
949
|
+
const root = process.cwd();
|
|
950
|
+
const statusPath = join(root, 'docs', 'wiki', 'current-status.md');
|
|
951
|
+
const raw = await readFile(statusPath, 'utf-8');
|
|
952
|
+
const title = raw.match(/^title:\s*(.+)$/m)?.[1] || 'current-status';
|
|
953
|
+
const confirmed = raw.match(/^last_confirmed:\s*(.+)$/m)?.[1] || '?';
|
|
954
|
+
const supported = (raw.match(/\|\|+/g) || []).length;
|
|
955
|
+
appendLine(`${C_ACCENT}Wiki:${RESET} ${title}`);
|
|
956
|
+
appendLine(` ${C_DIM}last_confirmed:${RESET} ${confirmed}`);
|
|
957
|
+
appendLine(` ${C_DIM}已支持条目:${RESET} ${supported}`);
|
|
958
|
+
appendLine(` ${C_DIM}位置:${RESET} docs/wiki/ (wiki-first 范式)`);
|
|
959
|
+
}
|
|
960
|
+
catch { /* 静默 */ }
|
|
961
|
+
return;
|
|
962
|
+
}
|
|
963
|
+
// /dream — 随机灵感 (从 Insights + Knowledge 资产随机取一条)
|
|
964
|
+
if (cmd === '/dream') {
|
|
965
|
+
try {
|
|
966
|
+
const { readContextAssets, readAssetBody } = await import('./bootstrap/context-os.js');
|
|
967
|
+
const layers = ['08-Insights', '07-Knowledge', '12-Analysis'];
|
|
968
|
+
const pool = [];
|
|
969
|
+
for (const layer of layers) {
|
|
970
|
+
const listings = await readContextAssets(layer);
|
|
971
|
+
for (const f of (listings[0]?.files || []).slice(0, 5)) {
|
|
972
|
+
const body = await readAssetBody(layer, f.file).catch(() => null);
|
|
973
|
+
const lines = (body?.body || '').split('\n').filter(l => l.trim() && !l.startsWith('---') && !l.startsWith('#') && !l.startsWith('>') && !l.startsWith('未来'));
|
|
974
|
+
if (lines[0])
|
|
975
|
+
pool.push(lines[0].trim().slice(0, 100));
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
if (pool.length === 0) {
|
|
979
|
+
appendLine(`${C_DIM}🌙 梦境空空 — 多对话让记忆沉淀出洞察后, /dream 就有素材了${RESET}`);
|
|
980
|
+
}
|
|
981
|
+
else {
|
|
982
|
+
const pick = pool[Math.floor(Math.random() * pool.length)];
|
|
983
|
+
appendLine(`${C_DIM}🌙 ${pick}${RESET}`);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
catch { /* 静默 */ }
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
584
989
|
if (trimmed.toLowerCase() === '/help' || trimmed === 'help') {
|
|
585
990
|
appendLine(`${C_DIM}命令:${RESET}`);
|
|
586
991
|
appendLine(` ${C_ACCENT}!<cmd>${RESET} 执行终端命令 ${C_DIM}如 !ls -la${RESET}`);
|
|
587
992
|
appendLine(` ${C_ACCENT}/queue${RESET} 切换队列模式 ${C_DIM}输入排队, 当前结束后自动执行${RESET}`);
|
|
588
993
|
appendLine(` ${C_ACCENT}/dequeue${RESET} 出队一条`);
|
|
589
994
|
appendLine(` ${C_ACCENT}/channel [名字|id|序号]${RESET} 切换当前智能体 ${C_DIM}无参列出所有; 支持名字/ID/序号三种解析${RESET}`);
|
|
995
|
+
appendLine(` ${C_ACCENT}/model${RESET} / ${C_ACCENT}/login${RESET} 模型供应商选择器 ${C_DIM}↑↓ 选择 · Enter 确认 · Esc 取消${RESET}`);
|
|
996
|
+
appendLine(` ${C_ACCENT}/logout${RESET} 查看当前供应商`);
|
|
997
|
+
appendLine(` ${C_ACCENT}/now${RESET} 当前状态总览 ${C_DIM}智能体/运行时间/上下文 tokens/消息数${RESET}`);
|
|
998
|
+
appendLine(` ${C_ACCENT}/session${RESET} 当前会话信息 ${C_DIM}channel/agent/消息窗口${RESET}`);
|
|
999
|
+
appendLine(` ${C_ACCENT}/loop${RESET} 循环状态 ${C_DIM}消息数 + token 估算${RESET}`);
|
|
1000
|
+
appendLine(` ${C_ACCENT}/memory${RESET} 记忆摘要 ${C_DIM}memory-compressor 落盘摘要${RESET}`);
|
|
1001
|
+
appendLine(` ${C_ACCENT}/resume${RESET} 恢复上下文 ${C_DIM}最近记忆 + 进行中计划${RESET}`);
|
|
1002
|
+
appendLine(` ${C_ACCENT}/goal${RESET} 进行中目标 ${C_DIM}plan-store active plans${RESET}`);
|
|
1003
|
+
appendLine(` ${C_ACCENT}/tools${RESET} 可用工具列表`);
|
|
1004
|
+
appendLine(` ${C_ACCENT}/skill${RESET} 技能候选 ${C_DIM}skill-writer 沉淀候选${RESET}`);
|
|
1005
|
+
appendLine(` ${C_ACCENT}/mcp${RESET} MCP 服务器列表`);
|
|
1006
|
+
appendLine(` ${C_ACCENT}/agent${RESET} 当前智能体身份`);
|
|
1007
|
+
appendLine(` ${C_ACCENT}/did${RESET} DID 身份`);
|
|
1008
|
+
appendLine(` ${C_ACCENT}/ipfs${RESET} Kubo 状态 ${C_DIM}节点/peers/pins${RESET}`);
|
|
1009
|
+
appendLine(` ${C_ACCENT}/ipns${RESET} IPNS keys + resolve`);
|
|
1010
|
+
appendLine(` ${C_ACCENT}/wallet${RESET} 钱包状态`);
|
|
1011
|
+
appendLine(` ${C_ACCENT}/email${RESET} 邮件配置`);
|
|
1012
|
+
appendLine(` ${C_ACCENT}/judgement${RESET} 判断力列表`);
|
|
1013
|
+
appendLine(` ${C_ACCENT}/insight${RESET} Context OS 洞察 (08-Insights)`);
|
|
1014
|
+
appendLine(` ${C_ACCENT}/wiki${RESET} wiki 状态`);
|
|
1015
|
+
appendLine(` ${C_ACCENT}/dream${RESET} 随机灵感`);
|
|
590
1016
|
appendLine(` ${C_ACCENT}@名字${RESET} @ 命中智能体 ${C_DIM}弹出窗选择后发送给智能体${RESET}`);
|
|
591
1017
|
appendLine(` ${C_ACCENT}/名字${RESET} / 命中命令/技能/插件 ${C_DIM}输入 / 自动弹出${RESET}`);
|
|
592
1018
|
appendLine(` ${C_ACCENT}#路径${RESET} # 命中文件 ${C_DIM}输入 # 自动弹出文件列表${RESET}`);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* npm 自动更新检查器
|
|
4
3
|
*
|
|
@@ -14,48 +13,11 @@
|
|
|
14
13
|
* 开发态下若 cwd 的 package.json 就是本包则回退到 cwd,不受任意工作目录影响。
|
|
15
14
|
* - 检查频率受节流缓存约束(默认 24h 一次),不会每次启动都打 npm。
|
|
16
15
|
*/
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
Object.defineProperty(o, k2, desc);
|
|
24
|
-
}) : (function(o, m, k, k2) {
|
|
25
|
-
if (k2 === undefined) k2 = k;
|
|
26
|
-
o[k2] = m[k];
|
|
27
|
-
}));
|
|
28
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
-
}) : function(o, v) {
|
|
31
|
-
o["default"] = v;
|
|
32
|
-
});
|
|
33
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
-
var ownKeys = function(o) {
|
|
35
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
-
var ar = [];
|
|
37
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
-
return ar;
|
|
39
|
-
};
|
|
40
|
-
return ownKeys(o);
|
|
41
|
-
};
|
|
42
|
-
return function (mod) {
|
|
43
|
-
if (mod && mod.__esModule) return mod;
|
|
44
|
-
var result = {};
|
|
45
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
-
__setModuleDefault(result, mod);
|
|
47
|
-
return result;
|
|
48
|
-
};
|
|
49
|
-
})();
|
|
50
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
-
exports.checkAndUpdate = checkAndUpdate;
|
|
52
|
-
exports.checkForUpdates = checkForUpdates;
|
|
53
|
-
exports.performUpdate = performUpdate;
|
|
54
|
-
const child_process_1 = require("child_process");
|
|
55
|
-
const fs = __importStar(require("fs"));
|
|
56
|
-
const path = __importStar(require("path"));
|
|
57
|
-
const https = __importStar(require("https"));
|
|
58
|
-
const http = __importStar(require("http"));
|
|
16
|
+
import { execSync } from 'child_process';
|
|
17
|
+
import * as fs from 'fs';
|
|
18
|
+
import * as path from 'path';
|
|
19
|
+
import * as https from 'https';
|
|
20
|
+
import * as http from 'http';
|
|
59
21
|
// ANSI 颜色
|
|
60
22
|
const RESET = '\x1b[0m';
|
|
61
23
|
const BOLD = '\x1b[1m';
|
|
@@ -113,7 +75,7 @@ function getGlobalBolloonDir() {
|
|
|
113
75
|
const candidates = [];
|
|
114
76
|
// 1. npm root -g(最可靠)
|
|
115
77
|
try {
|
|
116
|
-
const npmRoot =
|
|
78
|
+
const npmRoot = execSync('npm root -g', { encoding: 'utf-8', timeout: 8000 }).trim();
|
|
117
79
|
if (npmRoot)
|
|
118
80
|
candidates.push(path.join(npmRoot, '@bolloon', 'bolloon-agent'));
|
|
119
81
|
}
|
|
@@ -122,7 +84,7 @@ function getGlobalBolloonDir() {
|
|
|
122
84
|
}
|
|
123
85
|
// 2. npm prefix -g
|
|
124
86
|
try {
|
|
125
|
-
const npmPrefix =
|
|
87
|
+
const npmPrefix = execSync('npm prefix -g', { encoding: 'utf-8', timeout: 8000 }).trim();
|
|
126
88
|
if (npmPrefix)
|
|
127
89
|
candidates.push(path.join(npmPrefix, 'lib', 'node_modules', '@bolloon', 'bolloon-agent'));
|
|
128
90
|
}
|
|
@@ -280,7 +242,7 @@ async function checkBolloonUpdates() {
|
|
|
280
242
|
*/
|
|
281
243
|
function checkNpmOutdated() {
|
|
282
244
|
try {
|
|
283
|
-
const output =
|
|
245
|
+
const output = execSync('npm outdated --json', {
|
|
284
246
|
encoding: 'utf-8',
|
|
285
247
|
timeout: 30000,
|
|
286
248
|
maxBuffer: 10 * 1024 * 1024,
|
|
@@ -344,7 +306,7 @@ async function updatePackagesWithVersion(packagesWithVersion) {
|
|
|
344
306
|
const args = ['npm', 'install', '-g', ...packagesWithVersion];
|
|
345
307
|
notify(`\n${CYAN}📦 正在更新包...${RESET}\n`, RESET);
|
|
346
308
|
try {
|
|
347
|
-
|
|
309
|
+
execSync(args.join(' '), {
|
|
348
310
|
encoding: 'utf-8',
|
|
349
311
|
timeout: 300000,
|
|
350
312
|
stdio: 'inherit',
|
|
@@ -462,7 +424,7 @@ function resolveAutoUpdatePolicy() {
|
|
|
462
424
|
* 例如 Electron 用 app.relaunch(),Node 用 detached 重新 spawn)。
|
|
463
425
|
* 若未提供或 autoRestart=false,则仅提示用户手动重启。
|
|
464
426
|
*/
|
|
465
|
-
async function checkAndUpdate(opts = {}) {
|
|
427
|
+
export async function checkAndUpdate(opts = {}) {
|
|
466
428
|
const policy = resolveAutoUpdatePolicy();
|
|
467
429
|
if (policy.blocked) {
|
|
468
430
|
return { hasUpdate: false, info: null, updated: false, message: '跳过更新检查(已显式禁用)' };
|
|
@@ -566,13 +528,13 @@ async function checkAndUpdate(opts = {}) {
|
|
|
566
528
|
/**
|
|
567
529
|
* 仅检查更新,不自动安装
|
|
568
530
|
*/
|
|
569
|
-
async function checkForUpdates() {
|
|
531
|
+
export async function checkForUpdates() {
|
|
570
532
|
return await checkBolloonUpdates();
|
|
571
533
|
}
|
|
572
534
|
/**
|
|
573
535
|
* 手动触发更新
|
|
574
536
|
*/
|
|
575
|
-
async function performUpdate(packages) {
|
|
537
|
+
export async function performUpdate(packages) {
|
|
576
538
|
return await updatePackages(packages);
|
|
577
539
|
}
|
|
578
540
|
// CLI 入口
|
|
@@ -595,4 +557,3 @@ if (process.argv[1]?.includes('auto-update')) {
|
|
|
595
557
|
}
|
|
596
558
|
})();
|
|
597
559
|
}
|
|
598
|
-
//# sourceMappingURL=auto-update.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bolloon/bolloon-agent",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.37",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "P2P AI Document Agent - 全局安装后执行 `bolloon` 启动产品",
|
|
6
6
|
"main": "dist/cli-entry.js",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"dev": "tsx -r dotenv/config src/index.ts",
|
|
36
36
|
"dev:web": "npm run build:web && tsx -r dotenv/config src/index.ts --web",
|
|
37
37
|
"dev:electron": "npm run build:electron && npm run electron:start",
|
|
38
|
-
"electron:start": "NODE_ENV=development electron dist/electron.js",
|
|
38
|
+
"electron:start": "NODE_ENV=development electron dist/electron-build/electron.js",
|
|
39
39
|
"electron:dev": "concurrently \"npm run dev:web\" \"npm run electron:start\"",
|
|
40
40
|
"electron:build": "npm run build:electron && electron-builder",
|
|
41
41
|
"electron:pack": "electron-builder --dir",
|
|
@@ -133,7 +133,8 @@
|
|
|
133
133
|
"files": [
|
|
134
134
|
"dist/**/*",
|
|
135
135
|
"bin/**/*",
|
|
136
|
-
"package.json"
|
|
136
|
+
"package.json",
|
|
137
|
+
"dist/electron-build/**/*"
|
|
137
138
|
],
|
|
138
139
|
"npmRebuild": false,
|
|
139
140
|
"buildDependenciesFromSource": false,
|
|
@@ -147,7 +148,7 @@
|
|
|
147
148
|
}
|
|
148
149
|
],
|
|
149
150
|
"extraMetadata": {
|
|
150
|
-
"main": "dist/electron.js",
|
|
151
|
+
"main": "dist/electron-build/electron.js",
|
|
151
152
|
"type": "commonjs"
|
|
152
153
|
},
|
|
153
154
|
"win": {
|