replicas-engine 0.1.702 → 0.1.704
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/src/chunk-2RB7SIP3.js +10 -0
- package/dist/src/chunk-EC4MFY4M.js +551 -0
- package/dist/src/chunk-GDCMH7YA.js +23 -0
- package/dist/src/{chunk-UNES5UCP.js → chunk-WUJ4IALO.js} +42 -544
- package/dist/src/chunk-ZCBMGGAC.js +284 -0
- package/dist/src/command-protection-hook.js +50 -0
- package/dist/src/deepseek-command-protection-plugin.js +32 -0
- package/dist/src/headless-agent.js +6 -4
- package/dist/src/index.js +521 -818
- package/dist/src/post-tool-pr-hook.js +26 -0
- package/package.json +4 -1
- package/scripts/deepseek/replicas.cordis.patch.yml +4 -0
- package/scripts/opencode-command-protection-plugin.ts +88 -0
|
@@ -1128,6 +1128,13 @@ async function raceWithTimeout(promise, ms) {
|
|
|
1128
1128
|
});
|
|
1129
1129
|
}
|
|
1130
1130
|
}
|
|
1131
|
+
async function withTimeout(promise, ms, message) {
|
|
1132
|
+
const result = await raceWithTimeout(promise, ms);
|
|
1133
|
+
if (result === TIMEOUT) {
|
|
1134
|
+
throw new Error(message);
|
|
1135
|
+
}
|
|
1136
|
+
return result;
|
|
1137
|
+
}
|
|
1131
1138
|
|
|
1132
1139
|
// ../shared/src/agent-quota.ts
|
|
1133
1140
|
var OUT_OF_CREDITS_PATTERNS = [
|
|
@@ -3659,6 +3666,37 @@ function findGitCommitSignals(request) {
|
|
|
3659
3666
|
const command = extractCommandProtectionCommandText(request, { stringifyFallback: true }) ?? "";
|
|
3660
3667
|
return findGitCommitCommands(command).length > 0 ? ["git-commit"] : [];
|
|
3661
3668
|
}
|
|
3669
|
+
function mayCreatePullRequest(toolName, toolInput) {
|
|
3670
|
+
const input = normalizeCommandProtectionText(stringifyCommandProtectionInput(toolInput));
|
|
3671
|
+
const combined = `${toolName.toLowerCase()} ${input}`;
|
|
3672
|
+
return [
|
|
3673
|
+
/\bgit\s+push\b/,
|
|
3674
|
+
/\bgit\s+(?:branch|checkout|switch|pull|merge|rebase|reset)\b/,
|
|
3675
|
+
/\bgit\s+worktree\s+add\b/,
|
|
3676
|
+
/\bgh\b.{0,120}\bpr\s+(?:checkout|create|new|ready|reopen)\b/,
|
|
3677
|
+
/\bgh\s+api\b[\s\S]*(?:\/repos\/[^/\s]+\/[^/\s]+\/pulls\b|\bcreatepullrequest\b)/,
|
|
3678
|
+
/\b(?:glab|gitlab)\s+mr\s+(?:checkout|create)\b/,
|
|
3679
|
+
/\bhub\s+pull-request\b/,
|
|
3680
|
+
/\b(?:tea\s+pulls|bb\s+pr|az\s+repos\s+pr)\s+create\b/,
|
|
3681
|
+
/\bcreatepullrequest\b/,
|
|
3682
|
+
/\b(?:create|open|submit)[_-]?(?:pr|pull[_-]?request|mr|merge[_-]?request)\b/,
|
|
3683
|
+
/\b(?:pr|pull[_-]?request|mr|merge[_-]?request)[_-]?(?:create|open|submit)\b/,
|
|
3684
|
+
/\b(?:checkout|create|switch)[_-]?branch\b/,
|
|
3685
|
+
/\bbranch[_-]?(?:checkout|create|switch)\b/,
|
|
3686
|
+
/\b(?:switched to|checked out|created and switched to)(?: a new)? branch\b/,
|
|
3687
|
+
/github\.com\/[^/\s]+\/[^/\s]+\/pull\/\d+\b/,
|
|
3688
|
+
/\/merge_requests\/\d+\b/,
|
|
3689
|
+
/\b(?:create|open|submit)(?:pull|merge)request\b/,
|
|
3690
|
+
/\b(?:pull|merge)request(?:create|open|submit)\b/,
|
|
3691
|
+
/\bmergerequestcreate\b/,
|
|
3692
|
+
/api\.github\.com\/repos\/[^/\s]+\/[^/\s]+\/pulls\b/,
|
|
3693
|
+
/\/projects\/[^/\s]+\/merge_requests\b/,
|
|
3694
|
+
/\/pullrequests\b/,
|
|
3695
|
+
/\/_apis\/git\/repositories\/[^/\s]+\/pullrequests\b/,
|
|
3696
|
+
/\/pulls\b[\s\S]*\b(?:post|create)\b/,
|
|
3697
|
+
/\/merge_requests\b[\s\S]*\b(?:post|create)\b/
|
|
3698
|
+
].some((pattern) => pattern.test(combined));
|
|
3699
|
+
}
|
|
3662
3700
|
|
|
3663
3701
|
// ../shared/src/routes/plugin-catalog.ts
|
|
3664
3702
|
var EXPLICIT_PLUGIN_CATALOG = [
|
|
@@ -6574,529 +6612,12 @@ function isSkillRegistryManifest(value) {
|
|
|
6574
6612
|
);
|
|
6575
6613
|
}
|
|
6576
6614
|
|
|
6577
|
-
// src/utils/presigned-upload.ts
|
|
6578
|
-
import { createReadStream } from "fs";
|
|
6579
|
-
import { request as httpRequest } from "http";
|
|
6580
|
-
import { request as httpsRequest } from "https";
|
|
6581
|
-
async function putPresignedFile(urlValue, filePath, size, contentType) {
|
|
6582
|
-
await new Promise((resolve, reject) => {
|
|
6583
|
-
const url = new URL(urlValue);
|
|
6584
|
-
const request = (url.protocol === "https:" ? httpsRequest : httpRequest)(url, {
|
|
6585
|
-
method: "PUT",
|
|
6586
|
-
headers: {
|
|
6587
|
-
"content-length": String(size),
|
|
6588
|
-
"content-type": contentType
|
|
6589
|
-
}
|
|
6590
|
-
}, (response) => {
|
|
6591
|
-
response.setEncoding("utf8");
|
|
6592
|
-
let body = "";
|
|
6593
|
-
response.on("data", (chunk) => {
|
|
6594
|
-
body += chunk;
|
|
6595
|
-
});
|
|
6596
|
-
response.on("end", () => {
|
|
6597
|
-
const status = response.statusCode ?? 0;
|
|
6598
|
-
if (status >= 200 && status < 300) resolve();
|
|
6599
|
-
else reject(new Error(`upload failed: ${status} ${body}`));
|
|
6600
|
-
});
|
|
6601
|
-
response.on("error", reject);
|
|
6602
|
-
});
|
|
6603
|
-
request.on("error", reject);
|
|
6604
|
-
const file = size > 0 ? createReadStream(filePath, { start: 0, end: size - 1 }) : createReadStream(filePath);
|
|
6605
|
-
file.on("error", (error) => request.destroy(error));
|
|
6606
|
-
file.pipe(request);
|
|
6607
|
-
});
|
|
6608
|
-
}
|
|
6609
|
-
|
|
6610
|
-
// src/utils/codex-agent-env.ts
|
|
6611
|
-
function buildCodexAgentEnv(source = process.env) {
|
|
6612
|
-
const env = Object.fromEntries(
|
|
6613
|
-
Object.entries(source).filter((entry) => typeof entry[1] === "string")
|
|
6614
|
-
);
|
|
6615
|
-
if (env.REPLICAS_CODEX_AUTH_METHOD === "oauth" || env.REPLICAS_CODEX_AUTH_METHOD === "foundry") {
|
|
6616
|
-
delete env.OPENAI_API_KEY;
|
|
6617
|
-
}
|
|
6618
|
-
delete env.GH_TOKEN;
|
|
6619
|
-
delete env.GITHUB_TOKEN;
|
|
6620
|
-
delete env.GH_CONFIG_DIR;
|
|
6621
|
-
return env;
|
|
6622
|
-
}
|
|
6623
|
-
|
|
6624
|
-
// src/utils/exec.ts
|
|
6625
|
-
import { exec, execFile } from "child_process";
|
|
6626
|
-
import { promisify } from "util";
|
|
6627
|
-
var execAsync = promisify(exec);
|
|
6628
|
-
var execFileAsync = promisify(execFile);
|
|
6629
|
-
var SUBPROCESS_MAX_BUFFER = HOOK_EXEC_MAX_BUFFER_BYTES;
|
|
6630
|
-
|
|
6631
|
-
// src/managers/codex-asp/app-server-process.ts
|
|
6632
|
-
import { spawn } from "child_process";
|
|
6633
|
-
import { EventEmitter as EventEmitter2 } from "events";
|
|
6634
|
-
|
|
6635
|
-
// src/managers/codex-asp/asp-client.ts
|
|
6636
|
-
import { EventEmitter } from "events";
|
|
6637
|
-
var DEFAULT_REQUEST_TIMEOUT_MS = 12e4;
|
|
6638
|
-
function hasOwn(record, key) {
|
|
6639
|
-
return Object.prototype.hasOwnProperty.call(record, key);
|
|
6640
|
-
}
|
|
6641
|
-
var AspClient = class {
|
|
6642
|
-
stdin;
|
|
6643
|
-
stdout;
|
|
6644
|
-
emitter = new EventEmitter();
|
|
6645
|
-
pending = /* @__PURE__ */ new Map();
|
|
6646
|
-
nextId = 1;
|
|
6647
|
-
lineBuffer = "";
|
|
6648
|
-
disposed = false;
|
|
6649
|
-
get isDisposed() {
|
|
6650
|
-
return this.disposed;
|
|
6651
|
-
}
|
|
6652
|
-
constructor(options) {
|
|
6653
|
-
this.stdin = options.stdin;
|
|
6654
|
-
this.stdout = options.stdout;
|
|
6655
|
-
this.stdout.setEncoding("utf8");
|
|
6656
|
-
this.stdout.on("data", this.handleStdoutData);
|
|
6657
|
-
this.stdin.on("error", this.handleStdinError);
|
|
6658
|
-
}
|
|
6659
|
-
on(event, listener) {
|
|
6660
|
-
this.emitter.on(event, listener);
|
|
6661
|
-
}
|
|
6662
|
-
off(event, listener) {
|
|
6663
|
-
this.emitter.off(event, listener);
|
|
6664
|
-
}
|
|
6665
|
-
async request(method, params, opts) {
|
|
6666
|
-
if (this.disposed) {
|
|
6667
|
-
throw new Error(`Cannot send ${method}: ASP client disposed`);
|
|
6668
|
-
}
|
|
6669
|
-
const id = this.nextId;
|
|
6670
|
-
this.nextId += 1;
|
|
6671
|
-
const promise = new Promise((resolve, reject) => {
|
|
6672
|
-
const timeoutMs = opts?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
6673
|
-
const timer = timeoutMs > 0 ? setTimeout(() => {
|
|
6674
|
-
this.pending.delete(id);
|
|
6675
|
-
reject(new Error(`ASP request timed out for ${method}`));
|
|
6676
|
-
}, timeoutMs) : null;
|
|
6677
|
-
this.pending.set(id, { resolve, reject, method, timer });
|
|
6678
|
-
});
|
|
6679
|
-
this.write({ method, id, params });
|
|
6680
|
-
return promise;
|
|
6681
|
-
}
|
|
6682
|
-
notify(method, params) {
|
|
6683
|
-
if (this.disposed) {
|
|
6684
|
-
return;
|
|
6685
|
-
}
|
|
6686
|
-
try {
|
|
6687
|
-
this.write(params === void 0 ? { method } : { method, params });
|
|
6688
|
-
} catch (error) {
|
|
6689
|
-
console.warn(`[AspClient] Failed to send notification ${method}:`, error);
|
|
6690
|
-
}
|
|
6691
|
-
}
|
|
6692
|
-
respond(id, result) {
|
|
6693
|
-
if (this.disposed) {
|
|
6694
|
-
return;
|
|
6695
|
-
}
|
|
6696
|
-
try {
|
|
6697
|
-
this.write({ id, result });
|
|
6698
|
-
} catch (error) {
|
|
6699
|
-
console.warn(`[AspClient] Failed to send response ${String(id)}:`, error);
|
|
6700
|
-
}
|
|
6701
|
-
}
|
|
6702
|
-
reject(id, code, message, data) {
|
|
6703
|
-
if (this.disposed) {
|
|
6704
|
-
return;
|
|
6705
|
-
}
|
|
6706
|
-
try {
|
|
6707
|
-
this.write({
|
|
6708
|
-
id,
|
|
6709
|
-
error: {
|
|
6710
|
-
code,
|
|
6711
|
-
message,
|
|
6712
|
-
...data !== void 0 ? { data } : {}
|
|
6713
|
-
}
|
|
6714
|
-
});
|
|
6715
|
-
} catch (error) {
|
|
6716
|
-
console.warn(`[AspClient] Failed to send error response ${String(id)}:`, error);
|
|
6717
|
-
}
|
|
6718
|
-
}
|
|
6719
|
-
dispose(reason = new Error("ASP client disposed")) {
|
|
6720
|
-
if (this.disposed) {
|
|
6721
|
-
return;
|
|
6722
|
-
}
|
|
6723
|
-
this.disposed = true;
|
|
6724
|
-
this.stdout.off("data", this.handleStdoutData);
|
|
6725
|
-
this.stdin.removeListener("error", this.handleStdinError);
|
|
6726
|
-
for (const [id, pending] of this.pending) {
|
|
6727
|
-
if (pending.timer) {
|
|
6728
|
-
clearTimeout(pending.timer);
|
|
6729
|
-
}
|
|
6730
|
-
pending.reject(new Error(`${reason.message} while waiting for ${pending.method}`));
|
|
6731
|
-
this.pending.delete(id);
|
|
6732
|
-
}
|
|
6733
|
-
this.lineBuffer = "";
|
|
6734
|
-
this.emitter.emit("dispose", reason);
|
|
6735
|
-
this.emitter.removeAllListeners();
|
|
6736
|
-
}
|
|
6737
|
-
handleStdoutData = (chunk) => {
|
|
6738
|
-
this.lineBuffer += chunk.toString();
|
|
6739
|
-
let newlineIndex = this.lineBuffer.indexOf("\n");
|
|
6740
|
-
while (newlineIndex >= 0) {
|
|
6741
|
-
const line = this.lineBuffer.slice(0, newlineIndex).trim();
|
|
6742
|
-
this.lineBuffer = this.lineBuffer.slice(newlineIndex + 1);
|
|
6743
|
-
if (line.length > 0) {
|
|
6744
|
-
this.handleLine(line);
|
|
6745
|
-
}
|
|
6746
|
-
newlineIndex = this.lineBuffer.indexOf("\n");
|
|
6747
|
-
}
|
|
6748
|
-
};
|
|
6749
|
-
handleStdinError = (error) => {
|
|
6750
|
-
this.dispose(new Error(`ASP stdin error: ${error.message}`));
|
|
6751
|
-
};
|
|
6752
|
-
handleLine(line) {
|
|
6753
|
-
let parsed;
|
|
6754
|
-
try {
|
|
6755
|
-
parsed = JSON.parse(line);
|
|
6756
|
-
} catch (error) {
|
|
6757
|
-
console.warn("[AspClient] Failed to parse ASP JSON line:", error);
|
|
6758
|
-
return;
|
|
6759
|
-
}
|
|
6760
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
6761
|
-
console.warn("[AspClient] Ignoring non-object ASP message");
|
|
6762
|
-
return;
|
|
6763
|
-
}
|
|
6764
|
-
const message = parsed;
|
|
6765
|
-
const hasRequestId = typeof message.id === "number" || typeof message.id === "string";
|
|
6766
|
-
if (hasRequestId && (hasOwn(message, "result") || hasOwn(message, "error"))) {
|
|
6767
|
-
this.handleResponse(message);
|
|
6768
|
-
return;
|
|
6769
|
-
}
|
|
6770
|
-
if (hasRequestId && typeof message.method === "string") {
|
|
6771
|
-
this.emitter.emit("serverRequest", message);
|
|
6772
|
-
return;
|
|
6773
|
-
}
|
|
6774
|
-
if (!hasOwn(message, "id") && typeof message.method === "string") {
|
|
6775
|
-
this.emitter.emit("notification", message);
|
|
6776
|
-
}
|
|
6777
|
-
}
|
|
6778
|
-
handleResponse(message) {
|
|
6779
|
-
if (typeof message.id !== "number") {
|
|
6780
|
-
console.warn("[AspClient] Ignoring response with non-numeric request id");
|
|
6781
|
-
return;
|
|
6782
|
-
}
|
|
6783
|
-
const pending = this.pending.get(message.id);
|
|
6784
|
-
if (!pending) {
|
|
6785
|
-
console.warn(`[AspClient] Ignoring response for unknown request id ${message.id}`);
|
|
6786
|
-
return;
|
|
6787
|
-
}
|
|
6788
|
-
this.pending.delete(message.id);
|
|
6789
|
-
if (pending.timer) {
|
|
6790
|
-
clearTimeout(pending.timer);
|
|
6791
|
-
}
|
|
6792
|
-
if (hasOwn(message, "error")) {
|
|
6793
|
-
pending.reject(this.createRpcError(pending.method, message.error));
|
|
6794
|
-
return;
|
|
6795
|
-
}
|
|
6796
|
-
pending.resolve(message.result);
|
|
6797
|
-
}
|
|
6798
|
-
createRpcError(method, error) {
|
|
6799
|
-
if (typeof error !== "object" || error === null || Array.isArray(error)) {
|
|
6800
|
-
return new Error(`ASP request failed for ${method}`);
|
|
6801
|
-
}
|
|
6802
|
-
const rpcError = error;
|
|
6803
|
-
const code = typeof rpcError.code === "number" ? ` ${rpcError.code}` : "";
|
|
6804
|
-
const message = typeof rpcError.message === "string" ? rpcError.message : "Unknown ASP error";
|
|
6805
|
-
const data = hasOwn(rpcError, "data") ? ` data=${JSON.stringify(rpcError.data)}` : "";
|
|
6806
|
-
return new Error(`ASP request failed for ${method}:${code} ${message}${data}`);
|
|
6807
|
-
}
|
|
6808
|
-
write(message) {
|
|
6809
|
-
try {
|
|
6810
|
-
this.stdin.write(`${JSON.stringify(message)}
|
|
6811
|
-
`, (error) => {
|
|
6812
|
-
if (error) {
|
|
6813
|
-
this.dispose(new Error(`ASP write failed: ${error.message}`));
|
|
6814
|
-
}
|
|
6815
|
-
});
|
|
6816
|
-
} catch (error) {
|
|
6817
|
-
const writeError = error instanceof Error ? error : new Error("ASP write failed");
|
|
6818
|
-
this.dispose(writeError);
|
|
6819
|
-
throw writeError;
|
|
6820
|
-
}
|
|
6821
|
-
}
|
|
6822
|
-
};
|
|
6823
|
-
|
|
6824
|
-
// src/managers/codex-asp/app-server-process.ts
|
|
6825
|
-
var DEFAULT_CODEX_BINARY = "codex";
|
|
6826
|
-
var DEFAULT_CODEX_ARGS = [
|
|
6827
|
-
"app-server",
|
|
6828
|
-
"--listen",
|
|
6829
|
-
"stdio://",
|
|
6830
|
-
"-c",
|
|
6831
|
-
"features.memories=false",
|
|
6832
|
-
"-c",
|
|
6833
|
-
"memories.use_memories=false",
|
|
6834
|
-
"-c",
|
|
6835
|
-
"memories.generate_memories=false"
|
|
6836
|
-
];
|
|
6837
|
-
var MIN_CODEX_CLI_VERSION = "0.144.6";
|
|
6838
|
-
var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
|
|
6839
|
-
var codexCliVersionEnsured = null;
|
|
6840
|
-
var ENGINE_PACKAGE_VERSION = "0.1.702";
|
|
6841
|
-
var INITIALIZE_METHOD = "initialize";
|
|
6842
|
-
var INITIALIZED_NOTIFICATION = "initialized";
|
|
6843
|
-
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|
|
6844
|
-
var AppServerProcess = class {
|
|
6845
|
-
binary;
|
|
6846
|
-
args;
|
|
6847
|
-
env;
|
|
6848
|
-
cwd;
|
|
6849
|
-
chatgptAuthTokens;
|
|
6850
|
-
refreshChatgptAuthTokens;
|
|
6851
|
-
emitter = new EventEmitter2();
|
|
6852
|
-
child = null;
|
|
6853
|
-
client = null;
|
|
6854
|
-
shuttingDown = false;
|
|
6855
|
-
invalidating = false;
|
|
6856
|
-
constructor(options) {
|
|
6857
|
-
this.binary = options.binary ?? DEFAULT_CODEX_BINARY;
|
|
6858
|
-
const baseArgs = options.args ?? (options.env.REPLICAS_CODEX_AUTH_METHOD === "foundry" ? [
|
|
6859
|
-
...DEFAULT_CODEX_ARGS,
|
|
6860
|
-
"-c",
|
|
6861
|
-
`model=${JSON.stringify(options.env.CODEX_FOUNDRY_MODEL)}`,
|
|
6862
|
-
"-c",
|
|
6863
|
-
'model_provider="azure"',
|
|
6864
|
-
"-c",
|
|
6865
|
-
'model_providers.azure.name="Azure OpenAI"',
|
|
6866
|
-
"-c",
|
|
6867
|
-
`model_providers.azure.base_url=${JSON.stringify(options.env.CODEX_FOUNDRY_BASE_URL)}`,
|
|
6868
|
-
"-c",
|
|
6869
|
-
'model_providers.azure.env_key="AZURE_OPENAI_API_KEY"',
|
|
6870
|
-
"-c",
|
|
6871
|
-
'model_providers.azure.wire_api="responses"'
|
|
6872
|
-
] : DEFAULT_CODEX_ARGS);
|
|
6873
|
-
this.args = [...baseArgs, ...(options.configOverrides ?? []).flatMap((override) => ["-c", override])];
|
|
6874
|
-
this.env = options.env;
|
|
6875
|
-
this.cwd = options.cwd;
|
|
6876
|
-
this.chatgptAuthTokens = options.chatgptAuthTokens;
|
|
6877
|
-
this.refreshChatgptAuthTokens = options.refreshChatgptAuthTokens;
|
|
6878
|
-
}
|
|
6879
|
-
on(event, listener) {
|
|
6880
|
-
this.emitter.on(event, listener);
|
|
6881
|
-
}
|
|
6882
|
-
async start() {
|
|
6883
|
-
if (this.child && this.client) {
|
|
6884
|
-
return { client: this.client };
|
|
6885
|
-
}
|
|
6886
|
-
this.shuttingDown = false;
|
|
6887
|
-
this.invalidating = false;
|
|
6888
|
-
await this.ensureMinCodexCliVersion();
|
|
6889
|
-
const child = spawn(this.binary, this.args, {
|
|
6890
|
-
cwd: this.cwd,
|
|
6891
|
-
env: this.env,
|
|
6892
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
6893
|
-
});
|
|
6894
|
-
this.child = child;
|
|
6895
|
-
child.stderr.setEncoding("utf8");
|
|
6896
|
-
child.stderr.on("data", (chunk) => {
|
|
6897
|
-
for (const line of chunk.toString().split("\n")) {
|
|
6898
|
-
if (line.trim().length > 0) {
|
|
6899
|
-
console.error(`[codex-app-server] ${line}`);
|
|
6900
|
-
}
|
|
6901
|
-
}
|
|
6902
|
-
});
|
|
6903
|
-
child.on("exit", (code, signal) => {
|
|
6904
|
-
this.client?.dispose();
|
|
6905
|
-
this.client = null;
|
|
6906
|
-
this.child = null;
|
|
6907
|
-
if (!this.shuttingDown) {
|
|
6908
|
-
if (!this.invalidating) {
|
|
6909
|
-
console.warn(`[AppServerProcess] codex app-server exited unexpectedly code=${code ?? "null"} signal=${signal ?? "null"}`);
|
|
6910
|
-
}
|
|
6911
|
-
this.emitter.emit("exit", code, signal);
|
|
6912
|
-
}
|
|
6913
|
-
});
|
|
6914
|
-
const client = new AspClient({ stdin: child.stdin, stdout: child.stdout });
|
|
6915
|
-
this.client = client;
|
|
6916
|
-
client.on("serverRequest", (serverRequest) => {
|
|
6917
|
-
if (serverRequest.method !== "account/chatgptAuthTokens/refresh") return;
|
|
6918
|
-
if (!this.refreshChatgptAuthTokens) {
|
|
6919
|
-
client.reject(serverRequest.id, -32603, "Codex OAuth refresh is not configured");
|
|
6920
|
-
return;
|
|
6921
|
-
}
|
|
6922
|
-
void this.refreshChatgptAuthTokens(serverRequest.params).then((tokens) => {
|
|
6923
|
-
client.respond(serverRequest.id, tokens);
|
|
6924
|
-
}).catch((error) => {
|
|
6925
|
-
if (error instanceof Error && error.name === "CodexAspAuthMethodChangedError") {
|
|
6926
|
-
this.invalidating = true;
|
|
6927
|
-
client.dispose(error);
|
|
6928
|
-
if (!child.killed) child.kill("SIGTERM");
|
|
6929
|
-
return;
|
|
6930
|
-
}
|
|
6931
|
-
client.reject(
|
|
6932
|
-
serverRequest.id,
|
|
6933
|
-
-32603,
|
|
6934
|
-
error instanceof Error ? error.message : "Failed to refresh Codex OAuth credentials"
|
|
6935
|
-
);
|
|
6936
|
-
});
|
|
6937
|
-
});
|
|
6938
|
-
let cleanupEarlyFailureHandlers = () => {
|
|
6939
|
-
};
|
|
6940
|
-
const earlyFailure = new Promise((_resolve, reject) => {
|
|
6941
|
-
const onError = (error) => {
|
|
6942
|
-
reject(error);
|
|
6943
|
-
};
|
|
6944
|
-
const onExit = (code, signal) => {
|
|
6945
|
-
reject(new Error(`codex app-server exited before initialize completed code=${code ?? "null"} signal=${signal ?? "null"}`));
|
|
6946
|
-
};
|
|
6947
|
-
child.once("error", onError);
|
|
6948
|
-
child.once("exit", onExit);
|
|
6949
|
-
cleanupEarlyFailureHandlers = () => {
|
|
6950
|
-
child.off("error", onError);
|
|
6951
|
-
child.off("exit", onExit);
|
|
6952
|
-
};
|
|
6953
|
-
});
|
|
6954
|
-
try {
|
|
6955
|
-
const initializeParams = {
|
|
6956
|
-
clientInfo: {
|
|
6957
|
-
name: "replicas_engine",
|
|
6958
|
-
title: "Replicas Engine",
|
|
6959
|
-
version: ENGINE_PACKAGE_VERSION
|
|
6960
|
-
},
|
|
6961
|
-
capabilities: {
|
|
6962
|
-
experimentalApi: true,
|
|
6963
|
-
requestAttestation: false,
|
|
6964
|
-
optOutNotificationMethods: null
|
|
6965
|
-
}
|
|
6966
|
-
};
|
|
6967
|
-
await Promise.race([
|
|
6968
|
-
client.request(INITIALIZE_METHOD, initializeParams),
|
|
6969
|
-
earlyFailure
|
|
6970
|
-
]);
|
|
6971
|
-
cleanupEarlyFailureHandlers();
|
|
6972
|
-
client.notify(INITIALIZED_NOTIFICATION);
|
|
6973
|
-
await this.loginWithConfiguredCredentials(client);
|
|
6974
|
-
return { client };
|
|
6975
|
-
} catch (error) {
|
|
6976
|
-
cleanupEarlyFailureHandlers();
|
|
6977
|
-
client.dispose();
|
|
6978
|
-
await this.killAfterFailedStart();
|
|
6979
|
-
throw error;
|
|
6980
|
-
}
|
|
6981
|
-
}
|
|
6982
|
-
async stop() {
|
|
6983
|
-
const child = this.child;
|
|
6984
|
-
this.shuttingDown = true;
|
|
6985
|
-
this.client?.dispose(new Error("ASP process stopped"));
|
|
6986
|
-
this.client = null;
|
|
6987
|
-
this.child = null;
|
|
6988
|
-
if (!child || child.killed) {
|
|
6989
|
-
return;
|
|
6990
|
-
}
|
|
6991
|
-
await new Promise((resolve) => {
|
|
6992
|
-
const timer = setTimeout(() => {
|
|
6993
|
-
child.kill("SIGKILL");
|
|
6994
|
-
}, 2e3);
|
|
6995
|
-
child.once("exit", () => {
|
|
6996
|
-
clearTimeout(timer);
|
|
6997
|
-
resolve();
|
|
6998
|
-
});
|
|
6999
|
-
child.kill("SIGTERM");
|
|
7000
|
-
});
|
|
7001
|
-
}
|
|
7002
|
-
ensureMinCodexCliVersion() {
|
|
7003
|
-
codexCliVersionEnsured ??= this.runEnsureMinCodexCliVersion().catch((error) => {
|
|
7004
|
-
codexCliVersionEnsured = null;
|
|
7005
|
-
console.warn("[AppServerProcess] Failed to ensure minimum codex CLI version, continuing with installed binary:", error);
|
|
7006
|
-
});
|
|
7007
|
-
return codexCliVersionEnsured;
|
|
7008
|
-
}
|
|
7009
|
-
async runEnsureMinCodexCliVersion() {
|
|
7010
|
-
const { stdout } = await execFileAsync(this.binary, ["--version"], { env: this.env });
|
|
7011
|
-
const version = stdout.match(/(\d+\.\d+\.\d+)/)?.[1];
|
|
7012
|
-
if (version && !isVersionBelow(version, MIN_CODEX_CLI_VERSION)) {
|
|
7013
|
-
return;
|
|
7014
|
-
}
|
|
7015
|
-
console.warn(`[AppServerProcess] codex CLI ${version ?? "unknown"} is below ${MIN_CODEX_CLI_VERSION}; upgrading @openai/codex`);
|
|
7016
|
-
await execFileAsync(
|
|
7017
|
-
"npm",
|
|
7018
|
-
["install", "-g", "--no-audit", "--no-fund", `@openai/codex@${MIN_CODEX_CLI_VERSION}`],
|
|
7019
|
-
{ env: this.env, timeout: CODEX_UPGRADE_TIMEOUT_MS }
|
|
7020
|
-
);
|
|
7021
|
-
console.warn(`[AppServerProcess] upgraded codex CLI to ${MIN_CODEX_CLI_VERSION}`);
|
|
7022
|
-
}
|
|
7023
|
-
async loginWithConfiguredCredentials(client) {
|
|
7024
|
-
if (this.env.REPLICAS_CODEX_AUTH_METHOD === "oauth") {
|
|
7025
|
-
if (!this.chatgptAuthTokens) {
|
|
7026
|
-
throw new Error("Codex OAuth credentials were not prepared before app-server startup");
|
|
7027
|
-
}
|
|
7028
|
-
const params2 = {
|
|
7029
|
-
type: "chatgptAuthTokens",
|
|
7030
|
-
...this.chatgptAuthTokens
|
|
7031
|
-
};
|
|
7032
|
-
await client.request(ACCOUNT_LOGIN_START_METHOD, params2);
|
|
7033
|
-
return;
|
|
7034
|
-
}
|
|
7035
|
-
if (this.env.REPLICAS_CODEX_AUTH_METHOD !== "api_key" || !this.env.OPENAI_API_KEY) return;
|
|
7036
|
-
const params = {
|
|
7037
|
-
type: "apiKey",
|
|
7038
|
-
apiKey: this.env.OPENAI_API_KEY
|
|
7039
|
-
};
|
|
7040
|
-
await client.request(ACCOUNT_LOGIN_START_METHOD, params);
|
|
7041
|
-
}
|
|
7042
|
-
async killAfterFailedStart() {
|
|
7043
|
-
const child = this.child;
|
|
7044
|
-
this.child = null;
|
|
7045
|
-
this.client = null;
|
|
7046
|
-
if (!child || child.killed) {
|
|
7047
|
-
return;
|
|
7048
|
-
}
|
|
7049
|
-
this.shuttingDown = true;
|
|
7050
|
-
child.kill("SIGKILL");
|
|
7051
|
-
await new Promise((resolve) => {
|
|
7052
|
-
child.once("exit", () => resolve());
|
|
7053
|
-
});
|
|
7054
|
-
}
|
|
7055
|
-
};
|
|
7056
|
-
|
|
7057
|
-
// src/managers/codex-asp/notification-dispatch.ts
|
|
7058
|
-
var TURN_STARTED_METHOD = "turn/started";
|
|
7059
|
-
var TURN_COMPLETED_METHOD = "turn/completed";
|
|
7060
|
-
var TURN_PLAN_UPDATED_METHOD = "turn/plan/updated";
|
|
7061
|
-
var THREAD_GOAL_UPDATED_METHOD = "thread/goal/updated";
|
|
7062
|
-
var THREAD_GOAL_CLEARED_METHOD = "thread/goal/cleared";
|
|
7063
|
-
var ITEM_STARTED_METHOD = "item/started";
|
|
7064
|
-
var ITEM_COMPLETED_METHOD = "item/completed";
|
|
7065
|
-
var AGENT_MESSAGE_DELTA_METHOD = "item/agentMessage/delta";
|
|
7066
|
-
var REASONING_SUMMARY_TEXT_DELTA_METHOD = "item/reasoning/summaryTextDelta";
|
|
7067
|
-
var REASONING_TEXT_DELTA_METHOD = "item/reasoning/textDelta";
|
|
7068
|
-
var REASONING_SUMMARY_PART_ADDED_METHOD = "item/reasoning/summaryPartAdded";
|
|
7069
|
-
var COMMAND_EXECUTION_OUTPUT_DELTA_METHOD = "item/commandExecution/outputDelta";
|
|
7070
|
-
var FILE_CHANGE_OUTPUT_DELTA_METHOD = "item/fileChange/outputDelta";
|
|
7071
|
-
var ACCOUNT_RATE_LIMITS_UPDATED_METHOD = "account/rateLimits/updated";
|
|
7072
|
-
var THREAD_TOKEN_USAGE_UPDATED_METHOD = "thread/tokenUsage/updated";
|
|
7073
|
-
var THREAD_COMPACTED_METHOD = "thread/compacted";
|
|
7074
|
-
var MODEL_REROUTED_METHOD = "model/rerouted";
|
|
7075
|
-
function dispatchAspNotification(notification, handlers) {
|
|
7076
|
-
const handler = handlers[notification.method];
|
|
7077
|
-
if (!handler) return;
|
|
7078
|
-
handler(notification);
|
|
7079
|
-
}
|
|
7080
|
-
function recoverCompletedTurn(turn, completedItems, agentMessageDeltas) {
|
|
7081
|
-
const items = turn.items.length > 0 ? [...turn.items] : [];
|
|
7082
|
-
const itemIds = new Set(items.map((item) => item.id));
|
|
7083
|
-
for (const item of completedItems) {
|
|
7084
|
-
if (itemIds.has(item.id)) continue;
|
|
7085
|
-
items.push(item);
|
|
7086
|
-
itemIds.add(item.id);
|
|
7087
|
-
}
|
|
7088
|
-
for (const [itemId, text] of agentMessageDeltas) {
|
|
7089
|
-
if (itemIds.has(itemId)) continue;
|
|
7090
|
-
items.push({ type: "agentMessage", id: itemId, text, phase: null, memoryCitation: null });
|
|
7091
|
-
}
|
|
7092
|
-
return items.length > 0 ? { ...turn, items, itemsView: "full" } : turn;
|
|
7093
|
-
}
|
|
7094
|
-
|
|
7095
6615
|
export {
|
|
7096
6616
|
isRecord,
|
|
7097
6617
|
isNonEmptyString,
|
|
7098
6618
|
TIMEOUT,
|
|
7099
6619
|
raceWithTimeout,
|
|
6620
|
+
withTimeout,
|
|
7100
6621
|
createSuccessResult,
|
|
7101
6622
|
createErrorResult,
|
|
7102
6623
|
AGENT,
|
|
@@ -7207,6 +6728,7 @@ export {
|
|
|
7207
6728
|
isTransientErrorText,
|
|
7208
6729
|
isClaudeAuthErrorText,
|
|
7209
6730
|
isCodexAuthError,
|
|
6731
|
+
isVersionBelow,
|
|
7210
6732
|
hasChatStarted,
|
|
7211
6733
|
DESKTOP_STREAM_PORT,
|
|
7212
6734
|
MERGED_MESSAGE_SEPARATOR,
|
|
@@ -7242,6 +6764,7 @@ export {
|
|
|
7242
6764
|
extractCommandProtectionCommandText,
|
|
7243
6765
|
findPrMergeSignals,
|
|
7244
6766
|
findGitCommitSignals,
|
|
6767
|
+
mayCreatePullRequest,
|
|
7245
6768
|
coerceBackgroundTaskPayload,
|
|
7246
6769
|
isTerminalBackgroundTaskStatus,
|
|
7247
6770
|
areUserMessagesWithinMatchWindow,
|
|
@@ -7271,30 +6794,5 @@ export {
|
|
|
7271
6794
|
MEMORY_SUMMARY_FILENAME,
|
|
7272
6795
|
MEMORY_INDEX_FILENAME,
|
|
7273
6796
|
getMemoryOutputSafetyViolation,
|
|
7274
|
-
isSkillRegistryManifest
|
|
7275
|
-
putPresignedFile,
|
|
7276
|
-
buildCodexAgentEnv,
|
|
7277
|
-
execAsync,
|
|
7278
|
-
execFileAsync,
|
|
7279
|
-
SUBPROCESS_MAX_BUFFER,
|
|
7280
|
-
AppServerProcess,
|
|
7281
|
-
TURN_STARTED_METHOD,
|
|
7282
|
-
TURN_COMPLETED_METHOD,
|
|
7283
|
-
TURN_PLAN_UPDATED_METHOD,
|
|
7284
|
-
THREAD_GOAL_UPDATED_METHOD,
|
|
7285
|
-
THREAD_GOAL_CLEARED_METHOD,
|
|
7286
|
-
ITEM_STARTED_METHOD,
|
|
7287
|
-
ITEM_COMPLETED_METHOD,
|
|
7288
|
-
AGENT_MESSAGE_DELTA_METHOD,
|
|
7289
|
-
REASONING_SUMMARY_TEXT_DELTA_METHOD,
|
|
7290
|
-
REASONING_TEXT_DELTA_METHOD,
|
|
7291
|
-
REASONING_SUMMARY_PART_ADDED_METHOD,
|
|
7292
|
-
COMMAND_EXECUTION_OUTPUT_DELTA_METHOD,
|
|
7293
|
-
FILE_CHANGE_OUTPUT_DELTA_METHOD,
|
|
7294
|
-
ACCOUNT_RATE_LIMITS_UPDATED_METHOD,
|
|
7295
|
-
THREAD_TOKEN_USAGE_UPDATED_METHOD,
|
|
7296
|
-
THREAD_COMPACTED_METHOD,
|
|
7297
|
-
MODEL_REROUTED_METHOD,
|
|
7298
|
-
dispatchAspNotification,
|
|
7299
|
-
recoverCompletedTurn
|
|
6797
|
+
isSkillRegistryManifest
|
|
7300
6798
|
};
|