@keyou007/agent-bot 0.1.11 → 0.1.13-alpha.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/.env.example +1 -1
- package/CHANGELOG.md +19 -0
- package/README.md +63 -44
- package/README.zh.md +63 -44
- package/config.example.yaml +8 -22
- package/dist/cli/AgentPrerequisites.js +262 -0
- package/dist/cli/AgentPrerequisites.js.map +1 -0
- package/dist/cli/DefaultAgentSelection.js +47 -0
- package/dist/cli/DefaultAgentSelection.js.map +1 -0
- package/dist/cli/FeishuAppConfiguration.js +1 -1
- package/dist/cli/FeishuAppConfiguration.js.map +1 -1
- package/dist/cli/FeishuAppRegistration.js +2 -2
- package/dist/cli/FeishuAppRegistration.js.map +1 -1
- package/dist/cli/Initializer.js +166 -3
- package/dist/cli/Initializer.js.map +1 -1
- package/dist/cli/ServerStarter.js +7 -2
- package/dist/cli/ServerStarter.js.map +1 -1
- package/dist/cli/controlProtocol.js.map +1 -1
- package/dist/cli/help.js +24 -20
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/taskGroupOptions.js +95 -0
- package/dist/cli/taskGroupOptions.js.map +1 -0
- package/dist/cli.js +268 -6
- package/dist/cli.js.map +1 -1
- package/dist/codex/AppServerConnection.js +3 -3
- package/dist/codex/AppServerConnection.js.map +1 -1
- package/dist/codex/CodexProcessManager.js +4 -4
- package/dist/codex/CodexProcessManager.js.map +1 -1
- package/dist/codex/CodexRuntime.js +63 -25
- package/dist/codex/CodexRuntime.js.map +1 -1
- package/dist/config/loadConfig.js +8 -22
- package/dist/config/loadConfig.js.map +1 -1
- package/dist/config/schema.js +6 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/console/ConsoleConnector.js +3 -3
- package/dist/console/ConsoleConnector.js.map +1 -1
- package/dist/console/ConsoleTurnPresenter.js +14 -7
- package/dist/console/ConsoleTurnPresenter.js.map +1 -1
- package/dist/deprecated-cli.js +5 -0
- package/dist/deprecated-cli.js.map +1 -0
- package/dist/feishu/CardRenderer.js +13 -12
- package/dist/feishu/CardRenderer.js.map +1 -1
- package/dist/feishu/FeishuTurnPresenter.js +9 -5
- package/dist/feishu/FeishuTurnPresenter.js.map +1 -1
- package/dist/feishu/transport.js +1 -1
- package/dist/feishu/transport.js.map +1 -1
- package/dist/index.js +21 -3
- package/dist/index.js.map +1 -1
- package/dist/presentation/OutboundRouter.js +2 -2
- package/dist/presentation/OutboundRouter.js.map +1 -1
- package/dist/presentation/TurnStateReducer.js +2 -1
- package/dist/presentation/TurnStateReducer.js.map +1 -1
- package/dist/proxy/ProxySessionController.js +128 -72
- package/dist/proxy/ProxySessionController.js.map +1 -1
- package/dist/runtime/AcpRuntimeAdapter.js +3 -2
- package/dist/runtime/AcpRuntimeAdapter.js.map +1 -1
- package/dist/runtime/createAgentRuntimeRegistry.js +1 -1
- package/dist/runtime/createAgentRuntimeRegistry.js.map +1 -1
- package/dist/supervision/systemEnvironment.js +129 -0
- package/dist/supervision/systemEnvironment.js.map +1 -0
- package/dist/supervisor.js +13 -1
- package/dist/supervisor.js.map +1 -1
- package/docs/technical-reference.md +53 -34
- package/docs/technical-reference.zh.md +53 -34
- package/npm-shrinkwrap.json +4 -3
- package/package.json +9 -4
- package/skills/agent-bot/SKILL.md +72 -33
- package/src/cli/AgentPrerequisites.ts +377 -0
- package/src/cli/DefaultAgentSelection.ts +56 -0
- package/src/cli/FeishuAppConfiguration.ts +2 -2
- package/src/cli/FeishuAppRegistration.ts +4 -4
- package/src/cli/Initializer.ts +206 -5
- package/src/cli/ServerStarter.ts +8 -3
- package/src/cli/controlProtocol.ts +21 -1
- package/src/cli/help.ts +24 -20
- package/src/cli/taskGroupOptions.ts +149 -0
- package/src/cli.ts +391 -9
- package/src/codex/AppServerConnection.ts +3 -3
- package/src/codex/CodexProcessManager.ts +4 -4
- package/src/codex/CodexRuntime.ts +84 -31
- package/src/config/loadConfig.ts +8 -22
- package/src/config/schema.ts +7 -1
- package/src/console/ConsoleConnector.ts +3 -3
- package/src/console/ConsoleTurnPresenter.ts +20 -7
- package/src/deprecated-cli.ts +9 -0
- package/src/feishu/CardRenderer.ts +13 -12
- package/src/feishu/FeishuTurnPresenter.ts +15 -1
- package/src/feishu/transport.ts +1 -1
- package/src/index.ts +34 -3
- package/src/presentation/OutboundRouter.ts +15 -3
- package/src/presentation/TurnStateReducer.ts +2 -0
- package/src/presentation/turnViewTypes.ts +1 -0
- package/src/proxy/ProxySessionController.ts +217 -73
- package/src/runtime/AcpRuntimeAdapter.ts +3 -1
- package/src/runtime/createAgentRuntimeRegistry.ts +1 -1
- package/src/supervision/systemEnvironment.ts +174 -0
- package/src/supervisor.ts +12 -1
|
@@ -99,7 +99,9 @@ export class AcpRuntimeAdapter implements AgentRuntime {
|
|
|
99
99
|
|
|
100
100
|
async startTurn(sessionId: string, prompt: RuntimePrompt): Promise<string> {
|
|
101
101
|
const { text, localImagePaths } = normalizeRuntimePrompt(prompt);
|
|
102
|
-
if (localImagePaths.length > 0)
|
|
102
|
+
if (localImagePaths.length > 0) {
|
|
103
|
+
throw new Error("当前 ACP Agent 不支持图片输入,请切换到支持图片输入的 App Server Agent 后重试。");
|
|
104
|
+
}
|
|
103
105
|
const session = this.requireSession(sessionId);
|
|
104
106
|
const turnId = createId("turn");
|
|
105
107
|
session.activeTurnId = turnId;
|
|
@@ -12,7 +12,7 @@ export function createAgentRuntimeRegistry(config: AppConfig, logger: Logger): A
|
|
|
12
12
|
const runtimes: Record<string, AgentRuntime> = {};
|
|
13
13
|
for (const [agentName, agent] of Object.entries(config.agents)) {
|
|
14
14
|
const runtimeLogger = logger.child({ agentName, runtimeKind: agent.kind });
|
|
15
|
-
if (agent.kind === "
|
|
15
|
+
if (agent.kind === "app-server") {
|
|
16
16
|
const processManager = new CodexProcessManager(agent.command, agent.args, agent.env, runtimeLogger);
|
|
17
17
|
runtimes[agentName] = new CodexRuntime(processManager, runtimeLogger);
|
|
18
18
|
continue;
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
export interface WindowsEnvironmentSnapshot {
|
|
5
|
+
machine: Record<string, string>;
|
|
6
|
+
user: Record<string, string>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface EnvironmentRefreshResult {
|
|
10
|
+
environment: NodeJS.ProcessEnv;
|
|
11
|
+
refreshed: boolean;
|
|
12
|
+
pathChanged: boolean;
|
|
13
|
+
error?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type WindowsEnvironmentLoader = () => WindowsEnvironmentSnapshot;
|
|
17
|
+
|
|
18
|
+
const PROCESS_LOCAL_ENVIRONMENT_PREFIXES = ["AGENT_BOT_", "FEISHU_"];
|
|
19
|
+
|
|
20
|
+
export function refreshedSystemEnvironment(
|
|
21
|
+
inherited: NodeJS.ProcessEnv = process.env,
|
|
22
|
+
platform: NodeJS.Platform = process.platform,
|
|
23
|
+
loadWindowsEnvironment: WindowsEnvironmentLoader = readWindowsEnvironment,
|
|
24
|
+
): EnvironmentRefreshResult {
|
|
25
|
+
const fallback = { ...inherited };
|
|
26
|
+
if (platform !== "win32") {
|
|
27
|
+
return { environment: fallback, refreshed: false, pathChanged: false };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
const snapshot = loadWindowsEnvironment();
|
|
32
|
+
const environment = mergeWindowsEnvironment(inherited, snapshot);
|
|
33
|
+
return {
|
|
34
|
+
environment,
|
|
35
|
+
refreshed: true,
|
|
36
|
+
pathChanged: environmentValue(environment, "Path") !== environmentValue(inherited, "Path"),
|
|
37
|
+
};
|
|
38
|
+
} catch (error) {
|
|
39
|
+
return {
|
|
40
|
+
environment: fallback,
|
|
41
|
+
refreshed: false,
|
|
42
|
+
pathChanged: false,
|
|
43
|
+
error: error instanceof Error ? error.message : String(error),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function mergeWindowsEnvironment(
|
|
49
|
+
inherited: NodeJS.ProcessEnv,
|
|
50
|
+
snapshot: WindowsEnvironmentSnapshot,
|
|
51
|
+
): NodeJS.ProcessEnv {
|
|
52
|
+
const environment = { ...inherited };
|
|
53
|
+
applyEnvironment(environment, snapshot.machine);
|
|
54
|
+
applyEnvironment(environment, snapshot.user);
|
|
55
|
+
|
|
56
|
+
const machinePath = environmentValue(snapshot.machine, "Path")?.trim();
|
|
57
|
+
const userPath = environmentValue(snapshot.user, "Path")?.trim();
|
|
58
|
+
if (machinePath || userPath) {
|
|
59
|
+
const inheritedPath = environmentValue(inherited, "Path")?.trim();
|
|
60
|
+
setEnvironmentValue(
|
|
61
|
+
environment,
|
|
62
|
+
"Path",
|
|
63
|
+
mergePathValues(
|
|
64
|
+
expandEnvironmentReferences(
|
|
65
|
+
[machinePath, userPath, inheritedPath].filter(Boolean).join(";"),
|
|
66
|
+
environment,
|
|
67
|
+
),
|
|
68
|
+
),
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
return environment;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function readWindowsEnvironment(): WindowsEnvironmentSnapshot {
|
|
75
|
+
const systemRoot = process.env.SystemRoot ?? "C:\\Windows";
|
|
76
|
+
const executable = path.join(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
|
|
77
|
+
const script = [
|
|
78
|
+
"[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)",
|
|
79
|
+
"$machine = @{}",
|
|
80
|
+
"foreach ($entry in [Environment]::GetEnvironmentVariables([EnvironmentVariableTarget]::Machine).GetEnumerator()) { $machine[[string]$entry.Key] = [string]$entry.Value }",
|
|
81
|
+
"$user = @{}",
|
|
82
|
+
"foreach ($entry in [Environment]::GetEnvironmentVariables([EnvironmentVariableTarget]::User).GetEnumerator()) { $user[[string]$entry.Key] = [string]$entry.Value }",
|
|
83
|
+
"[pscustomobject]@{ machine = $machine; user = $user } | ConvertTo-Json -Compress -Depth 3",
|
|
84
|
+
].join("; ");
|
|
85
|
+
const result = spawnSync(executable, [
|
|
86
|
+
"-NoLogo",
|
|
87
|
+
"-NoProfile",
|
|
88
|
+
"-NonInteractive",
|
|
89
|
+
"-ExecutionPolicy",
|
|
90
|
+
"Bypass",
|
|
91
|
+
"-Command",
|
|
92
|
+
script,
|
|
93
|
+
], {
|
|
94
|
+
encoding: "utf8",
|
|
95
|
+
windowsHide: true,
|
|
96
|
+
timeout: 5_000,
|
|
97
|
+
maxBuffer: 8 * 1024 * 1024,
|
|
98
|
+
});
|
|
99
|
+
if (result.error) throw result.error;
|
|
100
|
+
if (result.status !== 0) {
|
|
101
|
+
throw new Error(result.stderr.trim() || `PowerShell exited with code ${result.status ?? "unknown"}.`);
|
|
102
|
+
}
|
|
103
|
+
const parsed = JSON.parse(result.stdout) as Partial<WindowsEnvironmentSnapshot>;
|
|
104
|
+
return {
|
|
105
|
+
machine: environmentRecord(parsed.machine),
|
|
106
|
+
user: environmentRecord(parsed.user),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function environmentRecord(value: unknown): Record<string, string> {
|
|
111
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
112
|
+
return Object.fromEntries(
|
|
113
|
+
Object.entries(value).flatMap(([name, entry]) =>
|
|
114
|
+
typeof entry === "string" ? [[name, entry]] : []),
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function applyEnvironment(
|
|
119
|
+
target: NodeJS.ProcessEnv,
|
|
120
|
+
source: Record<string, string>,
|
|
121
|
+
): void {
|
|
122
|
+
for (const [name, value] of Object.entries(source)) {
|
|
123
|
+
if (name.toLowerCase() === "path" || isProcessLocalEnvironmentName(name)) continue;
|
|
124
|
+
setEnvironmentValue(target, name, value);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function isProcessLocalEnvironmentName(name: string): boolean {
|
|
129
|
+
const normalized = name.toUpperCase();
|
|
130
|
+
return PROCESS_LOCAL_ENVIRONMENT_PREFIXES.some((prefix) => normalized.startsWith(prefix));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function setEnvironmentValue(environment: NodeJS.ProcessEnv, name: string, value: string): void {
|
|
134
|
+
for (const existingName of Object.keys(environment)) {
|
|
135
|
+
if (existingName !== name && existingName.toLowerCase() === name.toLowerCase()) {
|
|
136
|
+
delete environment[existingName];
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
environment[name] = value;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function environmentValue(
|
|
143
|
+
environment: NodeJS.ProcessEnv | Record<string, string>,
|
|
144
|
+
name: string,
|
|
145
|
+
): string | undefined {
|
|
146
|
+
const key = Object.keys(environment).find((candidate) => candidate.toLowerCase() === name.toLowerCase());
|
|
147
|
+
return key === undefined ? undefined : environment[key];
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function expandEnvironmentReferences(value: string, environment: NodeJS.ProcessEnv): string {
|
|
151
|
+
let expanded = value;
|
|
152
|
+
for (let attempt = 0; attempt < 5; attempt += 1) {
|
|
153
|
+
const next = expanded.replace(/%([^%]+)%/g, (match, name: string) =>
|
|
154
|
+
environmentValue(environment, name) ?? match);
|
|
155
|
+
if (next === expanded) break;
|
|
156
|
+
expanded = next;
|
|
157
|
+
}
|
|
158
|
+
return expanded;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function mergePathValues(value: string): string {
|
|
162
|
+
const seen = new Set<string>();
|
|
163
|
+
return value
|
|
164
|
+
.split(";")
|
|
165
|
+
.map((entry) => entry.trim())
|
|
166
|
+
.filter((entry) => {
|
|
167
|
+
if (!entry) return false;
|
|
168
|
+
const normalized = entry.replace(/[\\/]+$/, "").toLowerCase();
|
|
169
|
+
if (seen.has(normalized)) return false;
|
|
170
|
+
seen.add(normalized);
|
|
171
|
+
return true;
|
|
172
|
+
})
|
|
173
|
+
.join(";");
|
|
174
|
+
}
|
package/src/supervisor.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
STOP_EXIT_CODE,
|
|
14
14
|
} from "./supervision/restartPolicy.js";
|
|
15
15
|
import { SupervisorDiagnostics, nodeDiagnosticReportArguments } from "./supervision/SupervisorDiagnostics.js";
|
|
16
|
+
import { refreshedSystemEnvironment } from "./supervision/systemEnvironment.js";
|
|
16
17
|
|
|
17
18
|
const childEntry = fileURLToPath(new URL("./index.js", import.meta.url));
|
|
18
19
|
const config = loadConfig();
|
|
@@ -38,13 +39,23 @@ async function startChild(): Promise<void> {
|
|
|
38
39
|
const restartReason = nextStartReason;
|
|
39
40
|
nextStartReason = "Supervisor 重新拉起进程";
|
|
40
41
|
const workerStderr = diagnostics.openWorkerStderr();
|
|
42
|
+
const environmentRefresh = refreshedSystemEnvironment();
|
|
43
|
+
if (environmentRefresh.error) {
|
|
44
|
+
writeSupervisorLog("environment_refresh_failed", { error: environmentRefresh.error });
|
|
45
|
+
} else if (environmentRefresh.refreshed) {
|
|
46
|
+
writeSupervisorLog("environment_refreshed", { pathChanged: environmentRefresh.pathChanged });
|
|
47
|
+
}
|
|
41
48
|
try {
|
|
42
49
|
child = spawn(process.execPath, [
|
|
43
50
|
...nodeDiagnosticReportArguments(diagnostics.paths.crashReportDirectory),
|
|
44
51
|
childEntry,
|
|
45
52
|
], {
|
|
46
53
|
cwd: process.cwd(),
|
|
47
|
-
env: {
|
|
54
|
+
env: {
|
|
55
|
+
...environmentRefresh.environment,
|
|
56
|
+
AGENT_BOT_SUPERVISED: "1",
|
|
57
|
+
AGENT_BOT_RESTART_REASON: restartReason,
|
|
58
|
+
},
|
|
48
59
|
stdio: ["ignore", "ignore", workerStderr],
|
|
49
60
|
windowsHide: true,
|
|
50
61
|
});
|