replicas-engine 0.1.212 → 0.1.213
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/index.js +581 -5
- package/package.json +2 -1
package/dist/src/index.js
CHANGED
|
@@ -1493,7 +1493,7 @@ function parseReplicasConfigString(content, filename) {
|
|
|
1493
1493
|
}
|
|
1494
1494
|
|
|
1495
1495
|
// ../shared/src/engine/environment.ts
|
|
1496
|
-
var DAYTONA_SNAPSHOT_ID = "
|
|
1496
|
+
var DAYTONA_SNAPSHOT_ID = "26-05-2026-royal-york-v1";
|
|
1497
1497
|
|
|
1498
1498
|
// ../shared/src/engine/types.ts
|
|
1499
1499
|
var DEFAULT_CHAT_TITLES = {
|
|
@@ -1677,7 +1677,8 @@ function loadEngineEnv() {
|
|
|
1677
1677
|
AWS_REGION: readEnv("AWS_REGION"),
|
|
1678
1678
|
REPLICAS_CLAUDE_AUTH_METHOD: parseClaudeAuthMethod(readEnv("REPLICAS_CLAUDE_AUTH_METHOD")),
|
|
1679
1679
|
REPLICAS_CODEX_AUTH_METHOD: parseCodexAuthMethod(readEnv("REPLICAS_CODEX_AUTH_METHOD")),
|
|
1680
|
-
REPLICAS_ENV_SYSTEM_PROMPT: readEnv("REPLICAS_ENV_SYSTEM_PROMPT")
|
|
1680
|
+
REPLICAS_ENV_SYSTEM_PROMPT: readEnv("REPLICAS_ENV_SYSTEM_PROMPT"),
|
|
1681
|
+
CODEX_ASP_ENABLED: readEnv("CODEX_ASP_ENABLED")?.toLowerCase() === "true"
|
|
1681
1682
|
};
|
|
1682
1683
|
if (!IS_WARMING_MODE && !env.WORKSPACE_ID) {
|
|
1683
1684
|
console.error("WORKSPACE_ID is not set \u2014 this is required in normal (non-warming) mode");
|
|
@@ -5384,6 +5385,580 @@ var CodexManager = class _CodexManager extends CodingAgentManager {
|
|
|
5384
5385
|
}
|
|
5385
5386
|
};
|
|
5386
5387
|
|
|
5388
|
+
// src/managers/codex-asp/app-server-process.ts
|
|
5389
|
+
import { spawn } from "child_process";
|
|
5390
|
+
import { EventEmitter as EventEmitter2 } from "events";
|
|
5391
|
+
|
|
5392
|
+
// src/managers/codex-asp/asp-client.ts
|
|
5393
|
+
import { EventEmitter } from "events";
|
|
5394
|
+
var DEFAULT_REQUEST_TIMEOUT_MS = 12e4;
|
|
5395
|
+
function hasOwn(record, key) {
|
|
5396
|
+
return Object.prototype.hasOwnProperty.call(record, key);
|
|
5397
|
+
}
|
|
5398
|
+
var AspClient = class {
|
|
5399
|
+
stdin;
|
|
5400
|
+
stdout;
|
|
5401
|
+
emitter = new EventEmitter();
|
|
5402
|
+
pending = /* @__PURE__ */ new Map();
|
|
5403
|
+
nextId = 1;
|
|
5404
|
+
lineBuffer = "";
|
|
5405
|
+
disposed = false;
|
|
5406
|
+
get isDisposed() {
|
|
5407
|
+
return this.disposed;
|
|
5408
|
+
}
|
|
5409
|
+
constructor(options) {
|
|
5410
|
+
this.stdin = options.stdin;
|
|
5411
|
+
this.stdout = options.stdout;
|
|
5412
|
+
this.stdout.setEncoding("utf8");
|
|
5413
|
+
this.stdout.on("data", this.handleStdoutData);
|
|
5414
|
+
this.stdin.on("error", this.handleStdinError);
|
|
5415
|
+
}
|
|
5416
|
+
on(event, listener) {
|
|
5417
|
+
this.emitter.on(event, listener);
|
|
5418
|
+
}
|
|
5419
|
+
off(event, listener) {
|
|
5420
|
+
this.emitter.off(event, listener);
|
|
5421
|
+
}
|
|
5422
|
+
async request(method, params, opts) {
|
|
5423
|
+
if (this.disposed) {
|
|
5424
|
+
throw new Error(`Cannot send ${method}: ASP client disposed`);
|
|
5425
|
+
}
|
|
5426
|
+
const id = this.nextId;
|
|
5427
|
+
this.nextId += 1;
|
|
5428
|
+
const promise = new Promise((resolve3, reject) => {
|
|
5429
|
+
const timeoutMs = opts?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
5430
|
+
const timer = timeoutMs > 0 ? setTimeout(() => {
|
|
5431
|
+
this.pending.delete(id);
|
|
5432
|
+
reject(new Error(`ASP request timed out for ${method}`));
|
|
5433
|
+
}, timeoutMs) : null;
|
|
5434
|
+
this.pending.set(id, { resolve: resolve3, reject, method, timer });
|
|
5435
|
+
});
|
|
5436
|
+
this.write({ method, id, params });
|
|
5437
|
+
return promise;
|
|
5438
|
+
}
|
|
5439
|
+
notify(method, params) {
|
|
5440
|
+
if (this.disposed) {
|
|
5441
|
+
return;
|
|
5442
|
+
}
|
|
5443
|
+
try {
|
|
5444
|
+
this.write(params === void 0 ? { method } : { method, params });
|
|
5445
|
+
} catch (error) {
|
|
5446
|
+
console.warn(`[AspClient] Failed to send notification ${method}:`, error);
|
|
5447
|
+
}
|
|
5448
|
+
}
|
|
5449
|
+
respond(id, result) {
|
|
5450
|
+
if (this.disposed) {
|
|
5451
|
+
return;
|
|
5452
|
+
}
|
|
5453
|
+
try {
|
|
5454
|
+
this.write({ id, result });
|
|
5455
|
+
} catch (error) {
|
|
5456
|
+
console.warn(`[AspClient] Failed to send response ${String(id)}:`, error);
|
|
5457
|
+
}
|
|
5458
|
+
}
|
|
5459
|
+
dispose(reason = new Error("ASP client disposed")) {
|
|
5460
|
+
if (this.disposed) {
|
|
5461
|
+
return;
|
|
5462
|
+
}
|
|
5463
|
+
this.disposed = true;
|
|
5464
|
+
this.stdout.off("data", this.handleStdoutData);
|
|
5465
|
+
this.stdin.removeListener("error", this.handleStdinError);
|
|
5466
|
+
for (const [id, pending] of this.pending) {
|
|
5467
|
+
if (pending.timer) {
|
|
5468
|
+
clearTimeout(pending.timer);
|
|
5469
|
+
}
|
|
5470
|
+
pending.reject(new Error(`${reason.message} while waiting for ${pending.method}`));
|
|
5471
|
+
this.pending.delete(id);
|
|
5472
|
+
}
|
|
5473
|
+
this.lineBuffer = "";
|
|
5474
|
+
this.emitter.emit("dispose", reason);
|
|
5475
|
+
this.emitter.removeAllListeners();
|
|
5476
|
+
}
|
|
5477
|
+
handleStdoutData = (chunk) => {
|
|
5478
|
+
this.lineBuffer += chunk.toString();
|
|
5479
|
+
let newlineIndex = this.lineBuffer.indexOf("\n");
|
|
5480
|
+
while (newlineIndex >= 0) {
|
|
5481
|
+
const line = this.lineBuffer.slice(0, newlineIndex).trim();
|
|
5482
|
+
this.lineBuffer = this.lineBuffer.slice(newlineIndex + 1);
|
|
5483
|
+
if (line.length > 0) {
|
|
5484
|
+
this.handleLine(line);
|
|
5485
|
+
}
|
|
5486
|
+
newlineIndex = this.lineBuffer.indexOf("\n");
|
|
5487
|
+
}
|
|
5488
|
+
};
|
|
5489
|
+
handleStdinError = (error) => {
|
|
5490
|
+
this.dispose(new Error(`ASP stdin error: ${error.message}`));
|
|
5491
|
+
};
|
|
5492
|
+
handleLine(line) {
|
|
5493
|
+
let parsed;
|
|
5494
|
+
try {
|
|
5495
|
+
parsed = JSON.parse(line);
|
|
5496
|
+
} catch (error) {
|
|
5497
|
+
console.warn("[AspClient] Failed to parse ASP JSON line:", error);
|
|
5498
|
+
return;
|
|
5499
|
+
}
|
|
5500
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
5501
|
+
console.warn("[AspClient] Ignoring non-object ASP message");
|
|
5502
|
+
return;
|
|
5503
|
+
}
|
|
5504
|
+
const message = parsed;
|
|
5505
|
+
const hasRequestId = typeof message.id === "number" || typeof message.id === "string";
|
|
5506
|
+
if (hasRequestId && (hasOwn(message, "result") || hasOwn(message, "error"))) {
|
|
5507
|
+
this.handleResponse(message);
|
|
5508
|
+
return;
|
|
5509
|
+
}
|
|
5510
|
+
if (hasRequestId && typeof message.method === "string") {
|
|
5511
|
+
this.emitter.emit("serverRequest", message);
|
|
5512
|
+
return;
|
|
5513
|
+
}
|
|
5514
|
+
if (!hasOwn(message, "id") && typeof message.method === "string") {
|
|
5515
|
+
this.emitter.emit("notification", message);
|
|
5516
|
+
}
|
|
5517
|
+
}
|
|
5518
|
+
handleResponse(message) {
|
|
5519
|
+
if (typeof message.id !== "number") {
|
|
5520
|
+
console.warn("[AspClient] Ignoring response with non-numeric request id");
|
|
5521
|
+
return;
|
|
5522
|
+
}
|
|
5523
|
+
const pending = this.pending.get(message.id);
|
|
5524
|
+
if (!pending) {
|
|
5525
|
+
console.warn(`[AspClient] Ignoring response for unknown request id ${message.id}`);
|
|
5526
|
+
return;
|
|
5527
|
+
}
|
|
5528
|
+
this.pending.delete(message.id);
|
|
5529
|
+
if (pending.timer) {
|
|
5530
|
+
clearTimeout(pending.timer);
|
|
5531
|
+
}
|
|
5532
|
+
if (hasOwn(message, "error")) {
|
|
5533
|
+
pending.reject(this.createRpcError(pending.method, message.error));
|
|
5534
|
+
return;
|
|
5535
|
+
}
|
|
5536
|
+
pending.resolve(message.result);
|
|
5537
|
+
}
|
|
5538
|
+
createRpcError(method, error) {
|
|
5539
|
+
if (typeof error !== "object" || error === null || Array.isArray(error)) {
|
|
5540
|
+
return new Error(`ASP request failed for ${method}`);
|
|
5541
|
+
}
|
|
5542
|
+
const rpcError = error;
|
|
5543
|
+
const code = typeof rpcError.code === "number" ? ` ${rpcError.code}` : "";
|
|
5544
|
+
const message = typeof rpcError.message === "string" ? rpcError.message : "Unknown ASP error";
|
|
5545
|
+
const data = hasOwn(rpcError, "data") ? ` data=${JSON.stringify(rpcError.data)}` : "";
|
|
5546
|
+
return new Error(`ASP request failed for ${method}:${code} ${message}${data}`);
|
|
5547
|
+
}
|
|
5548
|
+
write(message) {
|
|
5549
|
+
try {
|
|
5550
|
+
this.stdin.write(`${JSON.stringify(message)}
|
|
5551
|
+
`, (error) => {
|
|
5552
|
+
if (error) {
|
|
5553
|
+
this.dispose(new Error(`ASP write failed: ${error.message}`));
|
|
5554
|
+
}
|
|
5555
|
+
});
|
|
5556
|
+
} catch (error) {
|
|
5557
|
+
const writeError = error instanceof Error ? error : new Error("ASP write failed");
|
|
5558
|
+
this.dispose(writeError);
|
|
5559
|
+
throw writeError;
|
|
5560
|
+
}
|
|
5561
|
+
}
|
|
5562
|
+
};
|
|
5563
|
+
|
|
5564
|
+
// src/managers/codex-asp/app-server-process.ts
|
|
5565
|
+
var DEFAULT_CODEX_BINARY = "codex";
|
|
5566
|
+
var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
|
|
5567
|
+
var ENGINE_PACKAGE_VERSION = "0.1.213";
|
|
5568
|
+
var INITIALIZE_METHOD = "initialize";
|
|
5569
|
+
var INITIALIZED_NOTIFICATION = "initialized";
|
|
5570
|
+
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|
|
5571
|
+
var AppServerProcess = class {
|
|
5572
|
+
binary;
|
|
5573
|
+
args;
|
|
5574
|
+
env;
|
|
5575
|
+
cwd;
|
|
5576
|
+
emitter = new EventEmitter2();
|
|
5577
|
+
child = null;
|
|
5578
|
+
client = null;
|
|
5579
|
+
shuttingDown = false;
|
|
5580
|
+
constructor(options = {}) {
|
|
5581
|
+
this.binary = options.binary ?? DEFAULT_CODEX_BINARY;
|
|
5582
|
+
this.args = options.args ?? DEFAULT_CODEX_ARGS;
|
|
5583
|
+
this.env = options.env ?? buildCodexAgentEnv();
|
|
5584
|
+
this.cwd = options.cwd ?? ENGINE_ENV.WORKSPACE_ROOT;
|
|
5585
|
+
}
|
|
5586
|
+
on(event, listener) {
|
|
5587
|
+
this.emitter.on(event, listener);
|
|
5588
|
+
}
|
|
5589
|
+
async start() {
|
|
5590
|
+
if (this.child && this.client) {
|
|
5591
|
+
return { client: this.client };
|
|
5592
|
+
}
|
|
5593
|
+
this.shuttingDown = false;
|
|
5594
|
+
const child = spawn(this.binary, this.args, {
|
|
5595
|
+
cwd: this.cwd,
|
|
5596
|
+
env: this.env,
|
|
5597
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
5598
|
+
});
|
|
5599
|
+
this.child = child;
|
|
5600
|
+
child.stderr.setEncoding("utf8");
|
|
5601
|
+
child.stderr.on("data", (chunk) => {
|
|
5602
|
+
for (const line of chunk.toString().split("\n")) {
|
|
5603
|
+
if (line.trim().length > 0) {
|
|
5604
|
+
console.error(`[codex-app-server] ${line}`);
|
|
5605
|
+
}
|
|
5606
|
+
}
|
|
5607
|
+
});
|
|
5608
|
+
child.on("exit", (code, signal) => {
|
|
5609
|
+
this.client?.dispose();
|
|
5610
|
+
this.client = null;
|
|
5611
|
+
this.child = null;
|
|
5612
|
+
if (!this.shuttingDown) {
|
|
5613
|
+
console.warn(`[AppServerProcess] codex app-server exited unexpectedly code=${code ?? "null"} signal=${signal ?? "null"}`);
|
|
5614
|
+
this.emitter.emit("exit", code, signal);
|
|
5615
|
+
}
|
|
5616
|
+
});
|
|
5617
|
+
const client = new AspClient({ stdin: child.stdin, stdout: child.stdout });
|
|
5618
|
+
this.client = client;
|
|
5619
|
+
let cleanupEarlyFailureHandlers = () => {
|
|
5620
|
+
};
|
|
5621
|
+
const earlyFailure = new Promise((_resolve, reject) => {
|
|
5622
|
+
const onError = (error) => {
|
|
5623
|
+
reject(error);
|
|
5624
|
+
};
|
|
5625
|
+
const onExit = (code, signal) => {
|
|
5626
|
+
reject(new Error(`codex app-server exited before initialize completed code=${code ?? "null"} signal=${signal ?? "null"}`));
|
|
5627
|
+
};
|
|
5628
|
+
child.once("error", onError);
|
|
5629
|
+
child.once("exit", onExit);
|
|
5630
|
+
cleanupEarlyFailureHandlers = () => {
|
|
5631
|
+
child.off("error", onError);
|
|
5632
|
+
child.off("exit", onExit);
|
|
5633
|
+
};
|
|
5634
|
+
});
|
|
5635
|
+
try {
|
|
5636
|
+
const initializeParams = {
|
|
5637
|
+
clientInfo: {
|
|
5638
|
+
name: "replicas_engine",
|
|
5639
|
+
title: "Replicas Engine",
|
|
5640
|
+
version: ENGINE_PACKAGE_VERSION
|
|
5641
|
+
},
|
|
5642
|
+
capabilities: {
|
|
5643
|
+
experimentalApi: true,
|
|
5644
|
+
requestAttestation: false,
|
|
5645
|
+
optOutNotificationMethods: null
|
|
5646
|
+
}
|
|
5647
|
+
};
|
|
5648
|
+
await Promise.race([
|
|
5649
|
+
client.request(INITIALIZE_METHOD, initializeParams),
|
|
5650
|
+
earlyFailure
|
|
5651
|
+
]);
|
|
5652
|
+
cleanupEarlyFailureHandlers();
|
|
5653
|
+
client.notify(INITIALIZED_NOTIFICATION);
|
|
5654
|
+
await this.loginWithConfiguredApiKey(client);
|
|
5655
|
+
return { client };
|
|
5656
|
+
} catch (error) {
|
|
5657
|
+
cleanupEarlyFailureHandlers();
|
|
5658
|
+
client.dispose();
|
|
5659
|
+
await this.killAfterFailedStart();
|
|
5660
|
+
throw error;
|
|
5661
|
+
}
|
|
5662
|
+
}
|
|
5663
|
+
async loginWithConfiguredApiKey(client) {
|
|
5664
|
+
if (ENGINE_ENV.REPLICAS_CODEX_AUTH_METHOD !== "api_key" || !ENGINE_ENV.OPENAI_API_KEY) {
|
|
5665
|
+
return;
|
|
5666
|
+
}
|
|
5667
|
+
const params = {
|
|
5668
|
+
type: "apiKey",
|
|
5669
|
+
apiKey: ENGINE_ENV.OPENAI_API_KEY
|
|
5670
|
+
};
|
|
5671
|
+
await client.request(ACCOUNT_LOGIN_START_METHOD, params);
|
|
5672
|
+
}
|
|
5673
|
+
async killAfterFailedStart() {
|
|
5674
|
+
const child = this.child;
|
|
5675
|
+
this.child = null;
|
|
5676
|
+
this.client = null;
|
|
5677
|
+
if (!child || child.killed) {
|
|
5678
|
+
return;
|
|
5679
|
+
}
|
|
5680
|
+
this.shuttingDown = true;
|
|
5681
|
+
child.kill("SIGKILL");
|
|
5682
|
+
await new Promise((resolve3) => {
|
|
5683
|
+
child.once("exit", () => resolve3());
|
|
5684
|
+
});
|
|
5685
|
+
}
|
|
5686
|
+
};
|
|
5687
|
+
|
|
5688
|
+
// src/managers/codex-asp/asp-host.ts
|
|
5689
|
+
var hostPromise = null;
|
|
5690
|
+
async function getCodexAspHost() {
|
|
5691
|
+
hostPromise ??= (async () => {
|
|
5692
|
+
try {
|
|
5693
|
+
const process2 = new AppServerProcess();
|
|
5694
|
+
const { client } = await process2.start();
|
|
5695
|
+
process2.on("exit", () => {
|
|
5696
|
+
hostPromise = null;
|
|
5697
|
+
});
|
|
5698
|
+
return { client };
|
|
5699
|
+
} catch (error) {
|
|
5700
|
+
hostPromise = null;
|
|
5701
|
+
throw error;
|
|
5702
|
+
}
|
|
5703
|
+
})();
|
|
5704
|
+
return hostPromise;
|
|
5705
|
+
}
|
|
5706
|
+
|
|
5707
|
+
// src/managers/codex-asp/codex-asp-manager.ts
|
|
5708
|
+
var DEFAULT_MODEL2 = "gpt-5.5";
|
|
5709
|
+
var THREAD_START_METHOD = "thread/start";
|
|
5710
|
+
var TURN_START_METHOD = "turn/start";
|
|
5711
|
+
var TURN_INTERRUPT_METHOD = "turn/interrupt";
|
|
5712
|
+
var TURN_COMPLETED_METHOD = "turn/completed";
|
|
5713
|
+
var ITEM_COMPLETED_METHOD = "item/completed";
|
|
5714
|
+
var AGENT_MESSAGE_DELTA_METHOD = "item/agentMessage/delta";
|
|
5715
|
+
var COMMAND_APPROVAL_METHOD = "item/commandExecution/requestApproval";
|
|
5716
|
+
var FILE_CHANGE_APPROVAL_METHOD = "item/fileChange/requestApproval";
|
|
5717
|
+
var CodexAspManager = class extends CodingAgentManager {
|
|
5718
|
+
currentThreadId = null;
|
|
5719
|
+
activeTurnId = null;
|
|
5720
|
+
historyEvents = [];
|
|
5721
|
+
constructor(options) {
|
|
5722
|
+
super(options);
|
|
5723
|
+
this.initializeManager(this.processMessageInternal.bind(this));
|
|
5724
|
+
}
|
|
5725
|
+
async initialize() {
|
|
5726
|
+
if (this.initialSessionId) {
|
|
5727
|
+
this.currentThreadId = this.initialSessionId;
|
|
5728
|
+
}
|
|
5729
|
+
}
|
|
5730
|
+
async interruptActiveTurn() {
|
|
5731
|
+
if (!this.currentThreadId || !this.activeTurnId) {
|
|
5732
|
+
return;
|
|
5733
|
+
}
|
|
5734
|
+
try {
|
|
5735
|
+
const host = await getCodexAspHost();
|
|
5736
|
+
const params = {
|
|
5737
|
+
threadId: this.currentThreadId,
|
|
5738
|
+
turnId: this.activeTurnId
|
|
5739
|
+
};
|
|
5740
|
+
await host.client.request(TURN_INTERRUPT_METHOD, params);
|
|
5741
|
+
} catch (error) {
|
|
5742
|
+
console.warn("[CodexAspManager] Failed to interrupt active turn:", error);
|
|
5743
|
+
}
|
|
5744
|
+
}
|
|
5745
|
+
async clearSessionState() {
|
|
5746
|
+
this.currentThreadId = null;
|
|
5747
|
+
this.activeTurnId = null;
|
|
5748
|
+
await this.onSaveSessionId(null);
|
|
5749
|
+
}
|
|
5750
|
+
async getHistory() {
|
|
5751
|
+
return {
|
|
5752
|
+
thread_id: this.currentThreadId,
|
|
5753
|
+
events: [...this.historyEvents]
|
|
5754
|
+
};
|
|
5755
|
+
}
|
|
5756
|
+
async processMessageInternal(request) {
|
|
5757
|
+
let host = null;
|
|
5758
|
+
try {
|
|
5759
|
+
host = await getCodexAspHost();
|
|
5760
|
+
const developerInstructions = this.buildCombinedInstructions(request.customInstructions);
|
|
5761
|
+
this.recordHistoryEvent("event_msg", {
|
|
5762
|
+
type: "user_message",
|
|
5763
|
+
message: request.message
|
|
5764
|
+
});
|
|
5765
|
+
if (!this.currentThreadId) {
|
|
5766
|
+
const threadStartResponse = await host.client.request(
|
|
5767
|
+
THREAD_START_METHOD,
|
|
5768
|
+
await this.buildThreadStartParams(request, developerInstructions)
|
|
5769
|
+
);
|
|
5770
|
+
this.currentThreadId = threadStartResponse.thread.id;
|
|
5771
|
+
await this.onSaveSessionId(this.currentThreadId);
|
|
5772
|
+
}
|
|
5773
|
+
const threadId = this.currentThreadId;
|
|
5774
|
+
const completedTurn = await this.runTurn(host, threadId, request, developerInstructions);
|
|
5775
|
+
if (completedTurn.status === "failed") {
|
|
5776
|
+
const turnError = completedTurn.error;
|
|
5777
|
+
if (!turnError) {
|
|
5778
|
+
throw new Error("Codex ASP turn failed without error details");
|
|
5779
|
+
}
|
|
5780
|
+
const parts = [`Codex ASP turn failed: ${turnError.message}`];
|
|
5781
|
+
if (turnError.codexErrorInfo !== null) {
|
|
5782
|
+
parts.push(`codexErrorInfo=${JSON.stringify(turnError.codexErrorInfo)}`);
|
|
5783
|
+
}
|
|
5784
|
+
if (turnError.additionalDetails) {
|
|
5785
|
+
parts.push(`details=${turnError.additionalDetails}`);
|
|
5786
|
+
}
|
|
5787
|
+
throw new Error(parts.join(" "));
|
|
5788
|
+
}
|
|
5789
|
+
if (completedTurn.status === "completed") {
|
|
5790
|
+
this.emitFinalAgentMessage(completedTurn);
|
|
5791
|
+
}
|
|
5792
|
+
} finally {
|
|
5793
|
+
this.activeTurnId = null;
|
|
5794
|
+
if (host?.client.isDisposed) {
|
|
5795
|
+
this.currentThreadId = null;
|
|
5796
|
+
void this.onSaveSessionId(null).catch(() => {
|
|
5797
|
+
});
|
|
5798
|
+
}
|
|
5799
|
+
await this.onTurnComplete();
|
|
5800
|
+
}
|
|
5801
|
+
}
|
|
5802
|
+
async buildThreadStartParams(request, developerInstructions) {
|
|
5803
|
+
const additionalDirectories = await getAgentAdditionalDirectories();
|
|
5804
|
+
return {
|
|
5805
|
+
model: request.model ?? DEFAULT_MODEL2,
|
|
5806
|
+
cwd: this.workingDirectory,
|
|
5807
|
+
runtimeWorkspaceRoots: additionalDirectories,
|
|
5808
|
+
sandbox: "danger-full-access",
|
|
5809
|
+
developerInstructions: developerInstructions ?? null,
|
|
5810
|
+
config: { web_search: "live" },
|
|
5811
|
+
experimentalRawEvents: false,
|
|
5812
|
+
persistExtendedHistory: false
|
|
5813
|
+
};
|
|
5814
|
+
}
|
|
5815
|
+
buildTurnStartParams(threadId, request, developerInstructions) {
|
|
5816
|
+
const effort = request.thinkingLevel === "max" ? "xhigh" : request.thinkingLevel;
|
|
5817
|
+
const model = request.model ?? DEFAULT_MODEL2;
|
|
5818
|
+
return {
|
|
5819
|
+
threadId,
|
|
5820
|
+
input: [{
|
|
5821
|
+
type: "text",
|
|
5822
|
+
text: request.message,
|
|
5823
|
+
text_elements: []
|
|
5824
|
+
}],
|
|
5825
|
+
model,
|
|
5826
|
+
...effort ? { effort } : {},
|
|
5827
|
+
...developerInstructions ? {
|
|
5828
|
+
collaborationMode: {
|
|
5829
|
+
mode: "default",
|
|
5830
|
+
settings: {
|
|
5831
|
+
model,
|
|
5832
|
+
reasoning_effort: effort ?? null,
|
|
5833
|
+
developer_instructions: developerInstructions
|
|
5834
|
+
}
|
|
5835
|
+
}
|
|
5836
|
+
} : {}
|
|
5837
|
+
};
|
|
5838
|
+
}
|
|
5839
|
+
async runTurn(host, threadId, request, developerInstructions) {
|
|
5840
|
+
let resolveCompleted;
|
|
5841
|
+
const completed = new Promise((resolve3) => {
|
|
5842
|
+
resolveCompleted = resolve3;
|
|
5843
|
+
});
|
|
5844
|
+
let rejectDisposed = () => {
|
|
5845
|
+
};
|
|
5846
|
+
const disposed = new Promise((_resolve, reject) => {
|
|
5847
|
+
rejectDisposed = reject;
|
|
5848
|
+
});
|
|
5849
|
+
void disposed.catch(() => {
|
|
5850
|
+
});
|
|
5851
|
+
let observedTurnId = null;
|
|
5852
|
+
const completedItems = [];
|
|
5853
|
+
const agentMessageDeltas = /* @__PURE__ */ new Map();
|
|
5854
|
+
const onNotification = (notification) => {
|
|
5855
|
+
if (notification.method === ITEM_COMPLETED_METHOD) {
|
|
5856
|
+
if (notification.params.threadId === threadId && (!observedTurnId || notification.params.turnId === observedTurnId)) {
|
|
5857
|
+
completedItems.push(notification.params.item);
|
|
5858
|
+
}
|
|
5859
|
+
return;
|
|
5860
|
+
}
|
|
5861
|
+
if (notification.method === AGENT_MESSAGE_DELTA_METHOD) {
|
|
5862
|
+
if (notification.params.threadId === threadId && (!observedTurnId || notification.params.turnId === observedTurnId)) {
|
|
5863
|
+
const currentText = agentMessageDeltas.get(notification.params.itemId) ?? "";
|
|
5864
|
+
agentMessageDeltas.set(notification.params.itemId, currentText + notification.params.delta);
|
|
5865
|
+
}
|
|
5866
|
+
return;
|
|
5867
|
+
}
|
|
5868
|
+
if (notification.method === TURN_COMPLETED_METHOD) {
|
|
5869
|
+
if (notification.params.threadId !== threadId) {
|
|
5870
|
+
return;
|
|
5871
|
+
}
|
|
5872
|
+
observedTurnId = notification.params.turn.id;
|
|
5873
|
+
const turn = notification.params.turn;
|
|
5874
|
+
const items = turn.items.length > 0 ? [...turn.items] : [];
|
|
5875
|
+
const itemIds = new Set(items.map((item) => item.id));
|
|
5876
|
+
for (const item of completedItems) {
|
|
5877
|
+
if (!itemIds.has(item.id)) {
|
|
5878
|
+
items.push(item);
|
|
5879
|
+
itemIds.add(item.id);
|
|
5880
|
+
}
|
|
5881
|
+
}
|
|
5882
|
+
for (const [itemId, text] of agentMessageDeltas) {
|
|
5883
|
+
if (!itemIds.has(itemId)) {
|
|
5884
|
+
items.push({
|
|
5885
|
+
type: "agentMessage",
|
|
5886
|
+
id: itemId,
|
|
5887
|
+
text,
|
|
5888
|
+
phase: null,
|
|
5889
|
+
memoryCitation: null
|
|
5890
|
+
});
|
|
5891
|
+
}
|
|
5892
|
+
}
|
|
5893
|
+
resolveCompleted(items.length > 0 ? { ...turn, items, itemsView: "full" } : turn);
|
|
5894
|
+
}
|
|
5895
|
+
};
|
|
5896
|
+
const onServerRequest = (serverRequest) => {
|
|
5897
|
+
if (serverRequest.method !== COMMAND_APPROVAL_METHOD && serverRequest.method !== FILE_CHANGE_APPROVAL_METHOD) {
|
|
5898
|
+
return;
|
|
5899
|
+
}
|
|
5900
|
+
console.warn("[CodexAspManager] approval requested while sandbox is danger-full-access");
|
|
5901
|
+
host.client.respond(serverRequest.id, { decision: "accept" });
|
|
5902
|
+
};
|
|
5903
|
+
const onDispose = (reason) => {
|
|
5904
|
+
this.currentThreadId = null;
|
|
5905
|
+
this.activeTurnId = null;
|
|
5906
|
+
void this.onSaveSessionId(null).catch(() => {
|
|
5907
|
+
});
|
|
5908
|
+
const turnLabel = observedTurnId ? ` ${observedTurnId}` : "";
|
|
5909
|
+
rejectDisposed(new Error(`Codex ASP client disposed before turn${turnLabel} completed: ${reason.message}`));
|
|
5910
|
+
};
|
|
5911
|
+
host.client.on("notification", onNotification);
|
|
5912
|
+
host.client.on("serverRequest", onServerRequest);
|
|
5913
|
+
host.client.on("dispose", onDispose);
|
|
5914
|
+
try {
|
|
5915
|
+
const turnStartResponse = await host.client.request(
|
|
5916
|
+
TURN_START_METHOD,
|
|
5917
|
+
this.buildTurnStartParams(threadId, request, developerInstructions)
|
|
5918
|
+
);
|
|
5919
|
+
observedTurnId = turnStartResponse.turn.id;
|
|
5920
|
+
this.activeTurnId = turnStartResponse.turn.id;
|
|
5921
|
+
return await Promise.race([completed, disposed]);
|
|
5922
|
+
} finally {
|
|
5923
|
+
host.client.off("notification", onNotification);
|
|
5924
|
+
host.client.off("serverRequest", onServerRequest);
|
|
5925
|
+
host.client.off("dispose", onDispose);
|
|
5926
|
+
}
|
|
5927
|
+
}
|
|
5928
|
+
emitFinalAgentMessage(turn) {
|
|
5929
|
+
let text = null;
|
|
5930
|
+
for (let index = turn.items.length - 1; index >= 0; index -= 1) {
|
|
5931
|
+
const item = turn.items[index];
|
|
5932
|
+
if (item?.type === "agentMessage") {
|
|
5933
|
+
text = item.text;
|
|
5934
|
+
break;
|
|
5935
|
+
}
|
|
5936
|
+
}
|
|
5937
|
+
if (!text) {
|
|
5938
|
+
return;
|
|
5939
|
+
}
|
|
5940
|
+
this.captureCompactionText(text);
|
|
5941
|
+
const event = this.recordHistoryEvent("response_item", {
|
|
5942
|
+
type: "message",
|
|
5943
|
+
role: "assistant",
|
|
5944
|
+
content: [{
|
|
5945
|
+
type: "output_text",
|
|
5946
|
+
text
|
|
5947
|
+
}]
|
|
5948
|
+
});
|
|
5949
|
+
this.onEvent(event);
|
|
5950
|
+
}
|
|
5951
|
+
recordHistoryEvent(type, payload) {
|
|
5952
|
+
const event = {
|
|
5953
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5954
|
+
type,
|
|
5955
|
+
payload
|
|
5956
|
+
};
|
|
5957
|
+
this.historyEvents.push(event);
|
|
5958
|
+
return event;
|
|
5959
|
+
}
|
|
5960
|
+
};
|
|
5961
|
+
|
|
5387
5962
|
// src/managers/relay-tools.ts
|
|
5388
5963
|
import { createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
|
|
5389
5964
|
import { z } from "zod";
|
|
@@ -6299,7 +6874,8 @@ var ChatService = class {
|
|
|
6299
6874
|
codexAvailable: isCodexAvailable()
|
|
6300
6875
|
});
|
|
6301
6876
|
} else {
|
|
6302
|
-
|
|
6877
|
+
const CodexProviderCtor = ENGINE_ENV.CODEX_ASP_ENABLED ? CodexAspManager : CodexManager;
|
|
6878
|
+
provider = new CodexProviderCtor({
|
|
6303
6879
|
workingDirectory: this.workingDirectory,
|
|
6304
6880
|
initialSessionId: persisted.providerSessionId,
|
|
6305
6881
|
onSaveSessionId: saveSession,
|
|
@@ -6805,7 +7381,7 @@ var PlanService = class {
|
|
|
6805
7381
|
var planService = new PlanService();
|
|
6806
7382
|
|
|
6807
7383
|
// src/services/warm-hooks-service.ts
|
|
6808
|
-
import { spawn } from "child_process";
|
|
7384
|
+
import { spawn as spawn2 } from "child_process";
|
|
6809
7385
|
import { readFile as readFile12 } from "fs/promises";
|
|
6810
7386
|
import { existsSync as existsSync8 } from "fs";
|
|
6811
7387
|
import { join as join18 } from "path";
|
|
@@ -6973,7 +7549,7 @@ async function executeHookScriptStreaming(params) {
|
|
|
6973
7549
|
params.onChunk(`$ ${params.label}
|
|
6974
7550
|
`);
|
|
6975
7551
|
return new Promise((resolve3) => {
|
|
6976
|
-
const proc =
|
|
7552
|
+
const proc = spawn2("bash", ["-lc", params.content], {
|
|
6977
7553
|
cwd: params.cwd,
|
|
6978
7554
|
env: process.env,
|
|
6979
7555
|
stdio: ["pipe", "pipe", "pipe"]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "replicas-engine",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.213",
|
|
4
4
|
"description": "Lightweight API server for Replicas workspaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"zod": "^4.0.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
+
"@replicas/codex-asp-types": "file:../codex-asp-types",
|
|
41
42
|
"@replicas/shared": "workspace:*",
|
|
42
43
|
"@types/node": "^20.11.17",
|
|
43
44
|
"tsup": "^8.5.0",
|