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.
Files changed (2) hide show
  1. package/dist/src/index.js +581 -5
  2. 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 = "25-05-2026-royal-york-v3";
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
- provider = new CodexManager({
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 = spawn("bash", ["-lc", params.content], {
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.212",
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",