@kafca/agentdock 0.1.7
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 +70 -0
- package/bin/agentdock.mjs +275 -0
- package/build/icon.png +0 -0
- package/dist/renderer/assets/index-BaNpzC6d.js +482 -0
- package/dist/renderer/assets/index-CLWJyO0E.css +11 -0
- package/dist/renderer/favicon.svg +19 -0
- package/dist/renderer/index.html +14 -0
- package/dist/renderer/logo-options.svg +153 -0
- package/dist-electron/electron/knowledge-skill-script.test.js +125 -0
- package/dist-electron/electron/lac-cli.test.js +221 -0
- package/dist-electron/electron/local-core-refactor.test.js +1075 -0
- package/dist-electron/electron/main.js +163 -0
- package/dist-electron/electron/plugin-kernel.test.js +534 -0
- package/dist-electron/electron/preload.js +2 -0
- package/dist-electron/package.json +3 -0
- package/dist-electron/packages/contracts/src/index.js +18 -0
- package/dist-electron/packages/contracts/src/local-core.js +2 -0
- package/dist-electron/packages/core-sdk/src/index.js +406 -0
- package/dist-electron/packages/knowledge-api/src/ai-vector-provider.js +388 -0
- package/dist-electron/packages/knowledge-api/src/index.js +146 -0
- package/dist-electron/packages/knowledge-api/src/sqlite-store.js +467 -0
- package/dist-electron/packages/knowledge-api/src/thread-knowledge-store.js +21 -0
- package/dist-electron/packages/knowledge-api/test/ai-vector-provider.test.js +412 -0
- package/dist-electron/packages/plugin-sdk/src/index.js +2 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +369 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-response-processor.js +110 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-session-coordinator.js +171 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-store.js +635 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-transport.js +190 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-turn-coordinator.js +244 -0
- package/dist-electron/services/local-ai-core/src/acp/workspace-acp-permissions.js +52 -0
- package/dist-electron/services/local-ai-core/src/cli/lac.js +290 -0
- package/dist-electron/services/local-ai-core/src/gateway/local-core-lark-gateway.js +976 -0
- package/dist-electron/services/local-ai-core/src/gateway/local-core-weixin-gateway.js +1143 -0
- package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +291 -0
- package/dist-electron/services/local-ai-core/src/kernel/capability-registry.js +67 -0
- package/dist-electron/services/local-ai-core/src/kernel/diagnostics.js +27 -0
- package/dist-electron/services/local-ai-core/src/kernel/event-bus.js +27 -0
- package/dist-electron/services/local-ai-core/src/kernel/lifecycle-manager.js +85 -0
- package/dist-electron/services/local-ai-core/src/kernel/plugin-registry.js +60 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/agent-localcore-acp-plugin.js +114 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/channel-lark-plugin.js +59 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/channel-weixin-plugin.js +56 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/knowledge-ai-vector-plugin.js +7 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/knowledge-noop-plugin.js +7 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/runtime-capabilities-plugin.js +62 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/scheduler-cron-plugin.js +49 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/scheduler-lark-plugin.js +38 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/scheduler-weixin-plugin.js +38 -0
- package/dist-electron/services/local-ai-core/src/router/workspace-route-config.js +230 -0
- package/dist-electron/services/local-ai-core/src/router/workspace-router-types.js +2 -0
- package/dist-electron/services/local-ai-core/src/router/workspace-router.js +389 -0
- package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +315 -0
- package/dist-electron/services/local-ai-core/src/runtime/local-core-runtime-state.js +282 -0
- package/dist-electron/services/local-ai-core/src/runtime/server.js +465 -0
- package/dist-electron/services/local-ai-core/src/runtime/standalone.js +38 -0
- package/dist-electron/services/local-ai-core/src/scheduler/adapters.js +2 -0
- package/dist-electron/services/local-ai-core/src/scheduler/cron-command-detector.js +70 -0
- package/dist-electron/services/local-ai-core/src/scheduler/cron.js +53 -0
- package/dist-electron/services/local-ai-core/src/scheduler/execution-policy.js +2 -0
- package/dist-electron/services/local-ai-core/src/scheduler/lark-execution-policies.js +66 -0
- package/dist-electron/services/local-ai-core/src/scheduler/lark-schedule-adapter.js +77 -0
- package/dist-electron/services/local-ai-core/src/scheduler/scheduled-conversation-executor.js +46 -0
- package/dist-electron/services/local-ai-core/src/scheduler/scheduler-run-lifecycle.js +64 -0
- package/dist-electron/services/local-ai-core/src/scheduler/scheduler-service.js +133 -0
- package/dist-electron/services/local-ai-core/src/scheduler/weixin-execution-policies.js +66 -0
- package/dist-electron/services/local-ai-core/src/scheduler/weixin-schedule-adapter.js +78 -0
- package/dist-electron/services/local-ai-core/src/thread/workspace-thread-id.js +17 -0
- package/dist-electron/services/local-ai-core/src/thread/workspace-thread-mappers.js +43 -0
- package/dist-electron/shared/desktop.js +195 -0
- package/dist-electron/src/api/client.js +73 -0
- package/dist-electron/src/api/sessions.js +21 -0
- package/dist-electron/src/lib/session-utils.js +51 -0
- package/dist-electron/src/pages/Threads/thread-chat-model.js +246 -0
- package/dist-electron/src/pages/Threads/thread-chat-model.test.js +76 -0
- package/dist-electron/src/pages/Threads/thread-chat-permission.js +26 -0
- package/dist-electron/src/pages/Threads/thread-chat-permission.test.js +102 -0
- package/dist-electron/src/pages/Threads/thread-chat-task-state.js +65 -0
- package/package.json +146 -0
package/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# AgentDock
|
|
2
|
+
|
|
3
|
+
基于 Local AI Core 的本地桌面 AI 工作台,内置原生 Feishu/Lark 网关与本地 ACP 会话运行时。
|
|
4
|
+
|
|
5
|
+
## 运行模式
|
|
6
|
+
|
|
7
|
+
- **桌面模式** — Electron 作为壳进程启动本地 Local AI Core,并加载桌面 UI
|
|
8
|
+
- **Local AI Core 模式** — 通过本地 `127.0.0.1:9831` 提供 runtime、chat、知识库与 Lark 网关能力
|
|
9
|
+
|
|
10
|
+
## 技术栈
|
|
11
|
+
|
|
12
|
+
React 19 · Electron 35 · Vite · TypeScript · Tailwind CSS · Zustand · i18next · react-markdown
|
|
13
|
+
|
|
14
|
+
## 快速开始
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pnpm install
|
|
18
|
+
pnpm dev # 启动开发环境(Vite + Electron)
|
|
19
|
+
pnpm start:core # 启动已构建的 Local AI Core
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## macOS 打开应用
|
|
23
|
+
|
|
24
|
+
如果安装后提示应用无法打开,可先清除隔离属性再启动:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
xattr -cr /Applications/AgentDock.app
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## 常用命令
|
|
31
|
+
|
|
32
|
+
| 命令 | 说明 |
|
|
33
|
+
|---|---|
|
|
34
|
+
| `pnpm dev` | 启动开发环境 |
|
|
35
|
+
| `pnpm dev:web` | 仅启动 Web 开发服务器 |
|
|
36
|
+
| `pnpm dev:core` | 构建并启动 Local AI Core |
|
|
37
|
+
| `pnpm build` | 完整生产构建 |
|
|
38
|
+
| `pnpm build:renderer` | 仅构建 React 前端 |
|
|
39
|
+
| `pnpm build:electron` | 仅构建 Electron 主进程 |
|
|
40
|
+
| `pnpm build:core` | 构建 Local AI Core 产物 |
|
|
41
|
+
| `pnpm start:core` | 运行已构建的 Local AI Core |
|
|
42
|
+
| `pnpm start:prod` | 运行已构建的 Electron 应用 |
|
|
43
|
+
| `pnpm e2e:smoke` | E2E 冒烟测试 |
|
|
44
|
+
|
|
45
|
+
## 环境变量
|
|
46
|
+
|
|
47
|
+
| 变量 | 说明 |
|
|
48
|
+
|---|---|
|
|
49
|
+
| `AI_WORKSTATION_USER_DATA_DIR` | 用户数据目录 |
|
|
50
|
+
| `AI_WORKSTATION_SMOKE_OUTPUT` | 冒烟测试输出路径 |
|
|
51
|
+
| `AI_WORKSTATION_SMOKE_SCENARIO` | 冒烟测试场景 |
|
|
52
|
+
| `AI_WORKSTATION_FORCE_RUNTIME_STATUS_ERROR` | 强制触发运行时状态错误,用于测试 |
|
|
53
|
+
| `AI_WORKSTATION_DEV_SERVER_URL` | Electron 开发模式连接的前端地址 |
|
|
54
|
+
|
|
55
|
+
## 项目结构
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
├── electron/ # Electron 主进程壳
|
|
59
|
+
├── apps/ # 未来的桌面/Web 前端壳目录
|
|
60
|
+
├── packages/ # contracts、core-sdk、knowledge-api
|
|
61
|
+
├── services/ # Local AI Core
|
|
62
|
+
├── src/ # React 渲染进程
|
|
63
|
+
│ ├── pages/ # 页面组件
|
|
64
|
+
│ ├── components/ # UI 组件库
|
|
65
|
+
│ ├── api/ # API 客户端
|
|
66
|
+
│ ├── store/ # Zustand 状态管理
|
|
67
|
+
│ └── types/ # 类型定义
|
|
68
|
+
├── shared/ # 跨进程共享类型
|
|
69
|
+
└── scripts/ # 构建/启动脚本
|
|
70
|
+
```
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import http from 'node:http';
|
|
3
|
+
import https from 'node:https';
|
|
4
|
+
import { spawn } from 'node:child_process';
|
|
5
|
+
import { createReadStream, existsSync, statSync } from 'node:fs';
|
|
6
|
+
import { homedir } from 'node:os';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
9
|
+
|
|
10
|
+
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
11
|
+
const rendererRoot = path.join(packageRoot, 'dist', 'renderer');
|
|
12
|
+
const coreEntry = path.join(packageRoot, 'dist-electron', 'services', 'local-ai-core', 'src', 'runtime', 'standalone.js');
|
|
13
|
+
const defaultHost = '127.0.0.1';
|
|
14
|
+
const defaultWebPort = 14173;
|
|
15
|
+
const defaultCoreOrigin = 'http://127.0.0.1:9831';
|
|
16
|
+
|
|
17
|
+
function parseArgs(argv) {
|
|
18
|
+
const flags = {};
|
|
19
|
+
const positional = [];
|
|
20
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
21
|
+
const arg = argv[index];
|
|
22
|
+
if (!arg.startsWith('--')) {
|
|
23
|
+
positional.push(arg);
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const [rawKey, rawValue] = arg.slice(2).split('=', 2);
|
|
27
|
+
const key = rawKey.trim();
|
|
28
|
+
if (!key) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (typeof rawValue === 'string') {
|
|
32
|
+
flags[key] = rawValue;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const next = argv[index + 1];
|
|
36
|
+
if (next && !next.startsWith('--')) {
|
|
37
|
+
flags[key] = next;
|
|
38
|
+
index += 1;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
flags[key] = 'true';
|
|
42
|
+
}
|
|
43
|
+
return { command: positional[0] || 'help', flags };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function readFlag(flags, name, fallback) {
|
|
47
|
+
const value = flags[name];
|
|
48
|
+
if (value === undefined || value === '') {
|
|
49
|
+
return fallback;
|
|
50
|
+
}
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function readPort(flags, name, fallback) {
|
|
55
|
+
const value = Number(readFlag(flags, name, fallback));
|
|
56
|
+
if (!Number.isInteger(value) || value <= 0 || value > 65535) {
|
|
57
|
+
throw new Error(`Invalid --${name}: ${readFlag(flags, name, fallback)}`);
|
|
58
|
+
}
|
|
59
|
+
return value;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function printHelp() {
|
|
63
|
+
console.log(`AgentDock
|
|
64
|
+
|
|
65
|
+
Usage:
|
|
66
|
+
agentdock core
|
|
67
|
+
agentdock web [--host 127.0.0.1] [--port 14173] [--core-origin http://127.0.0.1:9831]
|
|
68
|
+
agentdock serve [--host 127.0.0.1] [--port 14173] [--core-origin http://127.0.0.1:9831]
|
|
69
|
+
|
|
70
|
+
Examples:
|
|
71
|
+
agentdock serve
|
|
72
|
+
agentdock serve --host 0.0.0.0
|
|
73
|
+
agentdock web --port 14173
|
|
74
|
+
`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function ensureBuildOutput() {
|
|
78
|
+
if (!existsSync(rendererRoot)) {
|
|
79
|
+
throw new Error(`Missing renderer build output: ${rendererRoot}`);
|
|
80
|
+
}
|
|
81
|
+
if (!existsSync(coreEntry)) {
|
|
82
|
+
throw new Error(`Missing Local AI Core build output: ${coreEntry}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function coreEnv() {
|
|
87
|
+
return {
|
|
88
|
+
...process.env,
|
|
89
|
+
AI_WORKSTATION_USER_DATA_DIR:
|
|
90
|
+
process.env.AI_WORKSTATION_USER_DATA_DIR || path.join(homedir(), '.agentdock'),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function startCoreProcess({ stdio = 'inherit' } = {}) {
|
|
95
|
+
ensureBuildOutput();
|
|
96
|
+
return spawn(process.execPath, [coreEntry], {
|
|
97
|
+
cwd: process.cwd(),
|
|
98
|
+
env: coreEnv(),
|
|
99
|
+
stdio,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async function isCoreHealthy(coreOrigin = defaultCoreOrigin) {
|
|
104
|
+
try {
|
|
105
|
+
const response = await fetch(`${coreOrigin.replace(/\/+$/, '')}/api/local/v1/health`, {
|
|
106
|
+
signal: AbortSignal.timeout(500),
|
|
107
|
+
});
|
|
108
|
+
const json = await response.json();
|
|
109
|
+
return response.ok && json?.ok && json?.data?.name === 'local-ai-core';
|
|
110
|
+
} catch {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async function waitForCore(coreOrigin = defaultCoreOrigin, timeoutMs = 15000) {
|
|
116
|
+
const startedAt = Date.now();
|
|
117
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
118
|
+
if (await isCoreHealthy(coreOrigin)) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
await new Promise((resolve) => setTimeout(resolve, 250));
|
|
122
|
+
}
|
|
123
|
+
throw new Error(`Local AI Core did not become healthy at ${coreOrigin} within ${timeoutMs}ms`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function mimeType(filePath) {
|
|
127
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
128
|
+
return {
|
|
129
|
+
'.css': 'text/css; charset=utf-8',
|
|
130
|
+
'.html': 'text/html; charset=utf-8',
|
|
131
|
+
'.js': 'text/javascript; charset=utf-8',
|
|
132
|
+
'.json': 'application/json; charset=utf-8',
|
|
133
|
+
'.map': 'application/json; charset=utf-8',
|
|
134
|
+
'.png': 'image/png',
|
|
135
|
+
'.svg': 'image/svg+xml',
|
|
136
|
+
'.ico': 'image/x-icon',
|
|
137
|
+
'.webp': 'image/webp',
|
|
138
|
+
'.woff': 'font/woff',
|
|
139
|
+
'.woff2': 'font/woff2',
|
|
140
|
+
}[ext] || 'application/octet-stream';
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function sendFile(res, filePath) {
|
|
144
|
+
const stream = createReadStream(filePath);
|
|
145
|
+
res.statusCode = 200;
|
|
146
|
+
res.setHeader('Content-Type', mimeType(filePath));
|
|
147
|
+
stream.on('error', () => {
|
|
148
|
+
if (!res.headersSent) {
|
|
149
|
+
res.statusCode = 500;
|
|
150
|
+
}
|
|
151
|
+
res.end('Internal server error');
|
|
152
|
+
});
|
|
153
|
+
stream.pipe(res);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function resolveStaticPath(urlPath) {
|
|
157
|
+
const decodedPath = decodeURIComponent(urlPath);
|
|
158
|
+
const candidate = path.resolve(rendererRoot, `.${decodedPath}`);
|
|
159
|
+
if (!candidate.startsWith(`${rendererRoot}${path.sep}`) && candidate !== rendererRoot) {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
if (existsSync(candidate) && statSync(candidate).isFile()) {
|
|
163
|
+
return candidate;
|
|
164
|
+
}
|
|
165
|
+
const indexPath = path.join(rendererRoot, 'index.html');
|
|
166
|
+
if (!path.extname(candidate) && existsSync(indexPath)) {
|
|
167
|
+
return indexPath;
|
|
168
|
+
}
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function proxyToCore(req, res, coreOrigin) {
|
|
173
|
+
const upstream = new URL(req.url || '/', coreOrigin);
|
|
174
|
+
const client = upstream.protocol === 'https:' ? https : http;
|
|
175
|
+
const proxyReq = client.request(
|
|
176
|
+
{
|
|
177
|
+
protocol: upstream.protocol,
|
|
178
|
+
hostname: upstream.hostname,
|
|
179
|
+
port: upstream.port,
|
|
180
|
+
method: req.method,
|
|
181
|
+
path: `${upstream.pathname}${upstream.search}`,
|
|
182
|
+
headers: {
|
|
183
|
+
...req.headers,
|
|
184
|
+
host: upstream.host,
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
(proxyRes) => {
|
|
188
|
+
res.writeHead(proxyRes.statusCode || 502, proxyRes.headers);
|
|
189
|
+
proxyRes.pipe(res);
|
|
190
|
+
},
|
|
191
|
+
);
|
|
192
|
+
proxyReq.on('error', (error) => {
|
|
193
|
+
res.statusCode = 502;
|
|
194
|
+
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
|
|
195
|
+
res.end(`Local AI Core proxy failed: ${error.message}`);
|
|
196
|
+
});
|
|
197
|
+
req.pipe(proxyReq);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function startWebServer({ host, port, coreOrigin }) {
|
|
201
|
+
ensureBuildOutput();
|
|
202
|
+
const normalizedCoreOrigin = coreOrigin.replace(/\/+$/, '');
|
|
203
|
+
const server = http.createServer((req, res) => {
|
|
204
|
+
const requestUrl = new URL(req.url || '/', `http://${req.headers.host || `${host}:${port}`}`);
|
|
205
|
+
if (requestUrl.pathname === '/api/local/v1' || requestUrl.pathname.startsWith('/api/local/v1/')) {
|
|
206
|
+
proxyToCore(req, res, normalizedCoreOrigin);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const filePath = resolveStaticPath(requestUrl.pathname);
|
|
210
|
+
if (!filePath) {
|
|
211
|
+
res.statusCode = 404;
|
|
212
|
+
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
|
|
213
|
+
res.end('Not found');
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
sendFile(res, filePath);
|
|
217
|
+
});
|
|
218
|
+
server.listen(port, host, () => {
|
|
219
|
+
console.log(`[agentdock] Web listening at http://${host}:${port}`);
|
|
220
|
+
console.log(`[agentdock] Proxying /api/local/v1 to ${normalizedCoreOrigin}`);
|
|
221
|
+
});
|
|
222
|
+
return server;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async function runCore() {
|
|
226
|
+
const child = startCoreProcess();
|
|
227
|
+
child.on('exit', (code, signal) => {
|
|
228
|
+
process.exitCode = code ?? (signal ? 1 : 0);
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
async function runWeb(flags) {
|
|
233
|
+
const host = readFlag(flags, 'host', defaultHost);
|
|
234
|
+
const port = readPort(flags, 'port', defaultWebPort);
|
|
235
|
+
const coreOrigin = readFlag(flags, 'core-origin', defaultCoreOrigin);
|
|
236
|
+
startWebServer({ host, port, coreOrigin });
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async function runServe(flags) {
|
|
240
|
+
const host = readFlag(flags, 'host', defaultHost);
|
|
241
|
+
const port = readPort(flags, 'port', defaultWebPort);
|
|
242
|
+
const coreOrigin = readFlag(flags, 'core-origin', defaultCoreOrigin);
|
|
243
|
+
let coreProcess = null;
|
|
244
|
+
if (!(await isCoreHealthy(coreOrigin))) {
|
|
245
|
+
coreProcess = startCoreProcess();
|
|
246
|
+
await waitForCore(coreOrigin);
|
|
247
|
+
}
|
|
248
|
+
const server = startWebServer({ host, port, coreOrigin });
|
|
249
|
+
const shutdown = () => {
|
|
250
|
+
server.close();
|
|
251
|
+
if (coreProcess) {
|
|
252
|
+
coreProcess.kill('SIGTERM');
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
process.once('SIGINT', shutdown);
|
|
256
|
+
process.once('SIGTERM', shutdown);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const { command, flags } = parseArgs(process.argv.slice(2));
|
|
260
|
+
|
|
261
|
+
try {
|
|
262
|
+
if (command === 'core') {
|
|
263
|
+
await runCore();
|
|
264
|
+
} else if (command === 'web') {
|
|
265
|
+
await runWeb(flags);
|
|
266
|
+
} else if (command === 'serve') {
|
|
267
|
+
await runServe(flags);
|
|
268
|
+
} else {
|
|
269
|
+
printHelp();
|
|
270
|
+
process.exitCode = command === 'help' || command === '--help' || command === '-h' ? 0 : 1;
|
|
271
|
+
}
|
|
272
|
+
} catch (error) {
|
|
273
|
+
console.error(`[agentdock] ${error instanceof Error ? error.message : String(error)}`);
|
|
274
|
+
process.exitCode = 1;
|
|
275
|
+
}
|
package/build/icon.png
ADDED
|
Binary file
|