agent-anywhere-gateway 0.1.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/README.md +46 -0
- package/bin/agent-anywhere-gateway.js +13 -0
- package/config/cloudflare.gateway.env.example +9 -0
- package/package.json +29 -0
- package/src/adapters/local-agent-adapter.js +131 -0
- package/src/gateway/client.js +422 -0
- package/src/gateway/main.js +224 -0
- package/src/gateway/providers.js +28 -0
- package/src/gateway/runner.js +337 -0
- package/src/gateway.js +7 -0
- package/src/lib/capabilities.js +1 -0
- package/src/lib/local-discovery.js +322 -0
- package/src/lib/path-policy.js +1 -0
- package/src/runtimes/claude-code-headless-runtime.js +547 -0
- package/src/runtimes/claude-code-runtime.js +984 -0
- package/src/runtimes/codex-app-server-client.js +157 -0
- package/src/runtimes/codex-app-server-runtime.js +790 -0
- package/src/runtimes/codex-runtime.js +418 -0
- package/src/runtimes/mock-runtime.js +140 -0
- package/src/shared/capabilities.js +175 -0
- package/src/shared/gateway-protocol.js +26 -0
- package/src/shared/http-utils.js +78 -0
- package/src/shared/image-attachments.js +269 -0
- package/src/shared/path-policy.js +110 -0
- package/src/shared/project-files.js +119 -0
- package/src/shared/providers.js +27 -0
- package/src/shared/runtime-environment.js +32 -0
- package/src/shared/websocket.js +258 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
const { spawn } = require("node:child_process");
|
|
2
|
+
const readline = require("node:readline");
|
|
3
|
+
const { EventEmitter } = require("node:events");
|
|
4
|
+
const { resolveCodexExecutable } = require("./codex-runtime");
|
|
5
|
+
|
|
6
|
+
const DEFAULT_CLIENT_INFO = {
|
|
7
|
+
name: "agent_anywhere",
|
|
8
|
+
title: "Agent Anywhere",
|
|
9
|
+
version: "0.1.0"
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
class CodexAppServerClient extends EventEmitter {
|
|
13
|
+
constructor({
|
|
14
|
+
codexPathOverride,
|
|
15
|
+
spawnImpl = spawn,
|
|
16
|
+
clientInfo = DEFAULT_CLIENT_INFO
|
|
17
|
+
} = {}) {
|
|
18
|
+
super();
|
|
19
|
+
this.codexPathOverride = codexPathOverride || process.env.CODEX_CLI_PATH || undefined;
|
|
20
|
+
this.spawnImpl = spawnImpl;
|
|
21
|
+
this.clientInfo = clientInfo;
|
|
22
|
+
this.nextRequestId = 1;
|
|
23
|
+
this.pendingRequests = new Map();
|
|
24
|
+
this.process = null;
|
|
25
|
+
this.reader = null;
|
|
26
|
+
this.closed = false;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
start() {
|
|
30
|
+
if (this.process) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const codexPath = resolveCodexExecutable(this.codexPathOverride);
|
|
34
|
+
this.process = this.spawnImpl(codexPath, ["app-server"], {
|
|
35
|
+
env: process.env,
|
|
36
|
+
stdio: ["pipe", "pipe", "inherit"]
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
this.reader = readline.createInterface({ input: this.process.stdout });
|
|
40
|
+
this.reader.on("line", (line) => this.handleLine(line));
|
|
41
|
+
this.process.on("error", (error) => this.failPending(error));
|
|
42
|
+
this.process.on("exit", (code, signal) => {
|
|
43
|
+
this.closed = true;
|
|
44
|
+
const suffix = signal ? `signal ${signal}` : `code ${code}`;
|
|
45
|
+
this.failPending(new Error(`codex app-server 已退出:${suffix}`));
|
|
46
|
+
this.emit("exit", { code, signal });
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async initialize() {
|
|
51
|
+
this.start();
|
|
52
|
+
const result = await this.request("initialize", {
|
|
53
|
+
clientInfo: this.clientInfo,
|
|
54
|
+
capabilities: {
|
|
55
|
+
experimentalApi: true
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
this.notify("initialized", {});
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
request(method, params = {}) {
|
|
63
|
+
this.start();
|
|
64
|
+
const id = this.nextRequestId++;
|
|
65
|
+
this.write({ method, id, params });
|
|
66
|
+
return new Promise((resolve, reject) => {
|
|
67
|
+
this.pendingRequests.set(id, { resolve, reject, method });
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
notify(method, params = {}) {
|
|
72
|
+
this.start();
|
|
73
|
+
this.write({ method, params });
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
respond(id, result = {}) {
|
|
77
|
+
this.write({ id, result });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
respondError(id, error) {
|
|
81
|
+
this.write({
|
|
82
|
+
id,
|
|
83
|
+
error: {
|
|
84
|
+
code: error?.code || -32000,
|
|
85
|
+
message: error?.message || String(error || "request failed")
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
close() {
|
|
91
|
+
this.closed = true;
|
|
92
|
+
this.reader?.close();
|
|
93
|
+
if (this.process && !this.process.killed) {
|
|
94
|
+
this.process.kill();
|
|
95
|
+
}
|
|
96
|
+
this.failPending(new Error("codex app-server client closed"));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
write(message) {
|
|
100
|
+
if (!this.process || this.closed) {
|
|
101
|
+
throw new Error("codex app-server client is not running");
|
|
102
|
+
}
|
|
103
|
+
this.process.stdin.write(`${JSON.stringify(message)}\n`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
handleLine(line) {
|
|
107
|
+
let message;
|
|
108
|
+
try {
|
|
109
|
+
message = JSON.parse(line);
|
|
110
|
+
} catch (error) {
|
|
111
|
+
this.emit("error", new Error(`codex app-server 输出不是合法 JSON:${error.message}`));
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (message && Object.prototype.hasOwnProperty.call(message, "id") && !message.method) {
|
|
116
|
+
const pending = this.pendingRequests.get(message.id);
|
|
117
|
+
if (!pending) {
|
|
118
|
+
this.emit("unknownResponse", message);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
this.pendingRequests.delete(message.id);
|
|
122
|
+
if (message.error) {
|
|
123
|
+
const error = new Error(message.error.message || `codex app-server 请求失败:${pending.method}`);
|
|
124
|
+
error.code = message.error.code;
|
|
125
|
+
error.data = message.error.data;
|
|
126
|
+
pending.reject(error);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
pending.resolve(message.result);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (message && Object.prototype.hasOwnProperty.call(message, "id") && message.method) {
|
|
134
|
+
this.emit("request", message);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (message?.method) {
|
|
139
|
+
this.emit("notification", message);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
this.emit("unknownMessage", message);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
failPending(error) {
|
|
147
|
+
for (const pending of this.pendingRequests.values()) {
|
|
148
|
+
pending.reject(error);
|
|
149
|
+
}
|
|
150
|
+
this.pendingRequests.clear();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
module.exports = {
|
|
155
|
+
CodexAppServerClient,
|
|
156
|
+
DEFAULT_CLIENT_INFO
|
|
157
|
+
};
|