@next-open-ai/openbot 0.1.8 → 0.2.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 +6 -6
- package/{desktop → apps/desktop}/README.md +3 -3
- package/{desktop/renderer/dist/assets/index-DL_hPION.js → apps/desktop/renderer/dist/assets/index-BOS-F8a4.js} +37 -37
- package/{desktop/renderer/dist/assets/index-BBoPEPR6.css → apps/desktop/renderer/dist/assets/index-DxqxayUL.css} +2 -2
- package/{desktop → apps/desktop}/renderer/dist/index.html +2 -2
- package/dist/cli/cli.d.ts +2 -0
- package/dist/cli/cli.js +172 -0
- package/dist/cli.d.ts +4 -1
- package/dist/cli.js +4 -172
- package/dist/gateway/auth-hooks.d.ts +17 -0
- package/dist/gateway/auth-hooks.js +19 -0
- package/dist/gateway/channel-handler.d.ts +6 -0
- package/dist/gateway/channel-handler.js +3 -0
- package/dist/gateway/index.d.ts +1 -1
- package/dist/gateway/index.js +1 -1
- package/dist/gateway/methods/agent-cancel.js +1 -1
- package/dist/gateway/methods/agent-chat.js +3 -3
- package/dist/gateway/methods/install-skill-from-path.js +1 -1
- package/dist/gateway/methods/run-scheduled-task.js +3 -3
- package/dist/gateway/paths.d.ts +20 -0
- package/dist/gateway/paths.js +19 -0
- package/dist/gateway/server.d.ts +2 -4
- package/dist/gateway/server.js +98 -208
- package/dist/gateway/sse-handler.d.ts +6 -0
- package/dist/gateway/sse-handler.js +3 -0
- package/dist/gateway/voice-handler.d.ts +12 -0
- package/dist/gateway/voice-handler.js +18 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.js +5 -5
- package/dist/server/agents/agents.service.js +1 -1
- package/dist/server/bootstrap.d.ts +15 -0
- package/dist/server/bootstrap.js +38 -0
- package/dist/server/config/config.service.d.ts +1 -1
- package/dist/server/config/config.service.js +1 -1
- package/dist/server/database/database.service.d.ts +14 -6
- package/dist/server/database/database.service.js +99 -32
- package/dist/server/main.js +6 -19
- package/dist/server/skills/skills.service.js +1 -1
- package/dist/server/workspace/workspace.service.js +1 -1
- package/package.json +23 -20
- package/desktop/renderer/dist/assets/logo-RfPiqt5-.png +0 -0
- /package/dist/{agent → core/agent}/agent-dir.d.ts +0 -0
- /package/dist/{agent → core/agent}/agent-dir.js +0 -0
- /package/dist/{agent → core/agent}/agent-manager.d.ts +0 -0
- /package/dist/{agent → core/agent}/agent-manager.js +0 -0
- /package/dist/{agent → core/agent}/config-manager.d.ts +0 -0
- /package/dist/{agent → core/agent}/config-manager.js +0 -0
- /package/dist/{agent → core/agent}/run.d.ts +0 -0
- /package/dist/{agent → core/agent}/run.js +0 -0
- /package/dist/{agent → core/agent}/skills.d.ts +0 -0
- /package/dist/{agent → core/agent}/skills.js +0 -0
- /package/dist/{config → core/config}/desktop-config.d.ts +0 -0
- /package/dist/{config → core/config}/desktop-config.js +0 -0
- /package/dist/{config → core/config}/provider-support-default.d.ts +0 -0
- /package/dist/{config → core/config}/provider-support-default.js +0 -0
- /package/dist/{installer → core/installer}/index.d.ts +0 -0
- /package/dist/{installer → core/installer}/index.js +0 -0
- /package/dist/{installer → core/installer}/skill-installer.d.ts +0 -0
- /package/dist/{installer → core/installer}/skill-installer.js +0 -0
- /package/dist/{memory → core/memory}/build-summary.d.ts +0 -0
- /package/dist/{memory → core/memory}/build-summary.js +0 -0
- /package/dist/{memory → core/memory}/compaction-extension.d.ts +0 -0
- /package/dist/{memory → core/memory}/compaction-extension.js +0 -0
- /package/dist/{memory → core/memory}/embedding.d.ts +0 -0
- /package/dist/{memory → core/memory}/embedding.js +0 -0
- /package/dist/{memory → core/memory}/index.d.ts +0 -0
- /package/dist/{memory → core/memory}/index.js +0 -0
- /package/dist/{memory → core/memory}/remote-embedding.d.ts +0 -0
- /package/dist/{memory → core/memory}/remote-embedding.js +0 -0
- /package/dist/{memory → core/memory}/types.d.ts +0 -0
- /package/dist/{memory → core/memory}/types.js +0 -0
- /package/dist/{memory → core/memory}/vector-store.d.ts +0 -0
- /package/dist/{memory → core/memory}/vector-store.js +0 -0
- /package/dist/{tools → core/tools}/browser-tool.d.ts +0 -0
- /package/dist/{tools → core/tools}/browser-tool.js +0 -0
- /package/dist/{tools → core/tools}/index.d.ts +0 -0
- /package/dist/{tools → core/tools}/index.js +0 -0
- /package/dist/{tools → core/tools}/install-skill-tool.d.ts +0 -0
- /package/dist/{tools → core/tools}/install-skill-tool.js +0 -0
- /package/dist/{tools → core/tools}/save-experience-tool.d.ts +0 -0
- /package/dist/{tools → core/tools}/save-experience-tool.js +0 -0
package/dist/cli/cli.js
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
import { getOpenbotAgentDir } from "../core/agent/agent-dir.js";
|
|
7
|
+
import { run } from "../core/agent/run.js";
|
|
8
|
+
import { loadDesktopAgentConfig, getBoundAgentIdForCli, setProviderApiKey, setDefaultModel, getDesktopConfigList, syncDesktopConfigToModelsJson, ensureDesktopConfigInitialized, } from "../core/config/desktop-config.js";
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
10
|
+
const PKG = require("../../package.json");
|
|
11
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
const PKG_ROOT = join(__dirname, "..", "..");
|
|
13
|
+
async function runAction(positionalPrompt, opts) {
|
|
14
|
+
const skillPaths = opts.skillPath || [];
|
|
15
|
+
const agentId = (opts.agent && String(opts.agent).trim()) || (await getBoundAgentIdForCli());
|
|
16
|
+
const prompt = (opts.prompt ?? positionalPrompt ?? "").trim();
|
|
17
|
+
if (!prompt) {
|
|
18
|
+
console.error("Error: 请提供提示词(位置参数或 --prompt)");
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
console.error(`[openbot] Using agent: ${agentId}${!opts.agent ? " (default from config)" : ""}`);
|
|
22
|
+
const needDesktop = opts.apiKey === undefined || opts.provider === undefined || opts.model === undefined;
|
|
23
|
+
const desktopConfig = needDesktop ? await loadDesktopAgentConfig(agentId) : null;
|
|
24
|
+
const provider = opts.provider ?? desktopConfig?.provider ?? "deepseek";
|
|
25
|
+
const model = opts.model ?? desktopConfig?.model ?? "deepseek-chat";
|
|
26
|
+
const apiKey = opts.apiKey ?? process.env.OPENAI_API_KEY ?? desktopConfig?.apiKey ?? "";
|
|
27
|
+
if (desktopConfig && (desktopConfig.provider || desktopConfig.model)) {
|
|
28
|
+
console.error(`[openbot] Using model: ${provider}/${model} (from desktop config)`);
|
|
29
|
+
}
|
|
30
|
+
if (opts.timing)
|
|
31
|
+
process.env.OPENBOT_TIMING = "1";
|
|
32
|
+
const workspaceName = desktopConfig?.workspace ?? agentId;
|
|
33
|
+
try {
|
|
34
|
+
const result = await run({
|
|
35
|
+
workspace: workspaceName,
|
|
36
|
+
skillPaths,
|
|
37
|
+
userPrompt: prompt,
|
|
38
|
+
dryRun: opts.dryRun ?? false,
|
|
39
|
+
model,
|
|
40
|
+
provider,
|
|
41
|
+
agentDir: opts.agentDir ?? getOpenbotAgentDir(),
|
|
42
|
+
apiKey: apiKey || undefined,
|
|
43
|
+
});
|
|
44
|
+
if (result.dryRun) {
|
|
45
|
+
console.log("=== System prompt (skills) ===");
|
|
46
|
+
console.log(result.systemPrompt);
|
|
47
|
+
console.log("\n=== User prompt ===");
|
|
48
|
+
console.log(result.userPrompt);
|
|
49
|
+
console.log("\n(dry-run: 未调用 LLM,设置 OPENAI_API_KEY 可实际调用)");
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
// Content is already streamed by run()
|
|
53
|
+
if (!result.dryRun &&
|
|
54
|
+
(result.assistantContent === undefined || result.assistantContent === "")) {
|
|
55
|
+
console.warn("(模型返回为空;若此前有工具调用提示,说明当前为单轮模式,模型会基于技能描述直接以文本回答。)");
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
console.error(err);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const program = new Command();
|
|
64
|
+
program
|
|
65
|
+
.name("openbot")
|
|
66
|
+
.description("CLI to run prompts with skill paths (Agent Skills style)")
|
|
67
|
+
.version(PKG.version, "-v, --version", "显示版本号")
|
|
68
|
+
.option("-s, --skill-path <paths...>", "Additional skill paths to load")
|
|
69
|
+
.option("-a, --agent <id>", "指定智能体 ID,不传则使用桌面配置中的缺省智能体")
|
|
70
|
+
.option("-p, --prompt <text>", "用户提示词(与位置参数二选一)")
|
|
71
|
+
.option("--dry-run", "只输出组装的 system/user 内容,不调用 LLM")
|
|
72
|
+
.option("--model <id>", "模型 ID", "deepseek-chat")
|
|
73
|
+
.option("--provider <name>", "Provider(pi ModelRegistry);可选 deepseek、dashscope、openai", "deepseek")
|
|
74
|
+
.option("--agent-dir <path>", "Agent 配置目录(默认 ~/.openbot/agent)", getOpenbotAgentDir())
|
|
75
|
+
.option("--api-key <key>", "API Key(不传则使用环境变量 OPENAI_API_KEY)")
|
|
76
|
+
.option("--timing", "打印每轮 LLM 与 tool 耗时到 stderr")
|
|
77
|
+
.option("--max-tool-turns <n>", "最大工具调用轮数(默认 30);可设环境变量 OPENBOT_MAX_TOOL_TURNS", (v) => parseInt(v, 10) || 0, 0)
|
|
78
|
+
.argument("[prompt]", "用户提示词(与 --prompt 二选一)")
|
|
79
|
+
.action(async (positionalPrompt) => {
|
|
80
|
+
await runAction(positionalPrompt, program.opts());
|
|
81
|
+
});
|
|
82
|
+
program.addHelpText("after", `
|
|
83
|
+
Environment:
|
|
84
|
+
DEEPSEEK_API_KEY 默认 provider 为 deepseek 时使用;不设时回退 OPENAI_API_KEY
|
|
85
|
+
OPENAI_API_KEY 通用 API Key(可被 --api-key 覆盖)
|
|
86
|
+
DASHSCOPE_API_KEY provider=dashscope 时使用;不设时回退 OPENAI_API_KEY
|
|
87
|
+
OPENAI_BASE_URL 可选,在 pi 未找到模型时使用的 endpoint
|
|
88
|
+
OPENBOT_AGENT_DIR 缺省 agent 目录(默认 ~/.openbot/agent)
|
|
89
|
+
OPENBOT_TIMING=1 等同 --timing
|
|
90
|
+
OPENBOT_ALLOW_RUN_CODE 缺省 1(启用 run_python);设为 0 关闭
|
|
91
|
+
OPENBOT_MAX_TOOL_TURNS 最大工具轮数(默认 30)
|
|
92
|
+
|
|
93
|
+
Examples:
|
|
94
|
+
openbot "总结一下当前有哪些技能"
|
|
95
|
+
openbot -a my-agent "总结一下当前有哪些技能" 使用指定智能体
|
|
96
|
+
openbot -s ./skills "总结一下当前有哪些技能"
|
|
97
|
+
openbot -s ./my-skills --prompt "用 weather 技能查北京天气" --dry-run
|
|
98
|
+
`);
|
|
99
|
+
// Gateway server command
|
|
100
|
+
program
|
|
101
|
+
.command("gateway")
|
|
102
|
+
.description("Start WebSocket gateway server")
|
|
103
|
+
.option("-p, --port <port>", "Port to listen on", "38080")
|
|
104
|
+
.action(async (options) => {
|
|
105
|
+
const port = parseInt(options.port, 10);
|
|
106
|
+
if (isNaN(port) || port <= 0 || port > 65535) {
|
|
107
|
+
console.error("Error: Invalid port number");
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
const { startGatewayServer } = await import("../gateway/index.js");
|
|
111
|
+
const { close } = await startGatewayServer(port);
|
|
112
|
+
// Handle graceful shutdown
|
|
113
|
+
const shutdown = async () => {
|
|
114
|
+
console.log("\nShutting down...");
|
|
115
|
+
await close();
|
|
116
|
+
process.exit(0);
|
|
117
|
+
};
|
|
118
|
+
process.on("SIGINT", shutdown);
|
|
119
|
+
process.on("SIGTERM", shutdown);
|
|
120
|
+
});
|
|
121
|
+
// Login command(写入桌面 config;可选 model,不传则取该 provider 第一个模型,补齐后可直接运行)
|
|
122
|
+
program
|
|
123
|
+
.command("login")
|
|
124
|
+
.description("Save API key for a provider to desktop config (~/.openbot/desktop); optional model, default first model")
|
|
125
|
+
.argument("<provider>", "Provider name (e.g., deepseek, dashscope, openai)")
|
|
126
|
+
.argument("<apiKey>", "API Key")
|
|
127
|
+
.argument("[model]", "Model ID (optional; default: first model for provider)")
|
|
128
|
+
.action(async (provider, apiKey, model) => {
|
|
129
|
+
await setProviderApiKey(provider, apiKey, model);
|
|
130
|
+
console.log(`[openbot] API key saved for provider: ${provider}`);
|
|
131
|
+
});
|
|
132
|
+
// Config command
|
|
133
|
+
const configCmd = program.command("config").description("Manage configurations");
|
|
134
|
+
configCmd
|
|
135
|
+
.command("set-model")
|
|
136
|
+
.description("Set default provider and model in desktop config (~/.openbot/desktop)")
|
|
137
|
+
.argument("<provider>", "Provider name")
|
|
138
|
+
.argument("<modelId>", "Model ID")
|
|
139
|
+
.action(async (provider, modelId) => {
|
|
140
|
+
await setDefaultModel(provider, modelId);
|
|
141
|
+
console.log(`[openbot] Default model set: ${provider}/${modelId}`);
|
|
142
|
+
});
|
|
143
|
+
configCmd
|
|
144
|
+
.command("list")
|
|
145
|
+
.description("List desktop config (centralized config source)")
|
|
146
|
+
.action(async () => {
|
|
147
|
+
const list = await getDesktopConfigList();
|
|
148
|
+
if (list.providers.length === 0) {
|
|
149
|
+
console.log("No providers in desktop config. Run: openbot login <provider> <apiKey>");
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
console.log(`Default: ${list.defaultProvider} / ${list.defaultModel}\n`);
|
|
153
|
+
console.table(list.providers.map((r) => ({
|
|
154
|
+
Provider: r.provider,
|
|
155
|
+
"Default Model": r.defaultModel,
|
|
156
|
+
"API Key": r.hasKey ? "✅" : "❌",
|
|
157
|
+
})));
|
|
158
|
+
});
|
|
159
|
+
configCmd
|
|
160
|
+
.command("sync")
|
|
161
|
+
.description("Sync desktop config to ~/.openbot/agent/models.json for pi-agent")
|
|
162
|
+
.action(async () => {
|
|
163
|
+
await syncDesktopConfigToModelsJson();
|
|
164
|
+
console.log("[openbot] Synced desktop providers to agent models.json");
|
|
165
|
+
});
|
|
166
|
+
(async () => {
|
|
167
|
+
await ensureDesktopConfigInitialized();
|
|
168
|
+
await program.parseAsync(process.argv);
|
|
169
|
+
})().catch((err) => {
|
|
170
|
+
console.error(err);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
});
|
package/dist/cli.d.ts
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1,173 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import
|
|
6
|
-
import { getOpenbotAgentDir } from "./agent/agent-dir.js";
|
|
7
|
-
import { run } from "./agent/run.js";
|
|
8
|
-
import { loadDesktopAgentConfig, getBoundAgentIdForCli, setProviderApiKey, setDefaultModel, getDesktopConfigList, syncDesktopConfigToModelsJson, ensureDesktopConfigInitialized, } from "./config/desktop-config.js";
|
|
9
|
-
const require = createRequire(import.meta.url);
|
|
10
|
-
const PKG = require("../package.json");
|
|
11
|
-
// Based on distillate, the package root is one level up from dist/
|
|
12
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
|
-
const PKG_ROOT = join(__dirname, "..");
|
|
14
|
-
async function runAction(positionalPrompt, opts) {
|
|
15
|
-
const skillPaths = opts.skillPath || [];
|
|
16
|
-
const agentId = (opts.agent && String(opts.agent).trim()) || (await getBoundAgentIdForCli());
|
|
17
|
-
const prompt = (opts.prompt ?? positionalPrompt ?? "").trim();
|
|
18
|
-
if (!prompt) {
|
|
19
|
-
console.error("Error: 请提供提示词(位置参数或 --prompt)");
|
|
20
|
-
process.exit(1);
|
|
21
|
-
}
|
|
22
|
-
console.error(`[openbot] Using agent: ${agentId}${!opts.agent ? " (default from config)" : ""}`);
|
|
23
|
-
const needDesktop = opts.apiKey === undefined || opts.provider === undefined || opts.model === undefined;
|
|
24
|
-
const desktopConfig = needDesktop ? await loadDesktopAgentConfig(agentId) : null;
|
|
25
|
-
const provider = opts.provider ?? desktopConfig?.provider ?? "deepseek";
|
|
26
|
-
const model = opts.model ?? desktopConfig?.model ?? "deepseek-chat";
|
|
27
|
-
const apiKey = opts.apiKey ?? process.env.OPENAI_API_KEY ?? desktopConfig?.apiKey ?? "";
|
|
28
|
-
if (desktopConfig && (desktopConfig.provider || desktopConfig.model)) {
|
|
29
|
-
console.error(`[openbot] Using model: ${provider}/${model} (from desktop config)`);
|
|
30
|
-
}
|
|
31
|
-
if (opts.timing)
|
|
32
|
-
process.env.OPENBOT_TIMING = "1";
|
|
33
|
-
const workspaceName = desktopConfig?.workspace ?? agentId;
|
|
34
|
-
try {
|
|
35
|
-
const result = await run({
|
|
36
|
-
workspace: workspaceName,
|
|
37
|
-
skillPaths,
|
|
38
|
-
userPrompt: prompt,
|
|
39
|
-
dryRun: opts.dryRun ?? false,
|
|
40
|
-
model,
|
|
41
|
-
provider,
|
|
42
|
-
agentDir: opts.agentDir ?? getOpenbotAgentDir(),
|
|
43
|
-
apiKey: apiKey || undefined,
|
|
44
|
-
});
|
|
45
|
-
if (result.dryRun) {
|
|
46
|
-
console.log("=== System prompt (skills) ===");
|
|
47
|
-
console.log(result.systemPrompt);
|
|
48
|
-
console.log("\n=== User prompt ===");
|
|
49
|
-
console.log(result.userPrompt);
|
|
50
|
-
console.log("\n(dry-run: 未调用 LLM,设置 OPENAI_API_KEY 可实际调用)");
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
// Content is already streamed by run()
|
|
54
|
-
if (!result.dryRun &&
|
|
55
|
-
(result.assistantContent === undefined || result.assistantContent === "")) {
|
|
56
|
-
console.warn("(模型返回为空;若此前有工具调用提示,说明当前为单轮模式,模型会基于技能描述直接以文本回答。)");
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
catch (err) {
|
|
60
|
-
console.error(err);
|
|
61
|
-
process.exit(1);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
const program = new Command();
|
|
65
|
-
program
|
|
66
|
-
.name("openbot")
|
|
67
|
-
.description("CLI to run prompts with skill paths (Agent Skills style)")
|
|
68
|
-
.version(PKG.version, "-v, --version", "显示版本号")
|
|
69
|
-
.option("-s, --skill-path <paths...>", "Additional skill paths to load")
|
|
70
|
-
.option("-a, --agent <id>", "指定智能体 ID,不传则使用桌面配置中的缺省智能体")
|
|
71
|
-
.option("-p, --prompt <text>", "用户提示词(与位置参数二选一)")
|
|
72
|
-
.option("--dry-run", "只输出组装的 system/user 内容,不调用 LLM")
|
|
73
|
-
.option("--model <id>", "模型 ID", "deepseek-chat")
|
|
74
|
-
.option("--provider <name>", "Provider(pi ModelRegistry);可选 deepseek、dashscope、openai", "deepseek")
|
|
75
|
-
.option("--agent-dir <path>", "Agent 配置目录(默认 ~/.openbot/agent)", getOpenbotAgentDir())
|
|
76
|
-
.option("--api-key <key>", "API Key(不传则使用环境变量 OPENAI_API_KEY)")
|
|
77
|
-
.option("--timing", "打印每轮 LLM 与 tool 耗时到 stderr")
|
|
78
|
-
.option("--max-tool-turns <n>", "最大工具调用轮数(默认 30);可设环境变量 OPENBOT_MAX_TOOL_TURNS", (v) => parseInt(v, 10) || 0, 0)
|
|
79
|
-
.argument("[prompt]", "用户提示词(与 --prompt 二选一)")
|
|
80
|
-
.action(async (positionalPrompt) => {
|
|
81
|
-
await runAction(positionalPrompt, program.opts());
|
|
82
|
-
});
|
|
83
|
-
program.addHelpText("after", `
|
|
84
|
-
Environment:
|
|
85
|
-
DEEPSEEK_API_KEY 默认 provider 为 deepseek 时使用;不设时回退 OPENAI_API_KEY
|
|
86
|
-
OPENAI_API_KEY 通用 API Key(可被 --api-key 覆盖)
|
|
87
|
-
DASHSCOPE_API_KEY provider=dashscope 时使用;不设时回退 OPENAI_API_KEY
|
|
88
|
-
OPENAI_BASE_URL 可选,在 pi 未找到模型时使用的 endpoint
|
|
89
|
-
OPENBOT_AGENT_DIR 缺省 agent 目录(默认 ~/.openbot/agent)
|
|
90
|
-
OPENBOT_TIMING=1 等同 --timing
|
|
91
|
-
OPENBOT_ALLOW_RUN_CODE 缺省 1(启用 run_python);设为 0 关闭
|
|
92
|
-
OPENBOT_MAX_TOOL_TURNS 最大工具轮数(默认 30)
|
|
93
|
-
|
|
94
|
-
Examples:
|
|
95
|
-
openbot "总结一下当前有哪些技能"
|
|
96
|
-
openbot -a my-agent "总结一下当前有哪些技能" 使用指定智能体
|
|
97
|
-
openbot -s ./skills "总结一下当前有哪些技能"
|
|
98
|
-
openbot -s ./my-skills --prompt "用 weather 技能查北京天气" --dry-run
|
|
99
|
-
`);
|
|
100
|
-
// Gateway server command
|
|
101
|
-
program
|
|
102
|
-
.command("gateway")
|
|
103
|
-
.description("Start WebSocket gateway server")
|
|
104
|
-
.option("-p, --port <port>", "Port to listen on", "38080")
|
|
105
|
-
.action(async (options) => {
|
|
106
|
-
const port = parseInt(options.port, 10);
|
|
107
|
-
if (isNaN(port) || port <= 0 || port > 65535) {
|
|
108
|
-
console.error("Error: Invalid port number");
|
|
109
|
-
process.exit(1);
|
|
110
|
-
}
|
|
111
|
-
const { startGatewayServer } = await import("./gateway/index.js");
|
|
112
|
-
const { close } = await startGatewayServer(port);
|
|
113
|
-
// Handle graceful shutdown
|
|
114
|
-
const shutdown = async () => {
|
|
115
|
-
console.log("\nShutting down...");
|
|
116
|
-
await close();
|
|
117
|
-
process.exit(0);
|
|
118
|
-
};
|
|
119
|
-
process.on("SIGINT", shutdown);
|
|
120
|
-
process.on("SIGTERM", shutdown);
|
|
121
|
-
});
|
|
122
|
-
// Login command(写入桌面 config;可选 model,不传则取该 provider 第一个模型,补齐后可直接运行)
|
|
123
|
-
program
|
|
124
|
-
.command("login")
|
|
125
|
-
.description("Save API key for a provider to desktop config (~/.openbot/desktop); optional model, default first model")
|
|
126
|
-
.argument("<provider>", "Provider name (e.g., deepseek, dashscope, openai)")
|
|
127
|
-
.argument("<apiKey>", "API Key")
|
|
128
|
-
.argument("[model]", "Model ID (optional; default: first model for provider)")
|
|
129
|
-
.action(async (provider, apiKey, model) => {
|
|
130
|
-
await setProviderApiKey(provider, apiKey, model);
|
|
131
|
-
console.log(`[openbot] API key saved for provider: ${provider}`);
|
|
132
|
-
});
|
|
133
|
-
// Config command
|
|
134
|
-
const configCmd = program.command("config").description("Manage configurations");
|
|
135
|
-
configCmd
|
|
136
|
-
.command("set-model")
|
|
137
|
-
.description("Set default provider and model in desktop config (~/.openbot/desktop)")
|
|
138
|
-
.argument("<provider>", "Provider name")
|
|
139
|
-
.argument("<modelId>", "Model ID")
|
|
140
|
-
.action(async (provider, modelId) => {
|
|
141
|
-
await setDefaultModel(provider, modelId);
|
|
142
|
-
console.log(`[openbot] Default model set: ${provider}/${modelId}`);
|
|
143
|
-
});
|
|
144
|
-
configCmd
|
|
145
|
-
.command("list")
|
|
146
|
-
.description("List desktop config (centralized config source)")
|
|
147
|
-
.action(async () => {
|
|
148
|
-
const list = await getDesktopConfigList();
|
|
149
|
-
if (list.providers.length === 0) {
|
|
150
|
-
console.log("No providers in desktop config. Run: openbot login <provider> <apiKey>");
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
console.log(`Default: ${list.defaultProvider} / ${list.defaultModel}\n`);
|
|
154
|
-
console.table(list.providers.map((r) => ({
|
|
155
|
-
Provider: r.provider,
|
|
156
|
-
"Default Model": r.defaultModel,
|
|
157
|
-
"API Key": r.hasKey ? "✅" : "❌",
|
|
158
|
-
})));
|
|
159
|
-
});
|
|
160
|
-
configCmd
|
|
161
|
-
.command("sync")
|
|
162
|
-
.description("Sync desktop config to ~/.openbot/agent/models.json for pi-agent")
|
|
163
|
-
.action(async () => {
|
|
164
|
-
await syncDesktopConfigToModelsJson();
|
|
165
|
-
console.log("[openbot] Synced desktop providers to agent models.json");
|
|
166
|
-
});
|
|
167
|
-
(async () => {
|
|
168
|
-
await ensureDesktopConfigInitialized();
|
|
169
|
-
await program.parseAsync(process.argv);
|
|
170
|
-
})().catch((err) => {
|
|
171
|
-
console.error(err);
|
|
172
|
-
process.exit(1);
|
|
173
|
-
});
|
|
2
|
+
/**
|
|
3
|
+
* 兼容旧命令 node dist/cli.js / openbot → 实际入口为 dist/cli/cli.js
|
|
4
|
+
*/
|
|
5
|
+
import "./cli/cli.js";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gateway 各通道入口的鉴权/安全钩子(占位模块)。
|
|
3
|
+
* 连接之初可在此做 token 校验、限流等,当前暂不加逻辑,仅透传。
|
|
4
|
+
*/
|
|
5
|
+
import type { Request, Response, NextFunction } from 'express';
|
|
6
|
+
import type { IncomingMessage } from 'http';
|
|
7
|
+
/** HTTP:/server-api 进入 Nest 前的鉴权钩子(占位,直接 next) */
|
|
8
|
+
export declare function authHookServerApi(req: Request, res: Response, next: NextFunction): void;
|
|
9
|
+
/** HTTP:/channel 进入通道模块前的鉴权钩子(占位,直接 next) */
|
|
10
|
+
export declare function authHookChannel(req: Request, res: Response, next: NextFunction): void;
|
|
11
|
+
/** HTTP:/sse 进入 SSE 前的鉴权钩子(占位,直接 next) */
|
|
12
|
+
export declare function authHookSse(req: Request, res: Response, next: NextFunction): void;
|
|
13
|
+
/**
|
|
14
|
+
* WebSocket upgrade:/ws 或 /ws/voice 连接前的鉴权钩子(占位)。
|
|
15
|
+
* 返回 true 表示放行,false 表示拒绝(调用方应关闭 socket)。
|
|
16
|
+
*/
|
|
17
|
+
export declare function authHookWs(_req: IncomingMessage, _path: string): boolean;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** HTTP:/server-api 进入 Nest 前的鉴权钩子(占位,直接 next) */
|
|
2
|
+
export function authHookServerApi(req, res, next) {
|
|
3
|
+
next();
|
|
4
|
+
}
|
|
5
|
+
/** HTTP:/channel 进入通道模块前的鉴权钩子(占位,直接 next) */
|
|
6
|
+
export function authHookChannel(req, res, next) {
|
|
7
|
+
next();
|
|
8
|
+
}
|
|
9
|
+
/** HTTP:/sse 进入 SSE 前的鉴权钩子(占位,直接 next) */
|
|
10
|
+
export function authHookSse(req, res, next) {
|
|
11
|
+
next();
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* WebSocket upgrade:/ws 或 /ws/voice 连接前的鉴权钩子(占位)。
|
|
15
|
+
* 返回 true 表示放行,false 表示拒绝(调用方应关闭 socket)。
|
|
16
|
+
*/
|
|
17
|
+
export function authHookWs(_req, _path) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
package/dist/gateway/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { startGatewayServer } from "./server.js";
|
|
2
|
-
export { agentManager } from "../agent/agent-manager.js";
|
|
2
|
+
export { agentManager } from "../core/agent/agent-manager.js";
|
|
3
3
|
export type { GatewayClient, GatewayMessage, GatewayRequest, GatewayResponse, GatewayEvent, ConnectParams, AgentChatParams, } from "./types.js";
|
package/dist/gateway/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { startGatewayServer } from "./server.js";
|
|
2
|
-
export { agentManager } from "../agent/agent-manager.js";
|
|
2
|
+
export { agentManager } from "../core/agent/agent-manager.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { agentManager } from "../../agent/agent-manager.js";
|
|
1
|
+
import { agentManager } from "../../core/agent/agent-manager.js";
|
|
2
2
|
/**
|
|
3
3
|
* Handle agent.cancel: abort the current turn for the given session.
|
|
4
4
|
* Uses pi-coding-agent's session.abort() to stop the running agent and wait until idle.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { agentManager } from "../../agent/agent-manager.js";
|
|
2
|
-
import { getExperienceContextForUserMessage } from "../../memory/index.js";
|
|
1
|
+
import { agentManager } from "../../core/agent/agent-manager.js";
|
|
2
|
+
import { getExperienceContextForUserMessage } from "../../core/memory/index.js";
|
|
3
3
|
import { send, createEvent } from "../utils.js";
|
|
4
4
|
import { connectedClients } from "../clients.js";
|
|
5
|
-
import { getDesktopConfig, loadDesktopAgentConfig } from "../../config/desktop-config.js";
|
|
5
|
+
import { getDesktopConfig, loadDesktopAgentConfig } from "../../core/config/desktop-config.js";
|
|
6
6
|
/**
|
|
7
7
|
* Broadcast message to all clients subscribed to a session
|
|
8
8
|
*/
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* 在 Gateway 层处理 POST /server-api/skills/install-from-path,
|
|
3
3
|
* 委托核心 installer 将本地技能目录复制到全局或工作区,不依赖 Nest。
|
|
4
4
|
*/
|
|
5
|
-
import { installSkillFromPath } from "../../installer/index.js";
|
|
5
|
+
import { installSkillFromPath } from "../../core/installer/index.js";
|
|
6
6
|
export async function handleInstallSkillFromPath(body) {
|
|
7
7
|
const localPath = (body?.path ?? "").trim();
|
|
8
8
|
if (!localPath) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { agentManager } from "../../agent/agent-manager.js";
|
|
2
|
-
import { getExperienceContextForUserMessage } from "../../memory/index.js";
|
|
3
|
-
import { loadDesktopAgentConfig } from "../../config/desktop-config.js";
|
|
1
|
+
import { agentManager } from "../../core/agent/agent-manager.js";
|
|
2
|
+
import { getExperienceContextForUserMessage } from "../../core/memory/index.js";
|
|
3
|
+
import { loadDesktopAgentConfig } from "../../core/config/desktop-config.js";
|
|
4
4
|
async function readBody(req) {
|
|
5
5
|
return new Promise((resolve, reject) => {
|
|
6
6
|
const chunks = [];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gateway 路径常量:各模块使用独立 path 端点,便于路由与扩展。
|
|
3
|
+
*/
|
|
4
|
+
export declare const PATHS: {
|
|
5
|
+
/** 业务 REST API(Nest) */
|
|
6
|
+
readonly SERVER_API: "/server-api";
|
|
7
|
+
/** Agent 对话 WebSocket */
|
|
8
|
+
readonly WS: "/ws";
|
|
9
|
+
/** 语音通道 WebSocket(扩展占位) */
|
|
10
|
+
readonly WS_VOICE: "/ws/voice";
|
|
11
|
+
/** Agent 流式 SSE(占位) */
|
|
12
|
+
readonly SSE: "/sse";
|
|
13
|
+
/** 通道模块(webhook / 回调) */
|
|
14
|
+
readonly CHANNEL: "/channel";
|
|
15
|
+
/** 健康检查 */
|
|
16
|
+
readonly HEALTH: "/health";
|
|
17
|
+
/** 定时任务执行(Nest 回调 Gateway) */
|
|
18
|
+
readonly RUN_SCHEDULED_TASK: "/run-scheduled-task";
|
|
19
|
+
};
|
|
20
|
+
export type PathKey = keyof typeof PATHS;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gateway 路径常量:各模块使用独立 path 端点,便于路由与扩展。
|
|
3
|
+
*/
|
|
4
|
+
export const PATHS = {
|
|
5
|
+
/** 业务 REST API(Nest) */
|
|
6
|
+
SERVER_API: '/server-api',
|
|
7
|
+
/** Agent 对话 WebSocket */
|
|
8
|
+
WS: '/ws',
|
|
9
|
+
/** 语音通道 WebSocket(扩展占位) */
|
|
10
|
+
WS_VOICE: '/ws/voice',
|
|
11
|
+
/** Agent 流式 SSE(占位) */
|
|
12
|
+
SSE: '/sse',
|
|
13
|
+
/** 通道模块(webhook / 回调) */
|
|
14
|
+
CHANNEL: '/channel',
|
|
15
|
+
/** 健康检查 */
|
|
16
|
+
HEALTH: '/health',
|
|
17
|
+
/** 定时任务执行(Nest 回调 Gateway) */
|
|
18
|
+
RUN_SCHEDULED_TASK: '/run-scheduled-task',
|
|
19
|
+
};
|
package/dist/gateway/server.d.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import { WebSocketServer } from "ws";
|
|
2
1
|
import { type Server } from "http";
|
|
3
|
-
|
|
4
|
-
* Start WebSocket gateway server
|
|
5
|
-
*/
|
|
2
|
+
import { WebSocketServer } from "ws";
|
|
6
3
|
export declare function startGatewayServer(port?: number): Promise<{
|
|
7
4
|
httpServer: Server;
|
|
8
5
|
wss: WebSocketServer;
|
|
6
|
+
port: number;
|
|
9
7
|
close: () => Promise<void>;
|
|
10
8
|
}>;
|