@yuandc/aica 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 +9 -0
- package/dist/acp/agent.js +54 -0
- package/dist/acp/client/acp-client.js +102 -0
- package/dist/acp/client/acp-content.js +13 -0
- package/dist/acp/client/acp-events.js +106 -0
- package/dist/acp/client/acp-process.js +34 -0
- package/dist/acp/client/acp-runtime-pool.js +248 -0
- package/dist/acp/client/context-usage.js +29 -0
- package/dist/acp/client/json-rpc.js +128 -0
- package/dist/acp/provider-types.js +1 -0
- package/dist/acp/providers/codex/codex-process.js +51 -0
- package/dist/acp/providers/codex/events.js +1473 -0
- package/dist/acp/providers/codex/permissions.js +49 -0
- package/dist/acp/providers/codex/provider.js +376 -0
- package/dist/acp/providers/codex-acp/adapter.js +947 -0
- package/dist/acp/providers/codex-acp/context-maintenance.js +148 -0
- package/dist/acp/providers/codex-acp/launch.js +35 -0
- package/dist/acp/providers/codex-acp/provider.js +486 -0
- package/dist/acp/providers/mimo/provider.js +448 -0
- package/dist/acp/providers/opencode/provider.js +489 -0
- package/dist/acp/providers/registry.js +23 -0
- package/dist/acp/standard-events.js +167 -0
- package/dist/commands/start.js +137 -0
- package/dist/commands/worker-auth.js +100 -0
- package/dist/commands/worker-project.js +57 -0
- package/dist/core/aca-config.js +74 -0
- package/dist/core/aca-server-client.js +57 -0
- package/dist/core/acp-event-coalescer.js +108 -0
- package/dist/core/acp-event-upload-filter.js +16 -0
- package/dist/core/acp-orphan-cleanup.js +91 -0
- package/dist/core/affected-files.js +268 -0
- package/dist/core/auth.js +36 -0
- package/dist/core/file-transfer-worker.js +169 -0
- package/dist/core/fs.js +28 -0
- package/dist/core/heartbeat.js +578 -0
- package/dist/core/job-permission-policy.js +42 -0
- package/dist/core/job-worker.js +749 -0
- package/dist/core/logger.js +42 -0
- package/dist/core/long-poll-worker.js +26 -0
- package/dist/core/machine-filesystem-worker.js +352 -0
- package/dist/core/paths.js +26 -0
- package/dist/core/process-identity.js +34 -0
- package/dist/core/process.js +33 -0
- package/dist/core/provider-health.js +54 -0
- package/dist/core/runtime-options.js +38 -0
- package/dist/core/worktree.js +95 -0
- package/dist/worker-cli.js +27 -0
- package/dist/worker-single-cli.js +17 -0
- package/package.json +35 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
export class JsonLineRpcClient {
|
|
2
|
+
child;
|
|
3
|
+
handlers;
|
|
4
|
+
nextId = 1;
|
|
5
|
+
lineBuffer = "";
|
|
6
|
+
pending = new Map();
|
|
7
|
+
peerName;
|
|
8
|
+
includeJsonRpc;
|
|
9
|
+
notifications = [];
|
|
10
|
+
stdout = "";
|
|
11
|
+
stderr = "";
|
|
12
|
+
exitCode = null;
|
|
13
|
+
signal = null;
|
|
14
|
+
constructor(child, handlers = {}) {
|
|
15
|
+
this.child = child;
|
|
16
|
+
this.handlers = handlers;
|
|
17
|
+
this.peerName = handlers.peerName || "JSON-RPC peer";
|
|
18
|
+
this.includeJsonRpc = handlers.includeJsonRpc === true;
|
|
19
|
+
child.stdout.on("data", (chunk) => this.handleStdout(String(chunk)));
|
|
20
|
+
child.stderr.on("data", (chunk) => {
|
|
21
|
+
this.stderr += String(chunk);
|
|
22
|
+
});
|
|
23
|
+
child.on("close", (code, signal) => {
|
|
24
|
+
this.exitCode = code;
|
|
25
|
+
this.signal = signal;
|
|
26
|
+
for (const [id, pending] of this.pending) {
|
|
27
|
+
clearTimeout(pending.timer);
|
|
28
|
+
pending.reject(new Error(`${this.peerName} exited before ${pending.method} completed (code=${code}, signal=${signal})`));
|
|
29
|
+
this.pending.delete(id);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
child.on("error", (error) => {
|
|
33
|
+
for (const [id, pending] of this.pending) {
|
|
34
|
+
clearTimeout(pending.timer);
|
|
35
|
+
pending.reject(error);
|
|
36
|
+
this.pending.delete(id);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
request(method, params, timeoutMs = 120_000) {
|
|
41
|
+
const id = this.nextId++;
|
|
42
|
+
return new Promise((resolve, reject) => {
|
|
43
|
+
const timer = this.createRequestTimeout(id, method, timeoutMs, reject);
|
|
44
|
+
timer.unref();
|
|
45
|
+
this.pending.set(id, { method, resolve, reject, timer, timeoutMs });
|
|
46
|
+
this.write({ ...(this.includeJsonRpc ? { jsonrpc: "2.0" } : {}), id, method, ...(params === undefined ? {} : { params }) });
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
notify(method, params) {
|
|
50
|
+
this.write({ ...(this.includeJsonRpc ? { jsonrpc: "2.0" } : {}), method, ...(params === undefined ? {} : { params }) });
|
|
51
|
+
}
|
|
52
|
+
refreshPendingRequestTimeout(method) {
|
|
53
|
+
for (const [id, pending] of this.pending) {
|
|
54
|
+
if (pending.method !== method)
|
|
55
|
+
continue;
|
|
56
|
+
clearTimeout(pending.timer);
|
|
57
|
+
pending.timer = this.createRequestTimeout(id, pending.method, pending.timeoutMs, pending.reject);
|
|
58
|
+
pending.timer.unref();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
respond(id, result) {
|
|
62
|
+
this.write({ ...(this.includeJsonRpc ? { jsonrpc: "2.0" } : {}), id, result });
|
|
63
|
+
}
|
|
64
|
+
respondError(id, error) {
|
|
65
|
+
this.write({ ...(this.includeJsonRpc ? { jsonrpc: "2.0" } : {}), id, error: { code: -32603, message: error.message } });
|
|
66
|
+
}
|
|
67
|
+
createRequestTimeout(id, method, timeoutMs, reject) {
|
|
68
|
+
return setTimeout(() => {
|
|
69
|
+
this.pending.delete(id);
|
|
70
|
+
reject(new Error(`${this.peerName} request timed out while waiting for ${method}`));
|
|
71
|
+
}, timeoutMs);
|
|
72
|
+
}
|
|
73
|
+
handleStdout(chunk) {
|
|
74
|
+
this.stdout += chunk;
|
|
75
|
+
this.lineBuffer += chunk;
|
|
76
|
+
const lines = this.lineBuffer.split("\n");
|
|
77
|
+
this.lineBuffer = lines.pop() ?? "";
|
|
78
|
+
for (const line of lines) {
|
|
79
|
+
const trimmed = line.trim();
|
|
80
|
+
if (!trimmed)
|
|
81
|
+
continue;
|
|
82
|
+
let message;
|
|
83
|
+
try {
|
|
84
|
+
message = JSON.parse(trimmed);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
this.stderr += `\n[non-json stdout] ${trimmed}`;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
void this.handleMessage(message);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async handleMessage(message) {
|
|
94
|
+
if ("id" in message && ("result" in message || "error" in message) && typeof message.method !== "string") {
|
|
95
|
+
const id = Number(message.id);
|
|
96
|
+
const pending = this.pending.get(id);
|
|
97
|
+
if (!pending)
|
|
98
|
+
return;
|
|
99
|
+
this.pending.delete(id);
|
|
100
|
+
clearTimeout(pending.timer);
|
|
101
|
+
if ("error" in message) {
|
|
102
|
+
const error = message.error;
|
|
103
|
+
pending.reject(new Error(error?.message || `${this.peerName} error ${error?.code ?? "unknown"}`));
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
pending.resolve(message.result);
|
|
107
|
+
}
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (typeof message.method !== "string")
|
|
111
|
+
return;
|
|
112
|
+
if ("id" in message) {
|
|
113
|
+
try {
|
|
114
|
+
const result = await this.handlers.onRequest?.(message.method, message.params, message);
|
|
115
|
+
this.respond(message.id, result ?? null);
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
this.respondError(message.id, error instanceof Error ? error : new Error(String(error)));
|
|
119
|
+
}
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
this.notifications.push(message);
|
|
123
|
+
await this.handlers.onNotification?.(message.method, message.params, message);
|
|
124
|
+
}
|
|
125
|
+
write(message) {
|
|
126
|
+
this.child.stdin.write(`${JSON.stringify(message)}\n`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import { acpChildEnvironment } from "../../../core/process-identity.js";
|
|
4
|
+
export function startCodexAppServer(cwd) {
|
|
5
|
+
const command = resolveCodexPath();
|
|
6
|
+
const args = ["app-server", "--stdio"];
|
|
7
|
+
const child = spawn(command, args, {
|
|
8
|
+
cwd,
|
|
9
|
+
env: acpChildEnvironment({ CODEX_PATH: command }),
|
|
10
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
11
|
+
});
|
|
12
|
+
child.stdout.setEncoding("utf8");
|
|
13
|
+
child.stderr.setEncoding("utf8");
|
|
14
|
+
return { command, args, child };
|
|
15
|
+
}
|
|
16
|
+
export function resolveCodexPath() {
|
|
17
|
+
const explicit = process.env.CODEX_PATH;
|
|
18
|
+
if (explicit?.trim() && !isNodeWrapperCodexPath(explicit))
|
|
19
|
+
return explicit;
|
|
20
|
+
const nativeCandidates = [
|
|
21
|
+
"/usr/local/lib/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/bin/codex"
|
|
22
|
+
];
|
|
23
|
+
const native = nativeCandidates.find((candidate) => isExecutableFile(candidate));
|
|
24
|
+
if (native)
|
|
25
|
+
return native;
|
|
26
|
+
const fallbackCandidates = [
|
|
27
|
+
...(explicit?.trim() ? [explicit] : []),
|
|
28
|
+
"/usr/local/lib/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/bin/codex",
|
|
29
|
+
"/usr/local/bin/codex",
|
|
30
|
+
"codex"
|
|
31
|
+
];
|
|
32
|
+
return fallbackCandidates.find((candidate) => candidate === "codex" || isExecutableFile(candidate)) ?? "codex";
|
|
33
|
+
}
|
|
34
|
+
function isExecutableFile(filePath) {
|
|
35
|
+
try {
|
|
36
|
+
fs.accessSync(filePath, fs.constants.X_OK);
|
|
37
|
+
return fs.statSync(filePath).isFile();
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function isNodeWrapperCodexPath(filePath) {
|
|
44
|
+
try {
|
|
45
|
+
const realPath = fs.realpathSync(filePath);
|
|
46
|
+
return realPath.endsWith(".js");
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|