replicas-engine 0.1.212 → 0.1.214
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 +615 -111
- 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-v2";
|
|
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");
|
|
@@ -4023,20 +4024,6 @@ var MessageQueueService = class {
|
|
|
4023
4024
|
};
|
|
4024
4025
|
|
|
4025
4026
|
// src/managers/coding-agent-manager.ts
|
|
4026
|
-
var COMPACT_COMMAND_REGEX = /^\/compact\b\s*(.*)$/s;
|
|
4027
|
-
var COMPACT_TURN_MARKER = "\0__replicas_compact_turn__\0";
|
|
4028
|
-
var COMPACT_SUMMARY_PROMPT = [
|
|
4029
|
-
"The user has requested a session compaction. Produce a thorough summary of this conversation that captures everything needed to continue the work without the prior context.",
|
|
4030
|
-
"",
|
|
4031
|
-
"Cover at least:",
|
|
4032
|
-
"1. The high-level goal we are working toward and the user's most recent intent.",
|
|
4033
|
-
"2. Key decisions made and the rationale behind them.",
|
|
4034
|
-
"3. Files inspected or modified (paths + the relevant changes).",
|
|
4035
|
-
"4. Open questions, blockers, and pending follow-ups.",
|
|
4036
|
-
"5. Any environment details, credentials, or external systems already configured.",
|
|
4037
|
-
"",
|
|
4038
|
-
"Format the response as Markdown with clear headings. The session will be reset after your reply and your summary re-injected as the prelude to the next user turn; write it so a future agent can resume using only that prelude."
|
|
4039
|
-
].join("\n");
|
|
4040
4027
|
var MAX_INTERRUPT_QUEUE_ITEMS = 1e3;
|
|
4041
4028
|
var MAX_INTERRUPT_QUEUE_CHARS = 2e5;
|
|
4042
4029
|
var CodingAgentManager = class {
|
|
@@ -4047,9 +4034,7 @@ var CodingAgentManager = class {
|
|
|
4047
4034
|
onSaveSessionId;
|
|
4048
4035
|
onEvent;
|
|
4049
4036
|
hostOnTurnComplete;
|
|
4050
|
-
|
|
4051
|
-
compactionBuffer = "";
|
|
4052
|
-
pendingSessionPrelude = null;
|
|
4037
|
+
compacting = false;
|
|
4053
4038
|
constructor(options) {
|
|
4054
4039
|
this.workingDirectory = options.workingDirectory ?? ENGINE_ENV.WORKSPACE_ROOT;
|
|
4055
4040
|
this.initialSessionId = options.initialSessionId;
|
|
@@ -4058,65 +4043,26 @@ var CodingAgentManager = class {
|
|
|
4058
4043
|
this.hostOnTurnComplete = options.onTurnComplete;
|
|
4059
4044
|
}
|
|
4060
4045
|
onTurnComplete = async () => {
|
|
4061
|
-
if (this.
|
|
4062
|
-
this.
|
|
4063
|
-
const summary = this.compactionBuffer.trim();
|
|
4064
|
-
this.compactionBuffer = "";
|
|
4065
|
-
this.pendingSessionPrelude = summary.length > 0 ? summary : null;
|
|
4066
|
-
this.emitCompactionStatus("completed");
|
|
4067
|
-
try {
|
|
4068
|
-
await this.clearSessionState();
|
|
4069
|
-
} catch (error) {
|
|
4070
|
-
console.error("[CodingAgentManager] Failed to clear session after compaction:", error);
|
|
4071
|
-
}
|
|
4046
|
+
if (this.compacting) {
|
|
4047
|
+
this.setCompacting(false);
|
|
4072
4048
|
}
|
|
4073
4049
|
await this.hostOnTurnComplete();
|
|
4074
4050
|
};
|
|
4075
4051
|
isCompacting() {
|
|
4076
|
-
return this.
|
|
4077
|
-
}
|
|
4078
|
-
captureCompactionText(text) {
|
|
4079
|
-
if (!this.compactionInFlight) return;
|
|
4080
|
-
const trimmed = text.trim();
|
|
4081
|
-
if (!trimmed) return;
|
|
4082
|
-
this.compactionBuffer = this.compactionBuffer.length > 0 ? `${this.compactionBuffer}
|
|
4083
|
-
|
|
4084
|
-
${trimmed}` : trimmed;
|
|
4085
|
-
}
|
|
4086
|
-
consumePendingPrelude(message) {
|
|
4087
|
-
if (!this.pendingSessionPrelude) return message;
|
|
4088
|
-
const prelude = this.pendingSessionPrelude;
|
|
4089
|
-
this.pendingSessionPrelude = null;
|
|
4090
|
-
return `<prior-session-summary>
|
|
4091
|
-
${prelude}
|
|
4092
|
-
</prior-session-summary>
|
|
4093
|
-
|
|
4094
|
-
${message}`;
|
|
4052
|
+
return this.compacting;
|
|
4095
4053
|
}
|
|
4096
|
-
|
|
4054
|
+
// Dedup so a noisy stream of native compaction events doesn't spam the UI with redundant status flips.
|
|
4055
|
+
setCompacting(active) {
|
|
4056
|
+
if (this.compacting === active) return;
|
|
4057
|
+
this.compacting = active;
|
|
4097
4058
|
this.onEvent({
|
|
4098
4059
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4099
4060
|
type: COMPACTION_STATUS_EVENT_TYPE,
|
|
4100
|
-
payload: { state }
|
|
4061
|
+
payload: { state: active ? "in_progress" : "completed" }
|
|
4101
4062
|
});
|
|
4102
4063
|
}
|
|
4103
4064
|
initializeManager(processMessage) {
|
|
4104
|
-
|
|
4105
|
-
if (request.message.startsWith(COMPACT_TURN_MARKER)) {
|
|
4106
|
-
this.compactionInFlight = true;
|
|
4107
|
-
this.compactionBuffer = "";
|
|
4108
|
-
this.emitCompactionStatus("in_progress");
|
|
4109
|
-
const summaryPrompt = this.consumePendingPrelude(
|
|
4110
|
-
request.message.slice(COMPACT_TURN_MARKER.length)
|
|
4111
|
-
);
|
|
4112
|
-
return processMessage({ ...request, message: summaryPrompt });
|
|
4113
|
-
}
|
|
4114
|
-
return processMessage({
|
|
4115
|
-
...request,
|
|
4116
|
-
message: this.consumePendingPrelude(request.message)
|
|
4117
|
-
});
|
|
4118
|
-
};
|
|
4119
|
-
this.messageQueue = new MessageQueueService(wrappedProcessMessage);
|
|
4065
|
+
this.messageQueue = new MessageQueueService(processMessage);
|
|
4120
4066
|
this.initialized = this.initialize();
|
|
4121
4067
|
}
|
|
4122
4068
|
async interrupt() {
|
|
@@ -4136,7 +4082,7 @@ ${message}`;
|
|
|
4136
4082
|
getQueue() {
|
|
4137
4083
|
return this.messageQueue.getQueue().map((m) => ({
|
|
4138
4084
|
id: m.id,
|
|
4139
|
-
message: m.message
|
|
4085
|
+
message: m.message,
|
|
4140
4086
|
queuedAt: m.queuedAt,
|
|
4141
4087
|
...m.senderUserId ? { senderUserId: m.senderUserId } : {},
|
|
4142
4088
|
...m.senderEmail ? { senderEmail: m.senderEmail } : {},
|
|
@@ -4151,18 +4097,6 @@ ${message}`;
|
|
|
4151
4097
|
}
|
|
4152
4098
|
async enqueueMessage(request) {
|
|
4153
4099
|
await this.initialized;
|
|
4154
|
-
const compact = request.message.trimStart().match(COMPACT_COMMAND_REGEX);
|
|
4155
|
-
if (compact) {
|
|
4156
|
-
const guidance = compact[1].trim();
|
|
4157
|
-
const prompt = guidance ? `${COMPACT_SUMMARY_PROMPT}
|
|
4158
|
-
|
|
4159
|
-
Additional guidance from the user for the summary:
|
|
4160
|
-
${guidance}` : COMPACT_SUMMARY_PROMPT;
|
|
4161
|
-
return this.messageQueue.enqueue({
|
|
4162
|
-
...request,
|
|
4163
|
-
message: `${COMPACT_TURN_MARKER}${prompt}`
|
|
4164
|
-
});
|
|
4165
|
-
}
|
|
4166
4100
|
return this.messageQueue.enqueue(request);
|
|
4167
4101
|
}
|
|
4168
4102
|
emitContextUsage(payload) {
|
|
@@ -4201,7 +4135,7 @@ ${guidance}` : COMPACT_SUMMARY_PROMPT;
|
|
|
4201
4135
|
const queue = this.messageQueue.drainQueue({
|
|
4202
4136
|
maxItems: MAX_INTERRUPT_QUEUE_ITEMS,
|
|
4203
4137
|
maxChars: MAX_INTERRUPT_QUEUE_CHARS
|
|
4204
|
-
})
|
|
4138
|
+
});
|
|
4205
4139
|
return {
|
|
4206
4140
|
queue,
|
|
4207
4141
|
isProcessing: this.messageQueue.isProcessing()
|
|
@@ -4478,10 +4412,6 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
4478
4412
|
}
|
|
4479
4413
|
await this.abortAllPendingToolInputs();
|
|
4480
4414
|
}
|
|
4481
|
-
async clearSessionState() {
|
|
4482
|
-
this.sessionId = null;
|
|
4483
|
-
await this.onSaveSessionId(null);
|
|
4484
|
-
}
|
|
4485
4415
|
async abortAllPendingToolInputs() {
|
|
4486
4416
|
const pending = Array.from(this.pendingToolInputs.values());
|
|
4487
4417
|
this.pendingToolInputs.clear();
|
|
@@ -4839,15 +4769,20 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
4839
4769
|
console.log(`[ClaudeManager] Captured and persisted session ID: ${this.sessionId}`);
|
|
4840
4770
|
}
|
|
4841
4771
|
await this.checkForAuthFailure(message);
|
|
4842
|
-
|
|
4843
|
-
for (const block of message.message.content) {
|
|
4844
|
-
if (block.type === "text") {
|
|
4845
|
-
this.captureCompactionText(block.text);
|
|
4846
|
-
}
|
|
4847
|
-
}
|
|
4848
|
-
}
|
|
4772
|
+
this.trackNativeCompaction(message);
|
|
4849
4773
|
await this.recordEvent(message);
|
|
4850
4774
|
}
|
|
4775
|
+
// Claude Code intercepts /compact and auto-compaction inside the SDK process; we just observe the status messages to mirror state to the UI.
|
|
4776
|
+
trackNativeCompaction(message) {
|
|
4777
|
+
if (message.type !== "system") return;
|
|
4778
|
+
if (message.subtype === "status" && message.status === "compacting") {
|
|
4779
|
+
this.setCompacting(true);
|
|
4780
|
+
return;
|
|
4781
|
+
}
|
|
4782
|
+
if (message.subtype === "compact_boundary") {
|
|
4783
|
+
this.setCompacting(false);
|
|
4784
|
+
}
|
|
4785
|
+
}
|
|
4851
4786
|
async recordEvent(event) {
|
|
4852
4787
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
4853
4788
|
const jsonEvent = {
|
|
@@ -5011,11 +4946,6 @@ var CodexManager = class _CodexManager extends CodingAgentManager {
|
|
|
5011
4946
|
this.activeAbortController.abort();
|
|
5012
4947
|
}
|
|
5013
4948
|
}
|
|
5014
|
-
async clearSessionState() {
|
|
5015
|
-
this.currentThreadId = null;
|
|
5016
|
-
this.currentThread = null;
|
|
5017
|
-
await this.onSaveSessionId(null);
|
|
5018
|
-
}
|
|
5019
4949
|
/**
|
|
5020
4950
|
* Update the developer_instructions in ~/.codex/config.toml
|
|
5021
4951
|
* This sets the system prompt that Codex will use for this turn
|
|
@@ -5289,16 +5219,21 @@ var CodexManager = class _CodexManager extends CodingAgentManager {
|
|
|
5289
5219
|
}
|
|
5290
5220
|
return null;
|
|
5291
5221
|
}
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
if (event.type
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5222
|
+
// @openai/codex-sdk doesn't expose manual /compact (TUI-only); we only mirror the auto-compaction rollout entries to the UI.
|
|
5223
|
+
trackNativeCompaction(event) {
|
|
5224
|
+
if (event.type === "compacted") {
|
|
5225
|
+
this.setCompacting(false);
|
|
5226
|
+
return;
|
|
5227
|
+
}
|
|
5228
|
+
if (event.type !== "event_msg") return;
|
|
5229
|
+
const msg = event.payload.msg;
|
|
5230
|
+
if (!msg) return;
|
|
5231
|
+
const itemType = msg.payload?.item?.type;
|
|
5232
|
+
if (itemType !== "context_compaction") return;
|
|
5233
|
+
if (msg.type === "item_started") {
|
|
5234
|
+
this.setCompacting(true);
|
|
5235
|
+
} else if (msg.type === "item_completed") {
|
|
5236
|
+
this.setCompacting(false);
|
|
5302
5237
|
}
|
|
5303
5238
|
}
|
|
5304
5239
|
async startSessionTail(threadId) {
|
|
@@ -5351,7 +5286,7 @@ var CodexManager = class _CodexManager extends CodingAgentManager {
|
|
|
5351
5286
|
this.emitQuotaStatus(snapshot);
|
|
5352
5287
|
}
|
|
5353
5288
|
if (isJsonlEvent2(parsed)) {
|
|
5354
|
-
this.
|
|
5289
|
+
this.trackNativeCompaction(parsed);
|
|
5355
5290
|
this.onEvent(parsed);
|
|
5356
5291
|
emitted += 1;
|
|
5357
5292
|
}
|
|
@@ -5384,6 +5319,574 @@ var CodexManager = class _CodexManager extends CodingAgentManager {
|
|
|
5384
5319
|
}
|
|
5385
5320
|
};
|
|
5386
5321
|
|
|
5322
|
+
// src/managers/codex-asp/app-server-process.ts
|
|
5323
|
+
import { spawn } from "child_process";
|
|
5324
|
+
import { EventEmitter as EventEmitter2 } from "events";
|
|
5325
|
+
|
|
5326
|
+
// src/managers/codex-asp/asp-client.ts
|
|
5327
|
+
import { EventEmitter } from "events";
|
|
5328
|
+
var DEFAULT_REQUEST_TIMEOUT_MS = 12e4;
|
|
5329
|
+
function hasOwn(record, key) {
|
|
5330
|
+
return Object.prototype.hasOwnProperty.call(record, key);
|
|
5331
|
+
}
|
|
5332
|
+
var AspClient = class {
|
|
5333
|
+
stdin;
|
|
5334
|
+
stdout;
|
|
5335
|
+
emitter = new EventEmitter();
|
|
5336
|
+
pending = /* @__PURE__ */ new Map();
|
|
5337
|
+
nextId = 1;
|
|
5338
|
+
lineBuffer = "";
|
|
5339
|
+
disposed = false;
|
|
5340
|
+
get isDisposed() {
|
|
5341
|
+
return this.disposed;
|
|
5342
|
+
}
|
|
5343
|
+
constructor(options) {
|
|
5344
|
+
this.stdin = options.stdin;
|
|
5345
|
+
this.stdout = options.stdout;
|
|
5346
|
+
this.stdout.setEncoding("utf8");
|
|
5347
|
+
this.stdout.on("data", this.handleStdoutData);
|
|
5348
|
+
this.stdin.on("error", this.handleStdinError);
|
|
5349
|
+
}
|
|
5350
|
+
on(event, listener) {
|
|
5351
|
+
this.emitter.on(event, listener);
|
|
5352
|
+
}
|
|
5353
|
+
off(event, listener) {
|
|
5354
|
+
this.emitter.off(event, listener);
|
|
5355
|
+
}
|
|
5356
|
+
async request(method, params, opts) {
|
|
5357
|
+
if (this.disposed) {
|
|
5358
|
+
throw new Error(`Cannot send ${method}: ASP client disposed`);
|
|
5359
|
+
}
|
|
5360
|
+
const id = this.nextId;
|
|
5361
|
+
this.nextId += 1;
|
|
5362
|
+
const promise = new Promise((resolve3, reject) => {
|
|
5363
|
+
const timeoutMs = opts?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
5364
|
+
const timer = timeoutMs > 0 ? setTimeout(() => {
|
|
5365
|
+
this.pending.delete(id);
|
|
5366
|
+
reject(new Error(`ASP request timed out for ${method}`));
|
|
5367
|
+
}, timeoutMs) : null;
|
|
5368
|
+
this.pending.set(id, { resolve: resolve3, reject, method, timer });
|
|
5369
|
+
});
|
|
5370
|
+
this.write({ method, id, params });
|
|
5371
|
+
return promise;
|
|
5372
|
+
}
|
|
5373
|
+
notify(method, params) {
|
|
5374
|
+
if (this.disposed) {
|
|
5375
|
+
return;
|
|
5376
|
+
}
|
|
5377
|
+
try {
|
|
5378
|
+
this.write(params === void 0 ? { method } : { method, params });
|
|
5379
|
+
} catch (error) {
|
|
5380
|
+
console.warn(`[AspClient] Failed to send notification ${method}:`, error);
|
|
5381
|
+
}
|
|
5382
|
+
}
|
|
5383
|
+
respond(id, result) {
|
|
5384
|
+
if (this.disposed) {
|
|
5385
|
+
return;
|
|
5386
|
+
}
|
|
5387
|
+
try {
|
|
5388
|
+
this.write({ id, result });
|
|
5389
|
+
} catch (error) {
|
|
5390
|
+
console.warn(`[AspClient] Failed to send response ${String(id)}:`, error);
|
|
5391
|
+
}
|
|
5392
|
+
}
|
|
5393
|
+
dispose(reason = new Error("ASP client disposed")) {
|
|
5394
|
+
if (this.disposed) {
|
|
5395
|
+
return;
|
|
5396
|
+
}
|
|
5397
|
+
this.disposed = true;
|
|
5398
|
+
this.stdout.off("data", this.handleStdoutData);
|
|
5399
|
+
this.stdin.removeListener("error", this.handleStdinError);
|
|
5400
|
+
for (const [id, pending] of this.pending) {
|
|
5401
|
+
if (pending.timer) {
|
|
5402
|
+
clearTimeout(pending.timer);
|
|
5403
|
+
}
|
|
5404
|
+
pending.reject(new Error(`${reason.message} while waiting for ${pending.method}`));
|
|
5405
|
+
this.pending.delete(id);
|
|
5406
|
+
}
|
|
5407
|
+
this.lineBuffer = "";
|
|
5408
|
+
this.emitter.emit("dispose", reason);
|
|
5409
|
+
this.emitter.removeAllListeners();
|
|
5410
|
+
}
|
|
5411
|
+
handleStdoutData = (chunk) => {
|
|
5412
|
+
this.lineBuffer += chunk.toString();
|
|
5413
|
+
let newlineIndex = this.lineBuffer.indexOf("\n");
|
|
5414
|
+
while (newlineIndex >= 0) {
|
|
5415
|
+
const line = this.lineBuffer.slice(0, newlineIndex).trim();
|
|
5416
|
+
this.lineBuffer = this.lineBuffer.slice(newlineIndex + 1);
|
|
5417
|
+
if (line.length > 0) {
|
|
5418
|
+
this.handleLine(line);
|
|
5419
|
+
}
|
|
5420
|
+
newlineIndex = this.lineBuffer.indexOf("\n");
|
|
5421
|
+
}
|
|
5422
|
+
};
|
|
5423
|
+
handleStdinError = (error) => {
|
|
5424
|
+
this.dispose(new Error(`ASP stdin error: ${error.message}`));
|
|
5425
|
+
};
|
|
5426
|
+
handleLine(line) {
|
|
5427
|
+
let parsed;
|
|
5428
|
+
try {
|
|
5429
|
+
parsed = JSON.parse(line);
|
|
5430
|
+
} catch (error) {
|
|
5431
|
+
console.warn("[AspClient] Failed to parse ASP JSON line:", error);
|
|
5432
|
+
return;
|
|
5433
|
+
}
|
|
5434
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
5435
|
+
console.warn("[AspClient] Ignoring non-object ASP message");
|
|
5436
|
+
return;
|
|
5437
|
+
}
|
|
5438
|
+
const message = parsed;
|
|
5439
|
+
const hasRequestId = typeof message.id === "number" || typeof message.id === "string";
|
|
5440
|
+
if (hasRequestId && (hasOwn(message, "result") || hasOwn(message, "error"))) {
|
|
5441
|
+
this.handleResponse(message);
|
|
5442
|
+
return;
|
|
5443
|
+
}
|
|
5444
|
+
if (hasRequestId && typeof message.method === "string") {
|
|
5445
|
+
this.emitter.emit("serverRequest", message);
|
|
5446
|
+
return;
|
|
5447
|
+
}
|
|
5448
|
+
if (!hasOwn(message, "id") && typeof message.method === "string") {
|
|
5449
|
+
this.emitter.emit("notification", message);
|
|
5450
|
+
}
|
|
5451
|
+
}
|
|
5452
|
+
handleResponse(message) {
|
|
5453
|
+
if (typeof message.id !== "number") {
|
|
5454
|
+
console.warn("[AspClient] Ignoring response with non-numeric request id");
|
|
5455
|
+
return;
|
|
5456
|
+
}
|
|
5457
|
+
const pending = this.pending.get(message.id);
|
|
5458
|
+
if (!pending) {
|
|
5459
|
+
console.warn(`[AspClient] Ignoring response for unknown request id ${message.id}`);
|
|
5460
|
+
return;
|
|
5461
|
+
}
|
|
5462
|
+
this.pending.delete(message.id);
|
|
5463
|
+
if (pending.timer) {
|
|
5464
|
+
clearTimeout(pending.timer);
|
|
5465
|
+
}
|
|
5466
|
+
if (hasOwn(message, "error")) {
|
|
5467
|
+
pending.reject(this.createRpcError(pending.method, message.error));
|
|
5468
|
+
return;
|
|
5469
|
+
}
|
|
5470
|
+
pending.resolve(message.result);
|
|
5471
|
+
}
|
|
5472
|
+
createRpcError(method, error) {
|
|
5473
|
+
if (typeof error !== "object" || error === null || Array.isArray(error)) {
|
|
5474
|
+
return new Error(`ASP request failed for ${method}`);
|
|
5475
|
+
}
|
|
5476
|
+
const rpcError = error;
|
|
5477
|
+
const code = typeof rpcError.code === "number" ? ` ${rpcError.code}` : "";
|
|
5478
|
+
const message = typeof rpcError.message === "string" ? rpcError.message : "Unknown ASP error";
|
|
5479
|
+
const data = hasOwn(rpcError, "data") ? ` data=${JSON.stringify(rpcError.data)}` : "";
|
|
5480
|
+
return new Error(`ASP request failed for ${method}:${code} ${message}${data}`);
|
|
5481
|
+
}
|
|
5482
|
+
write(message) {
|
|
5483
|
+
try {
|
|
5484
|
+
this.stdin.write(`${JSON.stringify(message)}
|
|
5485
|
+
`, (error) => {
|
|
5486
|
+
if (error) {
|
|
5487
|
+
this.dispose(new Error(`ASP write failed: ${error.message}`));
|
|
5488
|
+
}
|
|
5489
|
+
});
|
|
5490
|
+
} catch (error) {
|
|
5491
|
+
const writeError = error instanceof Error ? error : new Error("ASP write failed");
|
|
5492
|
+
this.dispose(writeError);
|
|
5493
|
+
throw writeError;
|
|
5494
|
+
}
|
|
5495
|
+
}
|
|
5496
|
+
};
|
|
5497
|
+
|
|
5498
|
+
// src/managers/codex-asp/app-server-process.ts
|
|
5499
|
+
var DEFAULT_CODEX_BINARY = "codex";
|
|
5500
|
+
var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
|
|
5501
|
+
var ENGINE_PACKAGE_VERSION = "0.1.213";
|
|
5502
|
+
var INITIALIZE_METHOD = "initialize";
|
|
5503
|
+
var INITIALIZED_NOTIFICATION = "initialized";
|
|
5504
|
+
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|
|
5505
|
+
var AppServerProcess = class {
|
|
5506
|
+
binary;
|
|
5507
|
+
args;
|
|
5508
|
+
env;
|
|
5509
|
+
cwd;
|
|
5510
|
+
emitter = new EventEmitter2();
|
|
5511
|
+
child = null;
|
|
5512
|
+
client = null;
|
|
5513
|
+
shuttingDown = false;
|
|
5514
|
+
constructor(options = {}) {
|
|
5515
|
+
this.binary = options.binary ?? DEFAULT_CODEX_BINARY;
|
|
5516
|
+
this.args = options.args ?? DEFAULT_CODEX_ARGS;
|
|
5517
|
+
this.env = options.env ?? buildCodexAgentEnv();
|
|
5518
|
+
this.cwd = options.cwd ?? ENGINE_ENV.WORKSPACE_ROOT;
|
|
5519
|
+
}
|
|
5520
|
+
on(event, listener) {
|
|
5521
|
+
this.emitter.on(event, listener);
|
|
5522
|
+
}
|
|
5523
|
+
async start() {
|
|
5524
|
+
if (this.child && this.client) {
|
|
5525
|
+
return { client: this.client };
|
|
5526
|
+
}
|
|
5527
|
+
this.shuttingDown = false;
|
|
5528
|
+
const child = spawn(this.binary, this.args, {
|
|
5529
|
+
cwd: this.cwd,
|
|
5530
|
+
env: this.env,
|
|
5531
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
5532
|
+
});
|
|
5533
|
+
this.child = child;
|
|
5534
|
+
child.stderr.setEncoding("utf8");
|
|
5535
|
+
child.stderr.on("data", (chunk) => {
|
|
5536
|
+
for (const line of chunk.toString().split("\n")) {
|
|
5537
|
+
if (line.trim().length > 0) {
|
|
5538
|
+
console.error(`[codex-app-server] ${line}`);
|
|
5539
|
+
}
|
|
5540
|
+
}
|
|
5541
|
+
});
|
|
5542
|
+
child.on("exit", (code, signal) => {
|
|
5543
|
+
this.client?.dispose();
|
|
5544
|
+
this.client = null;
|
|
5545
|
+
this.child = null;
|
|
5546
|
+
if (!this.shuttingDown) {
|
|
5547
|
+
console.warn(`[AppServerProcess] codex app-server exited unexpectedly code=${code ?? "null"} signal=${signal ?? "null"}`);
|
|
5548
|
+
this.emitter.emit("exit", code, signal);
|
|
5549
|
+
}
|
|
5550
|
+
});
|
|
5551
|
+
const client = new AspClient({ stdin: child.stdin, stdout: child.stdout });
|
|
5552
|
+
this.client = client;
|
|
5553
|
+
let cleanupEarlyFailureHandlers = () => {
|
|
5554
|
+
};
|
|
5555
|
+
const earlyFailure = new Promise((_resolve, reject) => {
|
|
5556
|
+
const onError = (error) => {
|
|
5557
|
+
reject(error);
|
|
5558
|
+
};
|
|
5559
|
+
const onExit = (code, signal) => {
|
|
5560
|
+
reject(new Error(`codex app-server exited before initialize completed code=${code ?? "null"} signal=${signal ?? "null"}`));
|
|
5561
|
+
};
|
|
5562
|
+
child.once("error", onError);
|
|
5563
|
+
child.once("exit", onExit);
|
|
5564
|
+
cleanupEarlyFailureHandlers = () => {
|
|
5565
|
+
child.off("error", onError);
|
|
5566
|
+
child.off("exit", onExit);
|
|
5567
|
+
};
|
|
5568
|
+
});
|
|
5569
|
+
try {
|
|
5570
|
+
const initializeParams = {
|
|
5571
|
+
clientInfo: {
|
|
5572
|
+
name: "replicas_engine",
|
|
5573
|
+
title: "Replicas Engine",
|
|
5574
|
+
version: ENGINE_PACKAGE_VERSION
|
|
5575
|
+
},
|
|
5576
|
+
capabilities: {
|
|
5577
|
+
experimentalApi: true,
|
|
5578
|
+
requestAttestation: false,
|
|
5579
|
+
optOutNotificationMethods: null
|
|
5580
|
+
}
|
|
5581
|
+
};
|
|
5582
|
+
await Promise.race([
|
|
5583
|
+
client.request(INITIALIZE_METHOD, initializeParams),
|
|
5584
|
+
earlyFailure
|
|
5585
|
+
]);
|
|
5586
|
+
cleanupEarlyFailureHandlers();
|
|
5587
|
+
client.notify(INITIALIZED_NOTIFICATION);
|
|
5588
|
+
await this.loginWithConfiguredApiKey(client);
|
|
5589
|
+
return { client };
|
|
5590
|
+
} catch (error) {
|
|
5591
|
+
cleanupEarlyFailureHandlers();
|
|
5592
|
+
client.dispose();
|
|
5593
|
+
await this.killAfterFailedStart();
|
|
5594
|
+
throw error;
|
|
5595
|
+
}
|
|
5596
|
+
}
|
|
5597
|
+
async loginWithConfiguredApiKey(client) {
|
|
5598
|
+
if (ENGINE_ENV.REPLICAS_CODEX_AUTH_METHOD !== "api_key" || !ENGINE_ENV.OPENAI_API_KEY) {
|
|
5599
|
+
return;
|
|
5600
|
+
}
|
|
5601
|
+
const params = {
|
|
5602
|
+
type: "apiKey",
|
|
5603
|
+
apiKey: ENGINE_ENV.OPENAI_API_KEY
|
|
5604
|
+
};
|
|
5605
|
+
await client.request(ACCOUNT_LOGIN_START_METHOD, params);
|
|
5606
|
+
}
|
|
5607
|
+
async killAfterFailedStart() {
|
|
5608
|
+
const child = this.child;
|
|
5609
|
+
this.child = null;
|
|
5610
|
+
this.client = null;
|
|
5611
|
+
if (!child || child.killed) {
|
|
5612
|
+
return;
|
|
5613
|
+
}
|
|
5614
|
+
this.shuttingDown = true;
|
|
5615
|
+
child.kill("SIGKILL");
|
|
5616
|
+
await new Promise((resolve3) => {
|
|
5617
|
+
child.once("exit", () => resolve3());
|
|
5618
|
+
});
|
|
5619
|
+
}
|
|
5620
|
+
};
|
|
5621
|
+
|
|
5622
|
+
// src/managers/codex-asp/asp-host.ts
|
|
5623
|
+
var hostPromise = null;
|
|
5624
|
+
async function getCodexAspHost() {
|
|
5625
|
+
hostPromise ??= (async () => {
|
|
5626
|
+
try {
|
|
5627
|
+
const process2 = new AppServerProcess();
|
|
5628
|
+
const { client } = await process2.start();
|
|
5629
|
+
process2.on("exit", () => {
|
|
5630
|
+
hostPromise = null;
|
|
5631
|
+
});
|
|
5632
|
+
return { client };
|
|
5633
|
+
} catch (error) {
|
|
5634
|
+
hostPromise = null;
|
|
5635
|
+
throw error;
|
|
5636
|
+
}
|
|
5637
|
+
})();
|
|
5638
|
+
return hostPromise;
|
|
5639
|
+
}
|
|
5640
|
+
|
|
5641
|
+
// src/managers/codex-asp/codex-asp-manager.ts
|
|
5642
|
+
var DEFAULT_MODEL2 = "gpt-5.5";
|
|
5643
|
+
var THREAD_START_METHOD = "thread/start";
|
|
5644
|
+
var TURN_START_METHOD = "turn/start";
|
|
5645
|
+
var TURN_INTERRUPT_METHOD = "turn/interrupt";
|
|
5646
|
+
var TURN_COMPLETED_METHOD = "turn/completed";
|
|
5647
|
+
var ITEM_COMPLETED_METHOD = "item/completed";
|
|
5648
|
+
var AGENT_MESSAGE_DELTA_METHOD = "item/agentMessage/delta";
|
|
5649
|
+
var COMMAND_APPROVAL_METHOD = "item/commandExecution/requestApproval";
|
|
5650
|
+
var FILE_CHANGE_APPROVAL_METHOD = "item/fileChange/requestApproval";
|
|
5651
|
+
var CodexAspManager = class extends CodingAgentManager {
|
|
5652
|
+
currentThreadId = null;
|
|
5653
|
+
activeTurnId = null;
|
|
5654
|
+
historyEvents = [];
|
|
5655
|
+
constructor(options) {
|
|
5656
|
+
super(options);
|
|
5657
|
+
this.initializeManager(this.processMessageInternal.bind(this));
|
|
5658
|
+
}
|
|
5659
|
+
async initialize() {
|
|
5660
|
+
if (this.initialSessionId) {
|
|
5661
|
+
this.currentThreadId = this.initialSessionId;
|
|
5662
|
+
}
|
|
5663
|
+
}
|
|
5664
|
+
async interruptActiveTurn() {
|
|
5665
|
+
if (!this.currentThreadId || !this.activeTurnId) {
|
|
5666
|
+
return;
|
|
5667
|
+
}
|
|
5668
|
+
try {
|
|
5669
|
+
const host = await getCodexAspHost();
|
|
5670
|
+
const params = {
|
|
5671
|
+
threadId: this.currentThreadId,
|
|
5672
|
+
turnId: this.activeTurnId
|
|
5673
|
+
};
|
|
5674
|
+
await host.client.request(TURN_INTERRUPT_METHOD, params);
|
|
5675
|
+
} catch (error) {
|
|
5676
|
+
console.warn("[CodexAspManager] Failed to interrupt active turn:", error);
|
|
5677
|
+
}
|
|
5678
|
+
}
|
|
5679
|
+
async getHistory() {
|
|
5680
|
+
return {
|
|
5681
|
+
thread_id: this.currentThreadId,
|
|
5682
|
+
events: [...this.historyEvents]
|
|
5683
|
+
};
|
|
5684
|
+
}
|
|
5685
|
+
async processMessageInternal(request) {
|
|
5686
|
+
let host = null;
|
|
5687
|
+
try {
|
|
5688
|
+
host = await getCodexAspHost();
|
|
5689
|
+
const developerInstructions = this.buildCombinedInstructions(request.customInstructions);
|
|
5690
|
+
this.recordHistoryEvent("event_msg", {
|
|
5691
|
+
type: "user_message",
|
|
5692
|
+
message: request.message
|
|
5693
|
+
});
|
|
5694
|
+
if (!this.currentThreadId) {
|
|
5695
|
+
const threadStartResponse = await host.client.request(
|
|
5696
|
+
THREAD_START_METHOD,
|
|
5697
|
+
await this.buildThreadStartParams(request, developerInstructions)
|
|
5698
|
+
);
|
|
5699
|
+
this.currentThreadId = threadStartResponse.thread.id;
|
|
5700
|
+
await this.onSaveSessionId(this.currentThreadId);
|
|
5701
|
+
}
|
|
5702
|
+
const threadId = this.currentThreadId;
|
|
5703
|
+
const completedTurn = await this.runTurn(host, threadId, request, developerInstructions);
|
|
5704
|
+
if (completedTurn.status === "failed") {
|
|
5705
|
+
const turnError = completedTurn.error;
|
|
5706
|
+
if (!turnError) {
|
|
5707
|
+
throw new Error("Codex ASP turn failed without error details");
|
|
5708
|
+
}
|
|
5709
|
+
const parts = [`Codex ASP turn failed: ${turnError.message}`];
|
|
5710
|
+
if (turnError.codexErrorInfo !== null) {
|
|
5711
|
+
parts.push(`codexErrorInfo=${JSON.stringify(turnError.codexErrorInfo)}`);
|
|
5712
|
+
}
|
|
5713
|
+
if (turnError.additionalDetails) {
|
|
5714
|
+
parts.push(`details=${turnError.additionalDetails}`);
|
|
5715
|
+
}
|
|
5716
|
+
throw new Error(parts.join(" "));
|
|
5717
|
+
}
|
|
5718
|
+
if (completedTurn.status === "completed") {
|
|
5719
|
+
this.emitFinalAgentMessage(completedTurn);
|
|
5720
|
+
}
|
|
5721
|
+
} finally {
|
|
5722
|
+
this.activeTurnId = null;
|
|
5723
|
+
if (host?.client.isDisposed) {
|
|
5724
|
+
this.currentThreadId = null;
|
|
5725
|
+
void this.onSaveSessionId(null).catch(() => {
|
|
5726
|
+
});
|
|
5727
|
+
}
|
|
5728
|
+
await this.onTurnComplete();
|
|
5729
|
+
}
|
|
5730
|
+
}
|
|
5731
|
+
async buildThreadStartParams(request, developerInstructions) {
|
|
5732
|
+
const additionalDirectories = await getAgentAdditionalDirectories();
|
|
5733
|
+
return {
|
|
5734
|
+
model: request.model ?? DEFAULT_MODEL2,
|
|
5735
|
+
cwd: this.workingDirectory,
|
|
5736
|
+
runtimeWorkspaceRoots: additionalDirectories,
|
|
5737
|
+
sandbox: "danger-full-access",
|
|
5738
|
+
developerInstructions: developerInstructions ?? null,
|
|
5739
|
+
config: { web_search: "live" },
|
|
5740
|
+
experimentalRawEvents: false,
|
|
5741
|
+
persistExtendedHistory: false
|
|
5742
|
+
};
|
|
5743
|
+
}
|
|
5744
|
+
buildTurnStartParams(threadId, request, developerInstructions) {
|
|
5745
|
+
const effort = request.thinkingLevel === "max" ? "xhigh" : request.thinkingLevel;
|
|
5746
|
+
const model = request.model ?? DEFAULT_MODEL2;
|
|
5747
|
+
return {
|
|
5748
|
+
threadId,
|
|
5749
|
+
input: [{
|
|
5750
|
+
type: "text",
|
|
5751
|
+
text: request.message,
|
|
5752
|
+
text_elements: []
|
|
5753
|
+
}],
|
|
5754
|
+
model,
|
|
5755
|
+
...effort ? { effort } : {},
|
|
5756
|
+
...developerInstructions ? {
|
|
5757
|
+
collaborationMode: {
|
|
5758
|
+
mode: "default",
|
|
5759
|
+
settings: {
|
|
5760
|
+
model,
|
|
5761
|
+
reasoning_effort: effort ?? null,
|
|
5762
|
+
developer_instructions: developerInstructions
|
|
5763
|
+
}
|
|
5764
|
+
}
|
|
5765
|
+
} : {}
|
|
5766
|
+
};
|
|
5767
|
+
}
|
|
5768
|
+
async runTurn(host, threadId, request, developerInstructions) {
|
|
5769
|
+
let resolveCompleted;
|
|
5770
|
+
const completed = new Promise((resolve3) => {
|
|
5771
|
+
resolveCompleted = resolve3;
|
|
5772
|
+
});
|
|
5773
|
+
let rejectDisposed = () => {
|
|
5774
|
+
};
|
|
5775
|
+
const disposed = new Promise((_resolve, reject) => {
|
|
5776
|
+
rejectDisposed = reject;
|
|
5777
|
+
});
|
|
5778
|
+
void disposed.catch(() => {
|
|
5779
|
+
});
|
|
5780
|
+
let observedTurnId = null;
|
|
5781
|
+
const completedItems = [];
|
|
5782
|
+
const agentMessageDeltas = /* @__PURE__ */ new Map();
|
|
5783
|
+
const onNotification = (notification) => {
|
|
5784
|
+
if (notification.method === ITEM_COMPLETED_METHOD) {
|
|
5785
|
+
if (notification.params.threadId === threadId && (!observedTurnId || notification.params.turnId === observedTurnId)) {
|
|
5786
|
+
completedItems.push(notification.params.item);
|
|
5787
|
+
}
|
|
5788
|
+
return;
|
|
5789
|
+
}
|
|
5790
|
+
if (notification.method === AGENT_MESSAGE_DELTA_METHOD) {
|
|
5791
|
+
if (notification.params.threadId === threadId && (!observedTurnId || notification.params.turnId === observedTurnId)) {
|
|
5792
|
+
const currentText = agentMessageDeltas.get(notification.params.itemId) ?? "";
|
|
5793
|
+
agentMessageDeltas.set(notification.params.itemId, currentText + notification.params.delta);
|
|
5794
|
+
}
|
|
5795
|
+
return;
|
|
5796
|
+
}
|
|
5797
|
+
if (notification.method === TURN_COMPLETED_METHOD) {
|
|
5798
|
+
if (notification.params.threadId !== threadId) {
|
|
5799
|
+
return;
|
|
5800
|
+
}
|
|
5801
|
+
observedTurnId = notification.params.turn.id;
|
|
5802
|
+
const turn = notification.params.turn;
|
|
5803
|
+
const items = turn.items.length > 0 ? [...turn.items] : [];
|
|
5804
|
+
const itemIds = new Set(items.map((item) => item.id));
|
|
5805
|
+
for (const item of completedItems) {
|
|
5806
|
+
if (!itemIds.has(item.id)) {
|
|
5807
|
+
items.push(item);
|
|
5808
|
+
itemIds.add(item.id);
|
|
5809
|
+
}
|
|
5810
|
+
}
|
|
5811
|
+
for (const [itemId, text] of agentMessageDeltas) {
|
|
5812
|
+
if (!itemIds.has(itemId)) {
|
|
5813
|
+
items.push({
|
|
5814
|
+
type: "agentMessage",
|
|
5815
|
+
id: itemId,
|
|
5816
|
+
text,
|
|
5817
|
+
phase: null,
|
|
5818
|
+
memoryCitation: null
|
|
5819
|
+
});
|
|
5820
|
+
}
|
|
5821
|
+
}
|
|
5822
|
+
resolveCompleted(items.length > 0 ? { ...turn, items, itemsView: "full" } : turn);
|
|
5823
|
+
}
|
|
5824
|
+
};
|
|
5825
|
+
const onServerRequest = (serverRequest) => {
|
|
5826
|
+
if (serverRequest.method !== COMMAND_APPROVAL_METHOD && serverRequest.method !== FILE_CHANGE_APPROVAL_METHOD) {
|
|
5827
|
+
return;
|
|
5828
|
+
}
|
|
5829
|
+
console.warn("[CodexAspManager] approval requested while sandbox is danger-full-access");
|
|
5830
|
+
host.client.respond(serverRequest.id, { decision: "accept" });
|
|
5831
|
+
};
|
|
5832
|
+
const onDispose = (reason) => {
|
|
5833
|
+
this.currentThreadId = null;
|
|
5834
|
+
this.activeTurnId = null;
|
|
5835
|
+
void this.onSaveSessionId(null).catch(() => {
|
|
5836
|
+
});
|
|
5837
|
+
const turnLabel = observedTurnId ? ` ${observedTurnId}` : "";
|
|
5838
|
+
rejectDisposed(new Error(`Codex ASP client disposed before turn${turnLabel} completed: ${reason.message}`));
|
|
5839
|
+
};
|
|
5840
|
+
host.client.on("notification", onNotification);
|
|
5841
|
+
host.client.on("serverRequest", onServerRequest);
|
|
5842
|
+
host.client.on("dispose", onDispose);
|
|
5843
|
+
try {
|
|
5844
|
+
const turnStartResponse = await host.client.request(
|
|
5845
|
+
TURN_START_METHOD,
|
|
5846
|
+
this.buildTurnStartParams(threadId, request, developerInstructions)
|
|
5847
|
+
);
|
|
5848
|
+
observedTurnId = turnStartResponse.turn.id;
|
|
5849
|
+
this.activeTurnId = turnStartResponse.turn.id;
|
|
5850
|
+
return await Promise.race([completed, disposed]);
|
|
5851
|
+
} finally {
|
|
5852
|
+
host.client.off("notification", onNotification);
|
|
5853
|
+
host.client.off("serverRequest", onServerRequest);
|
|
5854
|
+
host.client.off("dispose", onDispose);
|
|
5855
|
+
}
|
|
5856
|
+
}
|
|
5857
|
+
emitFinalAgentMessage(turn) {
|
|
5858
|
+
let text = null;
|
|
5859
|
+
for (let index = turn.items.length - 1; index >= 0; index -= 1) {
|
|
5860
|
+
const item = turn.items[index];
|
|
5861
|
+
if (item?.type === "agentMessage") {
|
|
5862
|
+
text = item.text;
|
|
5863
|
+
break;
|
|
5864
|
+
}
|
|
5865
|
+
}
|
|
5866
|
+
if (!text) {
|
|
5867
|
+
return;
|
|
5868
|
+
}
|
|
5869
|
+
const event = this.recordHistoryEvent("response_item", {
|
|
5870
|
+
type: "message",
|
|
5871
|
+
role: "assistant",
|
|
5872
|
+
content: [{
|
|
5873
|
+
type: "output_text",
|
|
5874
|
+
text
|
|
5875
|
+
}]
|
|
5876
|
+
});
|
|
5877
|
+
this.onEvent(event);
|
|
5878
|
+
}
|
|
5879
|
+
recordHistoryEvent(type, payload) {
|
|
5880
|
+
const event = {
|
|
5881
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5882
|
+
type,
|
|
5883
|
+
payload
|
|
5884
|
+
};
|
|
5885
|
+
this.historyEvents.push(event);
|
|
5886
|
+
return event;
|
|
5887
|
+
}
|
|
5888
|
+
};
|
|
5889
|
+
|
|
5387
5890
|
// src/managers/relay-tools.ts
|
|
5388
5891
|
import { createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
|
|
5389
5892
|
import { z } from "zod";
|
|
@@ -6299,7 +6802,8 @@ var ChatService = class {
|
|
|
6299
6802
|
codexAvailable: isCodexAvailable()
|
|
6300
6803
|
});
|
|
6301
6804
|
} else {
|
|
6302
|
-
|
|
6805
|
+
const CodexProviderCtor = ENGINE_ENV.CODEX_ASP_ENABLED ? CodexAspManager : CodexManager;
|
|
6806
|
+
provider = new CodexProviderCtor({
|
|
6303
6807
|
workingDirectory: this.workingDirectory,
|
|
6304
6808
|
initialSessionId: persisted.providerSessionId,
|
|
6305
6809
|
onSaveSessionId: saveSession,
|
|
@@ -6805,7 +7309,7 @@ var PlanService = class {
|
|
|
6805
7309
|
var planService = new PlanService();
|
|
6806
7310
|
|
|
6807
7311
|
// src/services/warm-hooks-service.ts
|
|
6808
|
-
import { spawn } from "child_process";
|
|
7312
|
+
import { spawn as spawn2 } from "child_process";
|
|
6809
7313
|
import { readFile as readFile12 } from "fs/promises";
|
|
6810
7314
|
import { existsSync as existsSync8 } from "fs";
|
|
6811
7315
|
import { join as join18 } from "path";
|
|
@@ -6973,7 +7477,7 @@ async function executeHookScriptStreaming(params) {
|
|
|
6973
7477
|
params.onChunk(`$ ${params.label}
|
|
6974
7478
|
`);
|
|
6975
7479
|
return new Promise((resolve3) => {
|
|
6976
|
-
const proc =
|
|
7480
|
+
const proc = spawn2("bash", ["-lc", params.content], {
|
|
6977
7481
|
cwd: params.cwd,
|
|
6978
7482
|
env: process.env,
|
|
6979
7483
|
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.214",
|
|
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",
|