opc-agent 3.0.1 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +404 -74
- package/README.zh-CN.md +82 -0
- package/dist/channels/dingtalk.d.ts +17 -0
- package/dist/channels/dingtalk.js +38 -0
- package/dist/channels/googlechat.d.ts +14 -0
- package/dist/channels/googlechat.js +37 -0
- package/dist/channels/imessage.d.ts +13 -0
- package/dist/channels/imessage.js +28 -0
- package/dist/channels/irc.d.ts +20 -0
- package/dist/channels/irc.js +71 -0
- package/dist/channels/line.d.ts +14 -0
- package/dist/channels/line.js +28 -0
- package/dist/channels/matrix.d.ts +15 -0
- package/dist/channels/matrix.js +28 -0
- package/dist/channels/mattermost.d.ts +18 -0
- package/dist/channels/mattermost.js +49 -0
- package/dist/channels/msteams.d.ts +14 -0
- package/dist/channels/msteams.js +28 -0
- package/dist/channels/nostr.d.ts +14 -0
- package/dist/channels/nostr.js +28 -0
- package/dist/channels/qq.d.ts +15 -0
- package/dist/channels/qq.js +28 -0
- package/dist/channels/signal.d.ts +14 -0
- package/dist/channels/signal.js +28 -0
- package/dist/channels/sms.d.ts +15 -0
- package/dist/channels/sms.js +28 -0
- package/dist/channels/twitch.d.ts +17 -0
- package/dist/channels/twitch.js +59 -0
- package/dist/channels/voice-call.d.ts +27 -0
- package/dist/channels/voice-call.js +82 -0
- package/dist/channels/whatsapp.d.ts +14 -0
- package/dist/channels/whatsapp.js +28 -0
- package/dist/cli/chat.d.ts +2 -0
- package/dist/cli/chat.js +134 -0
- package/dist/cli/setup.d.ts +4 -0
- package/dist/cli/setup.js +303 -0
- package/dist/cli.js +142 -6
- package/dist/core/api-server.d.ts +25 -0
- package/dist/core/api-server.js +286 -0
- package/dist/core/audio.d.ts +50 -0
- package/dist/core/audio.js +68 -0
- package/dist/core/context-discovery.d.ts +16 -0
- package/dist/core/context-discovery.js +107 -0
- package/dist/core/context-refs.d.ts +29 -0
- package/dist/core/context-refs.js +162 -0
- package/dist/core/gateway.d.ts +53 -0
- package/dist/core/gateway.js +80 -0
- package/dist/core/heartbeat.d.ts +19 -0
- package/dist/core/heartbeat.js +50 -0
- package/dist/core/hooks.d.ts +28 -0
- package/dist/core/hooks.js +82 -0
- package/dist/core/ide-bridge.d.ts +53 -0
- package/dist/core/ide-bridge.js +97 -0
- package/dist/core/node-network.d.ts +23 -0
- package/dist/core/node-network.js +77 -0
- package/dist/core/profiles.d.ts +27 -0
- package/dist/core/profiles.js +131 -0
- package/dist/core/sandbox.d.ts +25 -0
- package/dist/core/sandbox.js +84 -1
- package/dist/core/session-manager.d.ts +33 -0
- package/dist/core/session-manager.js +157 -0
- package/dist/core/vision.d.ts +45 -0
- package/dist/core/vision.js +177 -0
- package/dist/hub/brain-seed.d.ts +14 -0
- package/dist/hub/brain-seed.js +77 -0
- package/dist/hub/client.d.ts +25 -0
- package/dist/hub/client.js +44 -0
- package/dist/index.d.ts +66 -1
- package/dist/index.js +95 -3
- package/dist/memory/context-compressor.d.ts +43 -0
- package/dist/memory/context-compressor.js +167 -0
- package/dist/memory/index.d.ts +4 -0
- package/dist/memory/index.js +5 -1
- package/dist/memory/user-profiler.d.ts +50 -0
- package/dist/memory/user-profiler.js +201 -0
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.js +54 -1
- package/dist/scheduler/cron-engine.d.ts +41 -0
- package/dist/scheduler/cron-engine.js +200 -0
- package/dist/scheduler/index.d.ts +3 -0
- package/dist/scheduler/index.js +7 -0
- package/dist/schema/oad.d.ts +12 -12
- package/dist/security/approvals.d.ts +53 -0
- package/dist/security/approvals.js +115 -0
- package/dist/security/elevated.d.ts +41 -0
- package/dist/security/elevated.js +89 -0
- package/dist/security/index.d.ts +6 -0
- package/dist/security/index.js +7 -1
- package/dist/security/secrets.d.ts +34 -0
- package/dist/security/secrets.js +115 -0
- package/dist/skills/builtin/index.d.ts +6 -0
- package/dist/skills/builtin/index.js +402 -0
- package/dist/skills/marketplace.d.ts +30 -0
- package/dist/skills/marketplace.js +142 -0
- package/dist/skills/types.d.ts +34 -0
- package/dist/skills/types.js +16 -0
- package/dist/studio/server.d.ts +25 -0
- package/dist/studio/server.js +780 -0
- package/dist/studio/templates-data.d.ts +21 -0
- package/dist/studio/templates-data.js +148 -0
- package/dist/studio-ui/index.html +2502 -1073
- package/dist/tools/builtin/browser.d.ts +47 -0
- package/dist/tools/builtin/browser.js +284 -0
- package/dist/tools/builtin/home-assistant.d.ts +12 -0
- package/dist/tools/builtin/home-assistant.js +126 -0
- package/dist/tools/builtin/index.d.ts +7 -1
- package/dist/tools/builtin/index.js +23 -2
- package/dist/tools/builtin/rl-tools.d.ts +13 -0
- package/dist/tools/builtin/rl-tools.js +228 -0
- package/dist/tools/builtin/vision.d.ts +6 -0
- package/dist/tools/builtin/vision.js +61 -0
- package/dist/tools/builtin/web-search.d.ts +9 -0
- package/dist/tools/builtin/web-search.js +150 -0
- package/dist/tools/document-processor.d.ts +39 -0
- package/dist/tools/document-processor.js +188 -0
- package/dist/tools/image-generator.d.ts +42 -0
- package/dist/tools/image-generator.js +136 -0
- package/dist/tools/web-scraper.d.ts +20 -0
- package/dist/tools/web-scraper.js +148 -0
- package/dist/tools/web-search.d.ts +51 -0
- package/dist/tools/web-search.js +152 -0
- package/install.ps1 +154 -0
- package/install.sh +164 -0
- package/package.json +63 -52
- package/src/channels/dingtalk.ts +46 -0
- package/src/channels/googlechat.ts +42 -0
- package/src/channels/imessage.ts +32 -0
- package/src/channels/irc.ts +82 -0
- package/src/channels/line.ts +33 -0
- package/src/channels/matrix.ts +34 -0
- package/src/channels/mattermost.ts +57 -0
- package/src/channels/msteams.ts +33 -0
- package/src/channels/nostr.ts +33 -0
- package/src/channels/qq.ts +34 -0
- package/src/channels/signal.ts +33 -0
- package/src/channels/sms.ts +34 -0
- package/src/channels/twitch.ts +65 -0
- package/src/channels/voice-call.ts +100 -0
- package/src/channels/whatsapp.ts +33 -0
- package/src/cli/chat.ts +99 -0
- package/src/cli/setup.ts +314 -0
- package/src/cli.ts +148 -6
- package/src/core/api-server.ts +277 -0
- package/src/core/audio.ts +98 -0
- package/src/core/context-discovery.ts +85 -0
- package/src/core/context-refs.ts +140 -0
- package/src/core/gateway.ts +106 -0
- package/src/core/heartbeat.ts +51 -0
- package/src/core/hooks.ts +105 -0
- package/src/core/ide-bridge.ts +133 -0
- package/src/core/node-network.ts +86 -0
- package/src/core/profiles.ts +122 -0
- package/src/core/sandbox.ts +100 -0
- package/src/core/session-manager.ts +137 -0
- package/src/core/vision.ts +180 -0
- package/src/hub/brain-seed.ts +54 -0
- package/src/hub/client.ts +60 -0
- package/src/index.ts +86 -1
- package/src/memory/context-compressor.ts +189 -0
- package/src/memory/index.ts +4 -0
- package/src/memory/user-profiler.ts +215 -0
- package/src/providers/index.ts +64 -1
- package/src/scheduler/cron-engine.ts +191 -0
- package/src/scheduler/index.ts +2 -0
- package/src/security/approvals.ts +143 -0
- package/src/security/elevated.ts +105 -0
- package/src/security/index.ts +6 -0
- package/src/security/secrets.ts +129 -0
- package/src/skills/builtin/index.ts +408 -0
- package/src/skills/marketplace.ts +113 -0
- package/src/skills/types.ts +42 -0
- package/src/studio/server.ts +1591 -791
- package/src/studio/templates-data.ts +178 -0
- package/src/studio-ui/index.html +2502 -1073
- package/src/tools/builtin/browser.ts +299 -0
- package/src/tools/builtin/home-assistant.ts +116 -0
- package/src/tools/builtin/index.ts +37 -28
- package/src/tools/builtin/rl-tools.ts +243 -0
- package/src/tools/builtin/vision.ts +64 -0
- package/src/tools/builtin/web-search.ts +126 -0
- package/src/tools/document-processor.ts +213 -0
- package/src/tools/image-generator.ts +150 -0
- package/src/tools/web-scraper.ts +179 -0
- package/src/tools/web-search.ts +180 -0
- package/tests/api-server.test.ts +148 -0
- package/tests/approvals.test.ts +89 -0
- package/tests/audio.test.ts +40 -0
- package/tests/browser.test.ts +179 -0
- package/tests/builtin-tools.test.ts +83 -83
- package/tests/channels-extra.test.ts +45 -0
- package/tests/context-compressor.test.ts +172 -0
- package/tests/context-refs.test.ts +121 -0
- package/tests/cron-engine.test.ts +101 -0
- package/tests/document-processor.test.ts +69 -0
- package/tests/e2e-nocode.test.ts +442 -0
- package/tests/elevated.test.ts +69 -0
- package/tests/gateway.test.ts +63 -71
- package/tests/home-assistant.test.ts +40 -0
- package/tests/hooks.test.ts +79 -0
- package/tests/ide-bridge.test.ts +38 -0
- package/tests/image-generator.test.ts +84 -0
- package/tests/node-network.test.ts +74 -0
- package/tests/profiles.test.ts +61 -0
- package/tests/rl-tools.test.ts +93 -0
- package/tests/sandbox-manager.test.ts +46 -0
- package/tests/secrets.test.ts +107 -0
- package/tests/settings-api.test.ts +148 -0
- package/tests/setup.test.ts +73 -0
- package/tests/studio.test.ts +402 -229
- package/tests/tools/builtin-extended.test.ts +138 -138
- package/tests/user-profiler.test.ts +169 -0
- package/tests/v090-features.test.ts +254 -0
- package/tests/vision.test.ts +61 -0
- package/tests/voice-call.test.ts +47 -0
- package/tests/voice-interaction.test.ts +38 -0
- package/tests/web-search.test.ts +155 -0
package/install.ps1
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# ============================================================================
|
|
2
|
+
# OPC Agent 一键安装脚本 for Windows
|
|
3
|
+
# 用法: irm https://raw.githubusercontent.com/Deepleaper/opc-agent/main/install.ps1 | iex
|
|
4
|
+
# 高级: $env:OPC_YES='1'; $env:OPC_NO_OLLAMA='1'; irm ... | iex
|
|
5
|
+
# ============================================================================
|
|
6
|
+
|
|
7
|
+
$ErrorActionPreference = "Stop"
|
|
8
|
+
|
|
9
|
+
# ── 颜色输出 ──────────────────────────────────────────────────
|
|
10
|
+
function Write-Step($msg) { Write-Host "`n━━━ $msg ━━━" -ForegroundColor Blue }
|
|
11
|
+
function Write-Ok($msg) { Write-Host "✅ $msg" -ForegroundColor Green }
|
|
12
|
+
function Write-Warn($msg) { Write-Host "⚠️ $msg" -ForegroundColor Yellow }
|
|
13
|
+
function Write-Err($msg) { Write-Host "❌ $msg" -ForegroundColor Red }
|
|
14
|
+
function Write-Info($msg) { Write-Host "ℹ️ $msg" -ForegroundColor Cyan }
|
|
15
|
+
|
|
16
|
+
$AutoYes = $env:OPC_YES -eq '1'
|
|
17
|
+
$SkipOllama = $env:OPC_NO_OLLAMA -eq '1'
|
|
18
|
+
|
|
19
|
+
function Confirm-Action($prompt) {
|
|
20
|
+
if ($AutoYes) { return $true }
|
|
21
|
+
$choice = Read-Host "❓ $prompt [Y/n]"
|
|
22
|
+
return ($choice -ne 'n' -and $choice -ne 'N' -and $choice -ne 'no')
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
# ── 检测操作系统 ──────────────────────────────────────────────
|
|
26
|
+
Write-Step "🔍 检测操作系统 / Detecting OS"
|
|
27
|
+
Write-Ok "Windows $([System.Environment]::OSVersion.Version) detected"
|
|
28
|
+
|
|
29
|
+
# ── 检测 & 安装 Node.js ──────────────────────────────────────
|
|
30
|
+
Write-Step "📦 检测 Node.js / Checking Node.js"
|
|
31
|
+
$NeedNode = $false
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
$nodeVer = (node -v) -replace 'v','' -split '\.' | Select-Object -First 1
|
|
35
|
+
if ([int]$nodeVer -ge 18) {
|
|
36
|
+
Write-Ok "Node.js $(node -v) 已安装 / installed"
|
|
37
|
+
} else {
|
|
38
|
+
Write-Warn "Node.js $(node -v) 版本过低,需要 18+ / version too old"
|
|
39
|
+
$NeedNode = $true
|
|
40
|
+
}
|
|
41
|
+
} catch {
|
|
42
|
+
Write-Warn "未检测到 Node.js / Node.js not found"
|
|
43
|
+
$NeedNode = $true
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if ($NeedNode) {
|
|
47
|
+
Write-Info "将安装 Node.js 22 LTS / Installing Node.js 22 LTS"
|
|
48
|
+
if (Confirm-Action "安装 Node.js 22? / Install Node.js 22?") {
|
|
49
|
+
$installed = $false
|
|
50
|
+
# 尝试 winget
|
|
51
|
+
try {
|
|
52
|
+
winget install OpenJS.NodeJS.LTS --accept-package-agreements --accept-source-agreements
|
|
53
|
+
$installed = $true
|
|
54
|
+
Write-Ok "Node.js 通过 winget 安装成功 / installed via winget"
|
|
55
|
+
} catch {}
|
|
56
|
+
|
|
57
|
+
# 尝试 choco
|
|
58
|
+
if (-not $installed) {
|
|
59
|
+
try {
|
|
60
|
+
choco install nodejs-lts -y
|
|
61
|
+
$installed = $true
|
|
62
|
+
Write-Ok "Node.js 通过 Chocolatey 安装成功 / installed via Chocolatey"
|
|
63
|
+
} catch {}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (-not $installed) {
|
|
67
|
+
Write-Err "自动安装失败 / Auto-install failed"
|
|
68
|
+
Write-Info "请手动下载安装 / Please download manually: https://nodejs.org/"
|
|
69
|
+
Start-Process "https://nodejs.org/en/download/"
|
|
70
|
+
exit 1
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
# 刷新 PATH
|
|
74
|
+
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
|
|
75
|
+
} else {
|
|
76
|
+
Write-Err "Node.js 是必需的 / Node.js is required"
|
|
77
|
+
Write-Info "下载地址 / Download: https://nodejs.org/"
|
|
78
|
+
exit 1
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# ── 安装 OPC Agent ────────────────────────────────────────────
|
|
83
|
+
Write-Step "🚀 安装 OPC Agent / Installing OPC Agent"
|
|
84
|
+
Write-Info "npm install -g opc-agent ..."
|
|
85
|
+
npm install -g opc-agent
|
|
86
|
+
Write-Ok "OPC Agent 安装成功 / installed"
|
|
87
|
+
|
|
88
|
+
# ── Ollama(可选)─────────────────────────────────────────────
|
|
89
|
+
if (-not $SkipOllama) {
|
|
90
|
+
Write-Step "🦙 检测 Ollama / Checking Ollama"
|
|
91
|
+
|
|
92
|
+
$hasOllama = $false
|
|
93
|
+
try { ollama --version 2>$null; $hasOllama = $true } catch {}
|
|
94
|
+
|
|
95
|
+
if ($hasOllama) {
|
|
96
|
+
Write-Ok "Ollama 已安装 / installed"
|
|
97
|
+
} else {
|
|
98
|
+
Write-Warn "未检测到 Ollama / Ollama not found"
|
|
99
|
+
Write-Info "Ollama 可让你在本地运行 AI 模型(免费、数据不出门)"
|
|
100
|
+
Write-Info "Ollama lets you run AI models locally (free, private)"
|
|
101
|
+
|
|
102
|
+
if (Confirm-Action "安装 Ollama? / Install Ollama?") {
|
|
103
|
+
try {
|
|
104
|
+
winget install Ollama.Ollama --accept-package-agreements --accept-source-agreements
|
|
105
|
+
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
|
|
106
|
+
Write-Ok "Ollama 安装成功 / installed"
|
|
107
|
+
$hasOllama = $true
|
|
108
|
+
} catch {
|
|
109
|
+
Write-Warn "winget 安装失败,请手动下载 / Please download manually: https://ollama.com/download"
|
|
110
|
+
Start-Process "https://ollama.com/download"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
# 拉取推荐模型
|
|
116
|
+
if ($hasOllama) {
|
|
117
|
+
Write-Step "🧠 推荐模型 / Recommended Models"
|
|
118
|
+
Write-Info "推荐拉取以下模型用于本地 Agent:"
|
|
119
|
+
Write-Info " • qwen2.5:7b — 中英文对话(4.7GB)"
|
|
120
|
+
Write-Info " • nomic-embed-text — 文本向量化(274MB)"
|
|
121
|
+
|
|
122
|
+
if (Confirm-Action "拉取推荐模型? / Pull recommended models?") {
|
|
123
|
+
Write-Info "拉取 qwen2.5:7b ... (可能需要几分钟)"
|
|
124
|
+
try { ollama pull qwen2.5:7b; Write-Ok "qwen2.5:7b ✓" } catch { Write-Warn "拉取失败,可稍后手动: ollama pull qwen2.5:7b" }
|
|
125
|
+
|
|
126
|
+
Write-Info "拉取 nomic-embed-text ..."
|
|
127
|
+
try { ollama pull nomic-embed-text; Write-Ok "nomic-embed-text ✓" } catch { Write-Warn "拉取失败,可稍后手动: ollama pull nomic-embed-text" }
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
# ── 完成 ──────────────────────────────────────────────────────
|
|
133
|
+
Write-Step "🎉 安装完成!/ Installation Complete!"
|
|
134
|
+
Write-Host ""
|
|
135
|
+
Write-Host "┌─────────────────────────────────────────────────┐" -ForegroundColor Green
|
|
136
|
+
Write-Host "│ OPC Agent 已安装成功! │" -ForegroundColor Green
|
|
137
|
+
Write-Host "│ OPC Agent installed successfully! │" -ForegroundColor Green
|
|
138
|
+
Write-Host "│ │" -ForegroundColor Green
|
|
139
|
+
Write-Host "│ 快速开始 / Quick Start: │" -ForegroundColor Green
|
|
140
|
+
Write-Host "│ opc init my-agent # 创建 Agent │" -ForegroundColor Green
|
|
141
|
+
Write-Host "│ cd my-agent; npm i │" -ForegroundColor Green
|
|
142
|
+
Write-Host "│ opc chat # 开始对话 │" -ForegroundColor Green
|
|
143
|
+
Write-Host "│ │" -ForegroundColor Green
|
|
144
|
+
Write-Host "│ 可视化面板 / Dashboard: │" -ForegroundColor Green
|
|
145
|
+
Write-Host "│ opc studio │" -ForegroundColor Green
|
|
146
|
+
Write-Host "│ │" -ForegroundColor Green
|
|
147
|
+
Write-Host "│ 交互式设置 / Setup wizard: │" -ForegroundColor Green
|
|
148
|
+
Write-Host "│ opc setup │" -ForegroundColor Green
|
|
149
|
+
Write-Host "└─────────────────────────────────────────────────┘" -ForegroundColor Green
|
|
150
|
+
Write-Host ""
|
|
151
|
+
|
|
152
|
+
if (Confirm-Action "现在打开 OPC Studio? / Open OPC Studio now?") {
|
|
153
|
+
opc studio
|
|
154
|
+
}
|
package/install.sh
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ============================================================================
|
|
3
|
+
# OPC Agent 一键安装脚本 (macOS / Linux / WSL)
|
|
4
|
+
# 用法: curl -fsSL https://raw.githubusercontent.com/Deepleaper/opc-agent/main/install.sh | bash
|
|
5
|
+
# 高级: curl -fsSL ... | bash -s -- --yes --no-ollama
|
|
6
|
+
# ============================================================================
|
|
7
|
+
|
|
8
|
+
set -e
|
|
9
|
+
|
|
10
|
+
# ── 颜色 & Emoji ──────────────────────────────────────────────
|
|
11
|
+
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; CYAN='\033[0;36m'; NC='\033[0m'
|
|
12
|
+
info() { echo -e "${CYAN}ℹ️ $1${NC}"; }
|
|
13
|
+
ok() { echo -e "${GREEN}✅ $1${NC}"; }
|
|
14
|
+
warn() { echo -e "${YELLOW}⚠️ $1${NC}"; }
|
|
15
|
+
err() { echo -e "${RED}❌ $1${NC}"; }
|
|
16
|
+
step() { echo -e "\n${BLUE}━━━ $1 ━━━${NC}"; }
|
|
17
|
+
|
|
18
|
+
# ── 参数解析 ──────────────────────────────────────────────────
|
|
19
|
+
AUTO_YES=false
|
|
20
|
+
SKIP_OLLAMA=false
|
|
21
|
+
for arg in "$@"; do
|
|
22
|
+
case "$arg" in
|
|
23
|
+
--yes|-y) AUTO_YES=true ;;
|
|
24
|
+
--no-ollama) SKIP_OLLAMA=true ;;
|
|
25
|
+
esac
|
|
26
|
+
done
|
|
27
|
+
|
|
28
|
+
confirm() {
|
|
29
|
+
if $AUTO_YES; then return 0; fi
|
|
30
|
+
read -r -p "$(echo -e "${YELLOW}❓ $1 [Y/n]: ${NC}")" choice
|
|
31
|
+
case "$choice" in n|N|no|NO) return 1 ;; *) return 0 ;; esac
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
# ── 检测操作系统 ──────────────────────────────────────────────
|
|
35
|
+
step "🔍 检测操作系统 / Detecting OS"
|
|
36
|
+
OS="unknown"
|
|
37
|
+
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
38
|
+
OS="macos"
|
|
39
|
+
ok "macOS detected"
|
|
40
|
+
elif grep -qi microsoft /proc/version 2>/dev/null; then
|
|
41
|
+
OS="wsl"
|
|
42
|
+
ok "WSL (Windows Subsystem for Linux) detected"
|
|
43
|
+
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
|
44
|
+
OS="linux"
|
|
45
|
+
ok "Linux detected"
|
|
46
|
+
else
|
|
47
|
+
err "不支持的操作系统 / Unsupported OS: $OSTYPE"
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# ── 检测 & 安装 Node.js ──────────────────────────────────────
|
|
52
|
+
step "📦 检测 Node.js / Checking Node.js"
|
|
53
|
+
NEED_NODE=false
|
|
54
|
+
|
|
55
|
+
if command -v node &>/dev/null; then
|
|
56
|
+
NODE_VER=$(node -v | sed 's/v//' | cut -d. -f1)
|
|
57
|
+
if [ "$NODE_VER" -ge 18 ]; then
|
|
58
|
+
ok "Node.js $(node -v) 已安装 / installed"
|
|
59
|
+
else
|
|
60
|
+
warn "Node.js $(node -v) 版本过低,需要 18+ / version too old, need 18+"
|
|
61
|
+
NEED_NODE=true
|
|
62
|
+
fi
|
|
63
|
+
else
|
|
64
|
+
warn "未检测到 Node.js / Node.js not found"
|
|
65
|
+
NEED_NODE=true
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
if $NEED_NODE; then
|
|
69
|
+
info "将通过 nvm 安装 Node.js 22 LTS / Installing Node.js 22 via nvm"
|
|
70
|
+
if confirm "安装 Node.js 22? / Install Node.js 22?"; then
|
|
71
|
+
if command -v nvm &>/dev/null || [ -s "$HOME/.nvm/nvm.sh" ]; then
|
|
72
|
+
[ -s "$HOME/.nvm/nvm.sh" ] && . "$HOME/.nvm/nvm.sh"
|
|
73
|
+
info "nvm 已存在,安装 Node 22... / nvm found, installing Node 22..."
|
|
74
|
+
else
|
|
75
|
+
info "安装 nvm... / Installing nvm..."
|
|
76
|
+
curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
|
|
77
|
+
export NVM_DIR="$HOME/.nvm"
|
|
78
|
+
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
|
|
79
|
+
fi
|
|
80
|
+
nvm install 22
|
|
81
|
+
nvm use 22
|
|
82
|
+
ok "Node.js $(node -v) 安装成功 / installed successfully"
|
|
83
|
+
else
|
|
84
|
+
err "Node.js 是必需的 / Node.js is required"
|
|
85
|
+
echo "手动安装 / Manual install: https://nodejs.org/"
|
|
86
|
+
exit 1
|
|
87
|
+
fi
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
# ── 安装 OPC Agent ────────────────────────────────────────────
|
|
91
|
+
step "🚀 安装 OPC Agent / Installing OPC Agent"
|
|
92
|
+
info "npm install -g opc-agent ..."
|
|
93
|
+
npm install -g opc-agent
|
|
94
|
+
ok "OPC Agent $(opc --version 2>/dev/null || echo '') 安装成功 / installed"
|
|
95
|
+
|
|
96
|
+
# ── Ollama(可选)─────────────────────────────────────────────
|
|
97
|
+
if ! $SKIP_OLLAMA; then
|
|
98
|
+
step "🦙 检测 Ollama / Checking Ollama"
|
|
99
|
+
|
|
100
|
+
if command -v ollama &>/dev/null; then
|
|
101
|
+
ok "Ollama 已安装 / installed ($(ollama --version 2>/dev/null || echo 'ok'))"
|
|
102
|
+
else
|
|
103
|
+
warn "未检测到 Ollama / Ollama not found"
|
|
104
|
+
info "Ollama 可让你在本地运行 AI 模型(免费、数据不出门)"
|
|
105
|
+
info "Ollama lets you run AI models locally (free, private)"
|
|
106
|
+
|
|
107
|
+
if confirm "安装 Ollama? / Install Ollama?"; then
|
|
108
|
+
if [ "$OS" = "macos" ]; then
|
|
109
|
+
if command -v brew &>/dev/null; then
|
|
110
|
+
brew install ollama
|
|
111
|
+
else
|
|
112
|
+
info "请从 https://ollama.com/download 下载安装"
|
|
113
|
+
info "Download from https://ollama.com/download"
|
|
114
|
+
open "https://ollama.com/download" 2>/dev/null || true
|
|
115
|
+
fi
|
|
116
|
+
else
|
|
117
|
+
curl -fsSL https://ollama.com/install.sh | sh
|
|
118
|
+
fi
|
|
119
|
+
ok "Ollama 安装成功 / installed"
|
|
120
|
+
else
|
|
121
|
+
info "跳过 Ollama / Skipping Ollama"
|
|
122
|
+
fi
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
# 拉取推荐模型
|
|
126
|
+
if command -v ollama &>/dev/null; then
|
|
127
|
+
step "🧠 推荐模型 / Recommended Models"
|
|
128
|
+
info "推荐拉取以下模型用于本地 Agent:"
|
|
129
|
+
info " • qwen2.5:7b — 中英文对话(4.7GB)"
|
|
130
|
+
info " • nomic-embed-text — 文本向量化(274MB)"
|
|
131
|
+
|
|
132
|
+
if confirm "拉取推荐模型? / Pull recommended models?"; then
|
|
133
|
+
info "拉取 qwen2.5:7b ... (可能需要几分钟)"
|
|
134
|
+
ollama pull qwen2.5:7b && ok "qwen2.5:7b ✓" || warn "qwen2.5:7b 拉取失败,可稍后手动: ollama pull qwen2.5:7b"
|
|
135
|
+
|
|
136
|
+
info "拉取 nomic-embed-text ..."
|
|
137
|
+
ollama pull nomic-embed-text && ok "nomic-embed-text ✓" || warn "拉取失败,可稍后手动: ollama pull nomic-embed-text"
|
|
138
|
+
fi
|
|
139
|
+
fi
|
|
140
|
+
fi
|
|
141
|
+
|
|
142
|
+
# ── 启动 Studio ───────────────────────────────────────────────
|
|
143
|
+
step "🎉 安装完成!/ Installation Complete!"
|
|
144
|
+
echo ""
|
|
145
|
+
echo -e "${GREEN}┌─────────────────────────────────────────────────┐${NC}"
|
|
146
|
+
echo -e "${GREEN}│ OPC Agent 已安装成功! │${NC}"
|
|
147
|
+
echo -e "${GREEN}│ OPC Agent installed successfully! │${NC}"
|
|
148
|
+
echo -e "${GREEN}│ │${NC}"
|
|
149
|
+
echo -e "${GREEN}│ 快速开始 / Quick Start: │${NC}"
|
|
150
|
+
echo -e "${GREEN}│ opc init my-agent # 创建 Agent │${NC}"
|
|
151
|
+
echo -e "${GREEN}│ cd my-agent && npm i │${NC}"
|
|
152
|
+
echo -e "${GREEN}│ opc chat # 开始对话 │${NC}"
|
|
153
|
+
echo -e "${GREEN}│ │${NC}"
|
|
154
|
+
echo -e "${GREEN}│ 可视化面板 / Dashboard: │${NC}"
|
|
155
|
+
echo -e "${GREEN}│ opc studio │${NC}"
|
|
156
|
+
echo -e "${GREEN}│ │${NC}"
|
|
157
|
+
echo -e "${GREEN}│ 交互式设置 / Setup wizard: │${NC}"
|
|
158
|
+
echo -e "${GREEN}│ opc setup │${NC}"
|
|
159
|
+
echo -e "${GREEN}└─────────────────────────────────────────────────┘${NC}"
|
|
160
|
+
echo ""
|
|
161
|
+
|
|
162
|
+
if confirm "现在打开 OPC Studio? / Open OPC Studio now?"; then
|
|
163
|
+
opc studio
|
|
164
|
+
fi
|
package/package.json
CHANGED
|
@@ -1,52 +1,63 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "opc-agent",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Open Agent Framework — Build, test, and run AI Agents for business workstations",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"bin": {
|
|
8
|
-
"opc": "dist/cli.js"
|
|
9
|
-
},
|
|
10
|
-
"scripts": {
|
|
11
|
-
"build": "tsc",
|
|
12
|
-
"postbuild": "xcopy /E /I /Y src\\studio-ui dist\\studio-ui",
|
|
13
|
-
"test": "vitest run",
|
|
14
|
-
"dev": "tsc --watch",
|
|
15
|
-
"lint": "tsc --noEmit",
|
|
16
|
-
"
|
|
17
|
-
"docs:
|
|
18
|
-
"docs:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"@types/
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
|
|
52
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "opc-agent",
|
|
3
|
+
"version": "4.0.1",
|
|
4
|
+
"description": "Open Agent Framework — Build, test, and run AI Agents for business workstations",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"opc": "dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"postbuild": "xcopy /E /I /Y src\\studio-ui dist\\studio-ui",
|
|
13
|
+
"test": "vitest run",
|
|
14
|
+
"dev": "tsc --watch",
|
|
15
|
+
"lint": "tsc --noEmit",
|
|
16
|
+
"setup": "opc setup",
|
|
17
|
+
"docs:dev": "vitepress dev docs",
|
|
18
|
+
"docs:build": "vitepress build docs",
|
|
19
|
+
"docs:preview": "vitepress preview docs"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"agent",
|
|
23
|
+
"ai",
|
|
24
|
+
"llm",
|
|
25
|
+
"framework",
|
|
26
|
+
"typescript",
|
|
27
|
+
"agent-framework"
|
|
28
|
+
],
|
|
29
|
+
"author": "Deepleaper",
|
|
30
|
+
"license": "Apache-2.0",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/Deepleaper/opc-agent.git"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"agent-workstation": "^2.0.1",
|
|
37
|
+
"agentkits": "^2.0.0",
|
|
38
|
+
"commander": "^12.0.0",
|
|
39
|
+
"express": "^4.21.0",
|
|
40
|
+
"js-yaml": "^4.1.0",
|
|
41
|
+
"mammoth": "^1.12.0",
|
|
42
|
+
"pdf-parse": "^1.1.4",
|
|
43
|
+
"ws": "^8.20.0",
|
|
44
|
+
"zod": "^3.23.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/express": "^4.17.21",
|
|
48
|
+
"@types/js-yaml": "^4.0.9",
|
|
49
|
+
"@types/node": "^20.11.0",
|
|
50
|
+
"@types/ws": "^8.18.1",
|
|
51
|
+
"typescript": "^5.5.0",
|
|
52
|
+
"vitepress": "^1.5.0",
|
|
53
|
+
"vitest": "^2.0.0"
|
|
54
|
+
},
|
|
55
|
+
"peerDependencies": {
|
|
56
|
+
"deepbrain": "^2.0.0"
|
|
57
|
+
},
|
|
58
|
+
"peerDependenciesMeta": {
|
|
59
|
+
"deepbrain": {
|
|
60
|
+
"optional": true
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { BaseChannel } from './index';
|
|
2
|
+
import type { Message } from '../core/types';
|
|
3
|
+
|
|
4
|
+
export interface DingTalkChannelConfig {
|
|
5
|
+
webhookUrl: string;
|
|
6
|
+
secret?: string;
|
|
7
|
+
appKey?: string;
|
|
8
|
+
appSecret?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class DingTalkChannel extends BaseChannel {
|
|
12
|
+
readonly type = 'dingtalk';
|
|
13
|
+
private config: DingTalkChannelConfig;
|
|
14
|
+
private running = false;
|
|
15
|
+
|
|
16
|
+
constructor(config: DingTalkChannelConfig) {
|
|
17
|
+
super();
|
|
18
|
+
if (!config.webhookUrl) {
|
|
19
|
+
throw new Error('DingTalkChannel requires webhookUrl in config');
|
|
20
|
+
}
|
|
21
|
+
this.config = config;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async start(): Promise<void> {
|
|
25
|
+
this.running = true;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async stop(): Promise<void> {
|
|
29
|
+
this.running = false;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async send(chatId: string, text: string): Promise<void> {
|
|
33
|
+
if (!this.running) {
|
|
34
|
+
throw new Error('DingTalkChannel: not started. Call start() first.');
|
|
35
|
+
}
|
|
36
|
+
const body = JSON.stringify({ msgtype: 'text', text: { content: text } });
|
|
37
|
+
const res = await fetch(this.config.webhookUrl, {
|
|
38
|
+
method: 'POST',
|
|
39
|
+
headers: { 'Content-Type': 'application/json' },
|
|
40
|
+
body,
|
|
41
|
+
});
|
|
42
|
+
if (!res.ok) {
|
|
43
|
+
throw new Error(`DingTalk webhook failed: ${res.status}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { BaseChannel } from './index';
|
|
2
|
+
import type { Message } from '../core/types';
|
|
3
|
+
|
|
4
|
+
export interface GoogleChatChannelConfig {
|
|
5
|
+
webhookUrl: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class GoogleChatChannel extends BaseChannel {
|
|
9
|
+
readonly type = 'googlechat';
|
|
10
|
+
private config: GoogleChatChannelConfig;
|
|
11
|
+
private running = false;
|
|
12
|
+
|
|
13
|
+
constructor(config: GoogleChatChannelConfig) {
|
|
14
|
+
super();
|
|
15
|
+
if (!config.webhookUrl) {
|
|
16
|
+
throw new Error('GoogleChatChannel requires webhookUrl in config');
|
|
17
|
+
}
|
|
18
|
+
this.config = config;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async start(): Promise<void> {
|
|
22
|
+
this.running = true;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async stop(): Promise<void> {
|
|
26
|
+
this.running = false;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async send(spaceId: string, text: string): Promise<void> {
|
|
30
|
+
if (!this.running) {
|
|
31
|
+
throw new Error('GoogleChatChannel: not started. Call start() first.');
|
|
32
|
+
}
|
|
33
|
+
const res = await fetch(this.config.webhookUrl, {
|
|
34
|
+
method: 'POST',
|
|
35
|
+
headers: { 'Content-Type': 'application/json' },
|
|
36
|
+
body: JSON.stringify({ text }),
|
|
37
|
+
});
|
|
38
|
+
if (!res.ok) {
|
|
39
|
+
throw new Error(`Google Chat webhook failed: ${res.status}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { BaseChannel } from './index';
|
|
2
|
+
import type { Message } from '../core/types';
|
|
3
|
+
|
|
4
|
+
export interface IMessageChannelConfig {
|
|
5
|
+
applescriptPath?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class IMessageChannel extends BaseChannel {
|
|
9
|
+
readonly type = 'imessage';
|
|
10
|
+
private config: IMessageChannelConfig;
|
|
11
|
+
|
|
12
|
+
constructor(config: IMessageChannelConfig = {}) {
|
|
13
|
+
super();
|
|
14
|
+
this.config = config;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async start(): Promise<void> {
|
|
18
|
+
try {
|
|
19
|
+
require('macOS iMessage CLI');
|
|
20
|
+
} catch {
|
|
21
|
+
throw new Error('Install macOS iMessage CLI to use the IMessageChannel. Run: npm install macOS iMessage CLI');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async stop(): Promise<void> {
|
|
26
|
+
// cleanup
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async send(chatId: string, text: string): Promise<void> {
|
|
30
|
+
throw new Error('IMessageChannel: not yet connected. Call start() first.');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { BaseChannel } from './index';
|
|
2
|
+
import type { Message } from '../core/types';
|
|
3
|
+
|
|
4
|
+
export interface IRCChannelConfig {
|
|
5
|
+
host: string;
|
|
6
|
+
port?: number;
|
|
7
|
+
nick: string;
|
|
8
|
+
channels: string[];
|
|
9
|
+
tls?: boolean;
|
|
10
|
+
password?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class IRCChannel extends BaseChannel {
|
|
14
|
+
readonly type = 'irc';
|
|
15
|
+
private config: IRCChannelConfig;
|
|
16
|
+
private client: any = null;
|
|
17
|
+
private running = false;
|
|
18
|
+
|
|
19
|
+
constructor(config: IRCChannelConfig) {
|
|
20
|
+
super();
|
|
21
|
+
if (!config.host || !config.nick || !config.channels?.length) {
|
|
22
|
+
throw new Error('IRCChannel requires host, nick, and channels in config');
|
|
23
|
+
}
|
|
24
|
+
this.config = config;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async start(): Promise<void> {
|
|
28
|
+
let IRC: any;
|
|
29
|
+
try {
|
|
30
|
+
IRC = require('irc-framework');
|
|
31
|
+
} catch {
|
|
32
|
+
throw new Error('Install irc-framework to use the IRCChannel. Run: npm install irc-framework');
|
|
33
|
+
}
|
|
34
|
+
this.client = new IRC.Client();
|
|
35
|
+
this.client.connect({
|
|
36
|
+
host: this.config.host,
|
|
37
|
+
port: this.config.port ?? (this.config.tls ? 6697 : 6667),
|
|
38
|
+
nick: this.config.nick,
|
|
39
|
+
tls: this.config.tls ?? false,
|
|
40
|
+
password: this.config.password,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
await new Promise<void>((resolve, reject) => {
|
|
44
|
+
this.client.on('registered', () => {
|
|
45
|
+
for (const ch of this.config.channels) {
|
|
46
|
+
this.client.join(ch);
|
|
47
|
+
}
|
|
48
|
+
resolve();
|
|
49
|
+
});
|
|
50
|
+
this.client.on('error', (err: any) => reject(new Error(`IRC connection error: ${err.message || err}`)));
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
this.running = true;
|
|
54
|
+
|
|
55
|
+
this.client.on('privmsg', async (event: any) => {
|
|
56
|
+
if (!this.handler) return;
|
|
57
|
+
const msg: Message = {
|
|
58
|
+
id: Date.now().toString(),
|
|
59
|
+
role: 'user',
|
|
60
|
+
content: event.message,
|
|
61
|
+
timestamp: Date.now(),
|
|
62
|
+
metadata: { channel: event.target, nick: event.nick },
|
|
63
|
+
};
|
|
64
|
+
await this.handler(msg);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async stop(): Promise<void> {
|
|
69
|
+
if (this.client) {
|
|
70
|
+
this.client.quit('Goodbye');
|
|
71
|
+
this.client = null;
|
|
72
|
+
}
|
|
73
|
+
this.running = false;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async send(target: string, text: string): Promise<void> {
|
|
77
|
+
if (!this.running || !this.client) {
|
|
78
|
+
throw new Error('IRCChannel: not started. Call start() first.');
|
|
79
|
+
}
|
|
80
|
+
this.client.say(target, text);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { BaseChannel } from './index';
|
|
2
|
+
import type { Message } from '../core/types';
|
|
3
|
+
|
|
4
|
+
export interface LINEChannelConfig {
|
|
5
|
+
channelAccessToken?: string;
|
|
6
|
+
channelSecret?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class LINEChannel extends BaseChannel {
|
|
10
|
+
readonly type = 'line';
|
|
11
|
+
private config: LINEChannelConfig;
|
|
12
|
+
|
|
13
|
+
constructor(config: LINEChannelConfig = {}) {
|
|
14
|
+
super();
|
|
15
|
+
this.config = config;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async start(): Promise<void> {
|
|
19
|
+
try {
|
|
20
|
+
require('@line/bot-sdk');
|
|
21
|
+
} catch {
|
|
22
|
+
throw new Error('Install @line/bot-sdk to use the LINEChannel. Run: npm install @line/bot-sdk');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async stop(): Promise<void> {
|
|
27
|
+
// cleanup
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async send(chatId: string, text: string): Promise<void> {
|
|
31
|
+
throw new Error('LINEChannel: not yet connected. Call start() first.');
|
|
32
|
+
}
|
|
33
|
+
}
|