u1s1-cli 1.14.6 → 1.15.0
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/agent-setup.d.ts +7 -0
- package/dist/agent-setup.js +14 -0
- package/dist/agents/agent-config.d.ts +83 -0
- package/dist/agents/agent-config.js +154 -0
- package/dist/agents/claude.d.ts +80 -0
- package/dist/agents/claude.js +233 -0
- package/dist/agents/codex.d.ts +111 -0
- package/dist/agents/codex.js +392 -0
- package/dist/agents/launch.d.ts +109 -0
- package/dist/agents/launch.js +444 -0
- package/dist/agents/pi.d.ts +9 -0
- package/dist/agents/pi.js +562 -0
- package/dist/agents/prefs.d.ts +35 -0
- package/dist/agents/prefs.js +96 -0
- package/dist/agents/runtime.d.ts +354 -0
- package/dist/agents/runtime.js +884 -0
- package/dist/agents/status.d.ts +20 -0
- package/dist/agents/status.js +241 -0
- package/dist/config-command.d.ts +18 -0
- package/dist/config-command.js +335 -0
- package/dist/config.d.ts +17 -0
- package/dist/config.js +35 -1
- package/dist/device-auth.d.ts +37 -1
- package/dist/device-auth.js +43 -8
- package/dist/embed.d.ts +13 -0
- package/dist/embed.js +15 -0
- package/dist/index.js +22 -556
- package/dist/launcher.d.ts +48 -0
- package/dist/launcher.js +235 -0
- package/dist/mcp-server.d.ts +105 -0
- package/dist/mcp-server.js +449 -0
- package/dist/pi-ui-text.d.ts +57 -0
- package/dist/pi-ui-text.js +148 -0
- package/dist/usage.js +2 -2
- package/package.json +1 -1
- package/scripts/p0-claude-code/README.md +39 -0
- package/scripts/p0-claude-code/launch-claude.ts +94 -0
- package/scripts/p0-claude-code/replay.ts +74 -0
- package/scripts/p0-claude-code/seed-local.mjs +145 -0
- package/scripts/p0-claude-code/tap.mjs +105 -0
- package/scripts/patch-pi.js +76 -55
- package/scripts/pi-patch-report.mjs +224 -0
- package/scripts/pi-upgrade.mjs +829 -0
- package/scripts/render-regression.mjs +67 -5
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type DefaultAgent } from "./config.js";
|
|
2
|
+
export type AgentChoice = DefaultAgent;
|
|
3
|
+
/** 启动器的保留字:不会再当 prompt 交给默认客户端。 */
|
|
4
|
+
export declare const LAUNCHER_WORDS: readonly ["pi", "claude", "codex", "use", "agents", "config"];
|
|
5
|
+
export declare function isLauncherWord(word: string): boolean;
|
|
6
|
+
export type Dispatch = {
|
|
7
|
+
kind: "agent";
|
|
8
|
+
agent: AgentChoice;
|
|
9
|
+
args: string[];
|
|
10
|
+
via: "explicit" | "default" | "legacy" | "fallback";
|
|
11
|
+
} | {
|
|
12
|
+
kind: "select";
|
|
13
|
+
args: string[];
|
|
14
|
+
} | {
|
|
15
|
+
kind: "use";
|
|
16
|
+
args: string[];
|
|
17
|
+
} | {
|
|
18
|
+
kind: "agents";
|
|
19
|
+
args: string[];
|
|
20
|
+
} | {
|
|
21
|
+
kind: "config";
|
|
22
|
+
args: string[];
|
|
23
|
+
};
|
|
24
|
+
export interface DispatchContext {
|
|
25
|
+
/** config.json 里的 defaultAgent */
|
|
26
|
+
defaultAgent?: AgentChoice;
|
|
27
|
+
/** 存量用户:已有配置或用过 Pi */
|
|
28
|
+
existingUser: boolean;
|
|
29
|
+
/** stdin/stdout 都是终端,能弹选择器 */
|
|
30
|
+
interactive: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 纯函数:参数 → 去哪。
|
|
34
|
+
* 全新用户只有在「不带参数 + 终端可交互」时才出选择器;带了参数(如 -p 脚本调用)或没有终端时
|
|
35
|
+
* 直接用 Pi、不记住,免得脚本卡在提问上。
|
|
36
|
+
*/
|
|
37
|
+
export declare function resolveDispatch(args: readonly string[], ctx: DispatchContext): Dispatch;
|
|
38
|
+
/**
|
|
39
|
+
* 存量用户:config.json 里除 baseUrl 以外还有东西(登录凭据、模型、邮箱…),或者 Pi 的
|
|
40
|
+
* agent 目录已经有设置文件。只有 baseUrl 的配置是安装脚本写的站点信息,不算。
|
|
41
|
+
*/
|
|
42
|
+
export declare function isExistingUser(raw: Record<string, unknown> | undefined, agentSettingsExists: boolean): boolean;
|
|
43
|
+
export declare function runLauncher(args: string[]): Promise<void>;
|
|
44
|
+
export declare function parseSelection(answer: string): AgentChoice | undefined;
|
|
45
|
+
/** `u1s1 --help` 中文版的启动器几行(中文按 CJK 双宽手工对齐)。 */
|
|
46
|
+
export declare function launcherHelpLines(): string[];
|
|
47
|
+
/** 英文版:与 index.ts 的命令表一起按 ASCII 宽度对齐。 */
|
|
48
|
+
export declare function launcherHelpRows(): [string, string][];
|
package/dist/launcher.js
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 启动器:选择器与分发。一个命令 `u1s1`,可以启动内置的 Pi,也可以启动用户机器上的官方原版客户端。
|
|
3
|
+
*
|
|
4
|
+
* u1s1 pi|claude|codex [参数…] 指定客户端,后面的参数原样传给它
|
|
5
|
+
* u1s1 [参数…] 默认客户端;存量用户(已有配置、没有默认客户端字段)默认 Pi,
|
|
6
|
+
* 全新用户首次运行出选择器并记住
|
|
7
|
+
* u1s1 use <客户端> 改默认
|
|
8
|
+
* u1s1 agents [pin|unpin|install …] 安装状态、版本、是否有更新;锁定版本;只下载不启动
|
|
9
|
+
* u1s1 config [list|get|set|unset …] 用户可调的设置(默认客户端、各客户端默认模型、自动更新),见 config-command.ts
|
|
10
|
+
*
|
|
11
|
+
* claude / codex 是否可用完全由网关配置(/v1/agents/:agent/config 的 enabled)决定,这里不写死。
|
|
12
|
+
*
|
|
13
|
+
* 现有子命令(login、usage、model、update、deploy 等)在 index.ts 里先于这里处理,行为不变。
|
|
14
|
+
*/
|
|
15
|
+
import { existsSync } from "node:fs";
|
|
16
|
+
import { createInterface } from "node:readline/promises";
|
|
17
|
+
import { agentSettingsFile, isDefaultAgent, loadConfig, readRawConfigFile, saveDefaultAgent, } from "./config.js";
|
|
18
|
+
import { tr } from "./i18n.js";
|
|
19
|
+
/** 启动器的保留字:不会再当 prompt 交给默认客户端。 */
|
|
20
|
+
export const LAUNCHER_WORDS = ["pi", "claude", "codex", "use", "agents", "config"];
|
|
21
|
+
export function isLauncherWord(word) {
|
|
22
|
+
return LAUNCHER_WORDS.includes(word);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 纯函数:参数 → 去哪。
|
|
26
|
+
* 全新用户只有在「不带参数 + 终端可交互」时才出选择器;带了参数(如 -p 脚本调用)或没有终端时
|
|
27
|
+
* 直接用 Pi、不记住,免得脚本卡在提问上。
|
|
28
|
+
*/
|
|
29
|
+
export function resolveDispatch(args, ctx) {
|
|
30
|
+
const [first, ...rest] = args;
|
|
31
|
+
switch (first) {
|
|
32
|
+
case "pi":
|
|
33
|
+
case "claude":
|
|
34
|
+
case "codex":
|
|
35
|
+
return { kind: "agent", agent: first, args: rest, via: "explicit" };
|
|
36
|
+
case "use":
|
|
37
|
+
return { kind: "use", args: rest };
|
|
38
|
+
case "agents":
|
|
39
|
+
return { kind: "agents", args: rest };
|
|
40
|
+
case "config":
|
|
41
|
+
return { kind: "config", args: rest };
|
|
42
|
+
}
|
|
43
|
+
if (ctx.defaultAgent)
|
|
44
|
+
return { kind: "agent", agent: ctx.defaultAgent, args: [...args], via: "default" };
|
|
45
|
+
if (ctx.existingUser)
|
|
46
|
+
return { kind: "agent", agent: "pi", args: [...args], via: "legacy" };
|
|
47
|
+
if (args.length === 0 && ctx.interactive)
|
|
48
|
+
return { kind: "select", args: [] };
|
|
49
|
+
return { kind: "agent", agent: "pi", args: [...args], via: "fallback" };
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 存量用户:config.json 里除 baseUrl 以外还有东西(登录凭据、模型、邮箱…),或者 Pi 的
|
|
53
|
+
* agent 目录已经有设置文件。只有 baseUrl 的配置是安装脚本写的站点信息,不算。
|
|
54
|
+
*/
|
|
55
|
+
export function isExistingUser(raw, agentSettingsExists) {
|
|
56
|
+
if (agentSettingsExists)
|
|
57
|
+
return true;
|
|
58
|
+
if (!raw)
|
|
59
|
+
return false;
|
|
60
|
+
return Object.entries(raw).some(([key, value]) => key !== "baseUrl" && value !== undefined && value !== null && value !== "");
|
|
61
|
+
}
|
|
62
|
+
// ---------------------------------------------------------------- run
|
|
63
|
+
export async function runLauncher(args) {
|
|
64
|
+
const raw = readRawConfigFile();
|
|
65
|
+
const dispatch = resolveDispatch(args, {
|
|
66
|
+
defaultAgent: isDefaultAgent(raw?.["defaultAgent"]) ? raw["defaultAgent"] : undefined,
|
|
67
|
+
existingUser: isExistingUser(raw, existsSync(agentSettingsFile)),
|
|
68
|
+
interactive: !!process.stdin.isTTY && !!process.stdout.isTTY,
|
|
69
|
+
});
|
|
70
|
+
switch (dispatch.kind) {
|
|
71
|
+
case "use":
|
|
72
|
+
useCommand(dispatch.args);
|
|
73
|
+
return;
|
|
74
|
+
case "agents":
|
|
75
|
+
await agentsCommand(dispatch.args);
|
|
76
|
+
return;
|
|
77
|
+
case "config": {
|
|
78
|
+
const { configCommand } = await import("./config-command.js");
|
|
79
|
+
process.exitCode = await configCommand(dispatch.args);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
case "select": {
|
|
83
|
+
const agent = await selectAgent();
|
|
84
|
+
saveDefaultAgent(agent);
|
|
85
|
+
console.log(tr(` 已记住,以后运行 u1s1 直接进入 ${agent}。随时可以用 u1s1 use <客户端> 修改。`, ` Saved. Running u1s1 now opens ${agent}. Change it any time with u1s1 use <client>.`));
|
|
86
|
+
await launch(agent, dispatch.args);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
case "agent":
|
|
90
|
+
await launch(dispatch.agent, dispatch.args);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async function launch(agent, args) {
|
|
95
|
+
if (agent === "pi") {
|
|
96
|
+
const { ensureAuth } = await import("./login.js");
|
|
97
|
+
const cfg = await ensureAuth();
|
|
98
|
+
const { installPendingUpdate, runAgent } = await import("./agents/pi.js");
|
|
99
|
+
await runAgent(cfg, args);
|
|
100
|
+
// autoUpdate 开着且启动时发现了新版:现在装(TUI 已退出,原地重铺安全)
|
|
101
|
+
installPendingUpdate();
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const code = agent === "codex"
|
|
105
|
+
? await (await import("./agents/codex.js")).runCodex(args)
|
|
106
|
+
: await (await import("./agents/claude.js")).runClaude(args);
|
|
107
|
+
// 签名代理是 unref 的,子进程退出后不必等;直接带着子进程的退出码退出
|
|
108
|
+
process.exit(code);
|
|
109
|
+
}
|
|
110
|
+
const OPTIONS = [
|
|
111
|
+
{
|
|
112
|
+
agent: "pi",
|
|
113
|
+
line: () => tr("pi u1s1 内置的编程助手,中文界面,开箱即用(推荐)", "pi u1s1's built-in coding assistant, ready to go (recommended)"),
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
agent: "claude",
|
|
117
|
+
line: () => tr("claude 启动官方 Claude Code(首次使用会从官方渠道下载)", "claude Launch the official Claude Code (downloaded from the official source on first use)"),
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
agent: "codex",
|
|
121
|
+
line: () => tr("codex 启动官方 Codex CLI(首次使用会从官方渠道下载)", "codex Launch the official Codex CLI (downloaded from the official source on first use)"),
|
|
122
|
+
},
|
|
123
|
+
];
|
|
124
|
+
export function parseSelection(answer) {
|
|
125
|
+
const a = answer.trim().toLowerCase();
|
|
126
|
+
if (a === "")
|
|
127
|
+
return "pi";
|
|
128
|
+
const byIndex = Number(a);
|
|
129
|
+
if (Number.isInteger(byIndex) && byIndex >= 1 && byIndex <= OPTIONS.length)
|
|
130
|
+
return OPTIONS[byIndex - 1].agent;
|
|
131
|
+
return OPTIONS.find((o) => o.agent === a)?.agent;
|
|
132
|
+
}
|
|
133
|
+
async function selectAgent() {
|
|
134
|
+
console.log("");
|
|
135
|
+
console.log(tr(" 选择要使用的客户端(以后可以用 u1s1 use <客户端> 修改):", " Choose a client (you can change it later with u1s1 use <client>):"));
|
|
136
|
+
OPTIONS.forEach((o, i) => console.log(` ${i + 1}) ${o.line()}`));
|
|
137
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
138
|
+
try {
|
|
139
|
+
for (;;) {
|
|
140
|
+
const choice = parseSelection(await rl.question(tr(" 输入序号 [1]: ", " Enter a number [1]: ")));
|
|
141
|
+
if (choice)
|
|
142
|
+
return choice;
|
|
143
|
+
console.log(tr(` 请输入 1-${OPTIONS.length}`, ` Please enter 1-${OPTIONS.length}`));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
rl.close();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// ---------------------------------------------------------------- use
|
|
151
|
+
function useCommand(args) {
|
|
152
|
+
const target = args[0];
|
|
153
|
+
if (!isDefaultAgent(target)) {
|
|
154
|
+
console.error(tr("用法: u1s1 use <pi|claude|codex>", "Usage: u1s1 use <pi|claude|codex>"));
|
|
155
|
+
process.exitCode = target === undefined || target === "--help" || target === "-h" ? 0 : 1;
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
saveDefaultAgent(target);
|
|
159
|
+
console.log(tr(`已把默认客户端设为 ${target}:运行 u1s1 直接进入它。`, `Default client set to ${target}: running u1s1 now opens it.`));
|
|
160
|
+
}
|
|
161
|
+
// ---------------------------------------------------------------- agents
|
|
162
|
+
async function agentsCommand(args) {
|
|
163
|
+
const [sub, agent, version] = args;
|
|
164
|
+
if (sub === "--help" || sub === "-h" || sub === "help") {
|
|
165
|
+
for (const line of agentsHelpLines())
|
|
166
|
+
console.log(line);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (sub === "pin" || sub === "unpin") {
|
|
170
|
+
if (agent !== "claude" && agent !== "codex") {
|
|
171
|
+
console.error(sub === "pin"
|
|
172
|
+
? tr("用法: u1s1 agents pin <claude|codex> <版本>", "Usage: u1s1 agents pin <claude|codex> <version>")
|
|
173
|
+
: tr("用法: u1s1 agents unpin <claude|codex>", "Usage: u1s1 agents unpin <claude|codex>"));
|
|
174
|
+
process.exitCode = 1;
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const { pinCommand, unpinCommand } = await import("./agents/status.js");
|
|
178
|
+
process.exitCode = sub === "pin" ? await pinCommand(version, agent) : unpinCommand(agent);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (sub === "install") {
|
|
182
|
+
if (agent === "pi" && version === undefined) {
|
|
183
|
+
console.log(tr("pi 随 u1s1 一起安装,不用单独下载。", "pi ships with u1s1; nothing to download."));
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if ((agent !== "claude" && agent !== "codex") || version !== undefined) {
|
|
187
|
+
console.error(tr("用法: u1s1 agents install <claude|codex>", "Usage: u1s1 agents install <claude|codex>"));
|
|
188
|
+
process.exitCode = 1;
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const { installCommand } = await import("./agents/status.js");
|
|
192
|
+
process.exitCode = await installCommand({}, agent);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
if (sub !== undefined) {
|
|
196
|
+
for (const line of agentsHelpLines())
|
|
197
|
+
console.error(line);
|
|
198
|
+
process.exitCode = 1;
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const { printAgentsStatus } = await import("./agents/status.js");
|
|
202
|
+
await printAgentsStatus(loadConfig().defaultAgent ?? (isExistingUser(readRawConfigFile(), existsSync(agentSettingsFile)) ? "pi" : undefined));
|
|
203
|
+
}
|
|
204
|
+
function agentsHelpLines() {
|
|
205
|
+
return [
|
|
206
|
+
tr("用法:", "Usage:"),
|
|
207
|
+
tr(" u1s1 agents 查看各客户端的安装状态、版本、是否有更新", " u1s1 agents Show each client's install status, version and updates"),
|
|
208
|
+
tr(" u1s1 agents install <客户端> 下载或更新到可用版本,不启动(claude / codex)", " u1s1 agents install <client> Download or update to a usable version without launching (claude / codex)"),
|
|
209
|
+
tr(" u1s1 agents pin <客户端> <版本> 锁定版本(不超出允许的范围)", " u1s1 agents pin <client> <ver> Pin a version (within the allowed range)"),
|
|
210
|
+
tr(" u1s1 agents unpin <客户端> 解除锁定,恢复自动更新", " u1s1 agents unpin <client> Remove the pin and resume automatic updates"),
|
|
211
|
+
];
|
|
212
|
+
}
|
|
213
|
+
// ---------------------------------------------------------------- help
|
|
214
|
+
/** `u1s1 --help` 中文版的启动器几行(中文按 CJK 双宽手工对齐)。 */
|
|
215
|
+
export function launcherHelpLines() {
|
|
216
|
+
return [
|
|
217
|
+
" u1s1 pi 进入内置的 Pi",
|
|
218
|
+
" u1s1 claude [参数] 启动官方 Claude Code(首次使用会下载)",
|
|
219
|
+
" u1s1 codex [参数] 启动官方 Codex CLI(首次使用会下载)",
|
|
220
|
+
" u1s1 use <客户端> 设置默认客户端(pi / claude / codex)",
|
|
221
|
+
" u1s1 agents 查看各客户端的安装状态、版本与更新",
|
|
222
|
+
" u1s1 config 设置默认客户端、各客户端的默认模型、自动更新",
|
|
223
|
+
];
|
|
224
|
+
}
|
|
225
|
+
/** 英文版:与 index.ts 的命令表一起按 ASCII 宽度对齐。 */
|
|
226
|
+
export function launcherHelpRows() {
|
|
227
|
+
return [
|
|
228
|
+
["u1s1 pi", "Open the built-in Pi"],
|
|
229
|
+
["u1s1 claude [args]", "Launch the official Claude Code (downloaded on first use)"],
|
|
230
|
+
["u1s1 codex [args]", "Launch the official Codex CLI (downloaded on first use)"],
|
|
231
|
+
["u1s1 use <client>", "Set the default client (pi / claude / codex)"],
|
|
232
|
+
["u1s1 agents", "Show each client's install status, version and updates"],
|
|
233
|
+
["u1s1 config", "Set the default client, each client's default model and auto-update"],
|
|
234
|
+
];
|
|
235
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import type { ApiFeatures } from "./api.js";
|
|
2
|
+
export declare const MCP_SERVER_NAME = "u1s1";
|
|
3
|
+
export declare const MCP_PROXY_ENV = "U1S1_MCP_PROXY";
|
|
4
|
+
export declare const MCP_TOKEN_ENV = "U1S1_MCP_TOKEN";
|
|
5
|
+
export declare const MCP_TOOLS_ENV = "U1S1_MCP_TOOLS";
|
|
6
|
+
/** 关闭开关:U1S1_MCP=0(或 off / false / no)时启动器不注入 MCP 服务。 */
|
|
7
|
+
export declare const MCP_SWITCH_ENV = "U1S1_MCP";
|
|
8
|
+
/** 排查用:设成一个文件路径时,服务把收发的每条协议消息和启动信息(不含 token)追加写进去。 */
|
|
9
|
+
export declare const MCP_TRACE_ENV = "U1S1_MCP_TRACE";
|
|
10
|
+
/** 启动器写进客户端环境、再由客户端转给 MCP 服务的变量(客户端配置里只引用名字,不写值)。 */
|
|
11
|
+
export declare const MCP_ENV_NAMES: readonly ["U1S1_MCP_PROXY", "U1S1_MCP_TOKEN", "U1S1_MCP_TOOLS", "U1S1_LANG"];
|
|
12
|
+
/** 我们支持的协议版本,新的在前。客户端要的版本在列表里就原样回,否则回第一个(规范的版本协商)。 */
|
|
13
|
+
export declare const MCP_PROTOCOL_VERSIONS: readonly ["2025-11-25", "2025-06-18", "2025-03-26", "2024-11-05"];
|
|
14
|
+
export type McpToolName = "web_search" | "web_fetch" | "generate_image";
|
|
15
|
+
/** 用户用环境变量关掉了注入。 */
|
|
16
|
+
export declare function mcpInjectionDisabled(env?: NodeJS.ProcessEnv): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* 网关能力 → U1S1_MCP_TOOLS。缺省值与 Pi 相同(web.ts / agents/pi.ts):搜索缺字段按开、
|
|
19
|
+
* 云端渲染和生图缺字段按关;拿不到 /v1/models 时(features 为 undefined)同样处理。
|
|
20
|
+
*/
|
|
21
|
+
export declare function mcpToolFlags(features: ApiFeatures | undefined): string;
|
|
22
|
+
/** 客户端拉起服务用的命令:同一个 node、同一份 CLI(dist/index.js),子命令 mcp-server。 */
|
|
23
|
+
export declare function mcpServerCommand(): {
|
|
24
|
+
command: string;
|
|
25
|
+
args: string[];
|
|
26
|
+
};
|
|
27
|
+
/** 注入时写进客户端 MCP 配置的环境变量(值由启动器放进客户端自己的环境,见各客户端模块)。 */
|
|
28
|
+
export interface McpLaunchEnv {
|
|
29
|
+
[MCP_PROXY_ENV]: string;
|
|
30
|
+
[MCP_TOKEN_ENV]: string;
|
|
31
|
+
[MCP_TOOLS_ENV]: string;
|
|
32
|
+
U1S1_LANG: "zh" | "en";
|
|
33
|
+
}
|
|
34
|
+
export declare function mcpLaunchEnv(input: {
|
|
35
|
+
proxyBaseUrl: string;
|
|
36
|
+
localToken: string;
|
|
37
|
+
features: ApiFeatures | undefined;
|
|
38
|
+
lang: "zh" | "en";
|
|
39
|
+
}): McpLaunchEnv;
|
|
40
|
+
export declare function isLoopbackProxyUrl(url: string): boolean;
|
|
41
|
+
export interface McpContent {
|
|
42
|
+
type: "text";
|
|
43
|
+
text: string;
|
|
44
|
+
}
|
|
45
|
+
export interface McpToolResult {
|
|
46
|
+
content: McpContent[];
|
|
47
|
+
isError?: boolean;
|
|
48
|
+
}
|
|
49
|
+
export interface McpTool {
|
|
50
|
+
name: McpToolName;
|
|
51
|
+
title: string;
|
|
52
|
+
description: string;
|
|
53
|
+
inputSchema: Record<string, unknown>;
|
|
54
|
+
annotations: Record<string, unknown>;
|
|
55
|
+
/** 参数已按 inputSchema 校验过;失败抛 Error,由服务转成 isError 结果。 */
|
|
56
|
+
run(args: Record<string, unknown>, signal: AbortSignal): Promise<McpToolResult>;
|
|
57
|
+
}
|
|
58
|
+
export interface McpToolsConfig {
|
|
59
|
+
/** 签名代理地址;没有(或不是回环地址)时只提供直连的 web_fetch */
|
|
60
|
+
proxyBaseUrl?: string;
|
|
61
|
+
localToken?: string;
|
|
62
|
+
/** U1S1_MCP_TOOLS 里的能力 */
|
|
63
|
+
flags: ReadonlySet<string>;
|
|
64
|
+
}
|
|
65
|
+
export declare function parseMcpToolsConfig(env: NodeJS.ProcessEnv): McpToolsConfig;
|
|
66
|
+
/**
|
|
67
|
+
* 按配置建工具。执行逻辑来自 Pi 的 tools.ts(动态引入:它会带进 Pi 的模块,只在这里用)。
|
|
68
|
+
* cfg 里只有代理地址和本地 token;没有设备凭证,api.ts 会以 Bearer <本地 token> 访问代理。
|
|
69
|
+
*/
|
|
70
|
+
export declare function buildMcpTools(config: McpToolsConfig): Promise<McpTool[]>;
|
|
71
|
+
/** 只做 inputSchema 里用到的那几种检查(必填、类型、数值范围、数组元素为字符串),出错给模型能看懂的一句话。 */
|
|
72
|
+
export declare function checkArguments(schema: Record<string, unknown>, args: unknown): string | null;
|
|
73
|
+
export interface McpServerOptions {
|
|
74
|
+
tools: McpTool[] | (() => Promise<McpTool[]>);
|
|
75
|
+
/** 写一条协议消息(不含换行) */
|
|
76
|
+
send: (line: string) => void;
|
|
77
|
+
log?: (line: string) => void;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* 协议核心:喂进一行,按需回一行。与传输无关,测试直接驱动它。
|
|
81
|
+
* 请求并发处理;notifications/cancelled 中止对应的 tools/call,之后不再回结果(规范要求)。
|
|
82
|
+
*/
|
|
83
|
+
export declare class McpServer {
|
|
84
|
+
private readonly options;
|
|
85
|
+
private readonly inflight;
|
|
86
|
+
private toolsPromise;
|
|
87
|
+
constructor(options: McpServerOptions);
|
|
88
|
+
private tools;
|
|
89
|
+
private reply;
|
|
90
|
+
/** 处理一行输入。返回的 Promise 在这条消息处理完(含工具执行)后落定。 */
|
|
91
|
+
handleLine(line: string): Promise<void>;
|
|
92
|
+
/** 关闭:中止所有在执行的工具调用。 */
|
|
93
|
+
abortAll(): void;
|
|
94
|
+
private handleMessage;
|
|
95
|
+
private handleNotification;
|
|
96
|
+
private initializeResult;
|
|
97
|
+
private callTool;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* 本进程的全局 dispatcher:发往回环地址(签名代理)的请求直连,其余照旧交给原来的 dispatcher
|
|
101
|
+
* (按用户的 HTTP(S)_PROXY 走)。tools.ts / api.ts 用全局 fetch,这样不用改它们。
|
|
102
|
+
*/
|
|
103
|
+
export declare function installLoopbackDirectDispatcher(): void;
|
|
104
|
+
/** `u1s1 mcp-server` 入口:stdin 一行一条消息,stdout 只写协议消息。stdin 关闭即退出。 */
|
|
105
|
+
export declare function runMcpServer(): Promise<void>;
|