replicas-engine 0.1.325 → 0.1.327
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 +165 -23
- package/package.json +1 -1
package/dist/src/index.js
CHANGED
|
@@ -287,7 +287,7 @@ var WORKSPACE_SIZES = ["small", "large"];
|
|
|
287
287
|
var INVALID_WORKSPACE_SIZE_ERROR = `Invalid size: must be one of ${WORKSPACE_SIZES.join(", ")}`;
|
|
288
288
|
|
|
289
289
|
// ../shared/src/e2b.ts
|
|
290
|
-
var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-06-
|
|
290
|
+
var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-06-19-v1";
|
|
291
291
|
|
|
292
292
|
// ../shared/src/runtime-env.ts
|
|
293
293
|
function parsePosixEnvFile(content) {
|
|
@@ -2034,6 +2034,75 @@ function parseReplicasConfigString(content, filename) {
|
|
|
2034
2034
|
return parseReplicasConfig(parsed, filename);
|
|
2035
2035
|
}
|
|
2036
2036
|
|
|
2037
|
+
// ../shared/src/errors.ts
|
|
2038
|
+
var TRANSIENT_NETWORK_ERROR_PATTERNS = [
|
|
2039
|
+
/socket connection was closed unexpectedly/,
|
|
2040
|
+
/fetch failed/,
|
|
2041
|
+
/network error/,
|
|
2042
|
+
/network request failed/,
|
|
2043
|
+
/econnreset/,
|
|
2044
|
+
/econnrefused/,
|
|
2045
|
+
/etimedout/,
|
|
2046
|
+
/enotfound/,
|
|
2047
|
+
/eai_again/,
|
|
2048
|
+
/und_err_socket/,
|
|
2049
|
+
/und_err_connect_timeout/,
|
|
2050
|
+
/headers timeout/,
|
|
2051
|
+
/body timeout/,
|
|
2052
|
+
/connection reset/,
|
|
2053
|
+
/connection closed/,
|
|
2054
|
+
/closed unexpectedly/
|
|
2055
|
+
];
|
|
2056
|
+
var HTTP_CONTEXT_PATTERN = /(api error|request|response|status|http)/;
|
|
2057
|
+
var HTTP_STATUS_PATTERN = /(^|[^0-9])([1-5][0-9]{2})(?=$|[^0-9])/g;
|
|
2058
|
+
function extractErrorText(error) {
|
|
2059
|
+
const parts = [];
|
|
2060
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2061
|
+
const collect = (value) => {
|
|
2062
|
+
if (value === null || value === void 0 || seen.has(value)) return;
|
|
2063
|
+
seen.add(value);
|
|
2064
|
+
if (typeof value === "string") {
|
|
2065
|
+
parts.push(value);
|
|
2066
|
+
return;
|
|
2067
|
+
}
|
|
2068
|
+
if (value instanceof Error) {
|
|
2069
|
+
parts.push(value.name, value.message);
|
|
2070
|
+
collect(value.cause);
|
|
2071
|
+
return;
|
|
2072
|
+
}
|
|
2073
|
+
if (typeof value === "object") {
|
|
2074
|
+
const record = value;
|
|
2075
|
+
for (const key of ["name", "message", "code", "error", "cause"]) {
|
|
2076
|
+
collect(record[key]);
|
|
2077
|
+
}
|
|
2078
|
+
const errors = record.errors;
|
|
2079
|
+
if (Array.isArray(errors)) {
|
|
2080
|
+
for (const err of errors) collect(err);
|
|
2081
|
+
}
|
|
2082
|
+
return;
|
|
2083
|
+
}
|
|
2084
|
+
parts.push(String(value));
|
|
2085
|
+
};
|
|
2086
|
+
collect(error);
|
|
2087
|
+
return parts.filter(Boolean).join("\n");
|
|
2088
|
+
}
|
|
2089
|
+
function isTransientErrorText(text, options = {}) {
|
|
2090
|
+
const normalized = text.toLowerCase();
|
|
2091
|
+
if (!normalized) return false;
|
|
2092
|
+
if (TRANSIENT_NETWORK_ERROR_PATTERNS.some((pattern) => pattern.test(normalized))) return true;
|
|
2093
|
+
if (options.includeRateLimit && /rate limit/.test(normalized)) return true;
|
|
2094
|
+
if (options.extraPatterns?.some((pattern) => pattern.test(normalized))) return true;
|
|
2095
|
+
const httpStatuses = new Set(options.httpStatuses ?? []);
|
|
2096
|
+
const httpStatusClasses = new Set(options.httpStatusClasses ?? []);
|
|
2097
|
+
if (httpStatuses.size === 0 && httpStatusClasses.size === 0) return false;
|
|
2098
|
+
if (options.requireHttpContext !== false && !HTTP_CONTEXT_PATTERN.test(normalized)) return false;
|
|
2099
|
+
for (const match of normalized.matchAll(HTTP_STATUS_PATTERN)) {
|
|
2100
|
+
const status = Number(match[2]);
|
|
2101
|
+
if (httpStatuses.has(status) || httpStatusClasses.has(Math.floor(status / 100))) return true;
|
|
2102
|
+
}
|
|
2103
|
+
return false;
|
|
2104
|
+
}
|
|
2105
|
+
|
|
2037
2106
|
// ../shared/src/claude-auth.ts
|
|
2038
2107
|
function isClaudeAuthErrorText(text) {
|
|
2039
2108
|
const lower = text.toLowerCase();
|
|
@@ -6220,6 +6289,16 @@ var ClaudeAuthError = class extends Error {
|
|
|
6220
6289
|
this.name = "ClaudeAuthError";
|
|
6221
6290
|
}
|
|
6222
6291
|
};
|
|
6292
|
+
var ClaudeTransientTurnError = class extends Error {
|
|
6293
|
+
constructor(message) {
|
|
6294
|
+
super(message);
|
|
6295
|
+
this.name = "ClaudeTransientTurnError";
|
|
6296
|
+
}
|
|
6297
|
+
};
|
|
6298
|
+
var MAX_AUTH_RETRIES = 2;
|
|
6299
|
+
var MAX_TRANSIENT_RETRIES = 2;
|
|
6300
|
+
var TRANSIENT_RETRY_DELAYS_MS = [1e3, 2500];
|
|
6301
|
+
var CLAUDE_TRANSIENT_HTTP_STATUSES = [408, 500, 502, 503, 504, 529];
|
|
6223
6302
|
var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
6224
6303
|
historyFile;
|
|
6225
6304
|
sessionId = null;
|
|
@@ -6384,35 +6463,52 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
6384
6463
|
};
|
|
6385
6464
|
}
|
|
6386
6465
|
async processMessageInternal(request) {
|
|
6387
|
-
const MAX_AUTH_RETRIES = 2;
|
|
6388
6466
|
let lastError;
|
|
6389
6467
|
let authRetryExhausted = false;
|
|
6468
|
+
let attempt = 0;
|
|
6469
|
+
let authRetries = 0;
|
|
6470
|
+
let transientRetries = 0;
|
|
6390
6471
|
try {
|
|
6391
|
-
|
|
6472
|
+
while (true) {
|
|
6392
6473
|
try {
|
|
6393
6474
|
await this.executeQuery(request, { skipUserMessageRecord: attempt > 0 });
|
|
6394
6475
|
return;
|
|
6395
6476
|
} catch (error) {
|
|
6396
6477
|
lastError = error;
|
|
6397
|
-
if (
|
|
6398
|
-
|
|
6399
|
-
|
|
6400
|
-
|
|
6401
|
-
|
|
6402
|
-
|
|
6478
|
+
if (_ClaudeManager.isAuthError(error)) {
|
|
6479
|
+
if (authRetries >= MAX_AUTH_RETRIES) {
|
|
6480
|
+
authRetryExhausted = true;
|
|
6481
|
+
throw error;
|
|
6482
|
+
}
|
|
6483
|
+
authRetries++;
|
|
6484
|
+
console.error(
|
|
6485
|
+
`[ClaudeManager] Auth failure detected (attempt ${authRetries}/${MAX_AUTH_RETRIES}), refreshing credentials and retrying...`,
|
|
6486
|
+
error
|
|
6487
|
+
);
|
|
6488
|
+
this.setAuthRetrying(true);
|
|
6489
|
+
const refreshed = await claudeTokenManager.fetchFreshCredentials(
|
|
6490
|
+
error instanceof Error ? error.message : String(error)
|
|
6491
|
+
);
|
|
6492
|
+
if (!refreshed) {
|
|
6493
|
+
authRetryExhausted = true;
|
|
6494
|
+
throw error;
|
|
6495
|
+
}
|
|
6496
|
+
attempt++;
|
|
6497
|
+
continue;
|
|
6403
6498
|
}
|
|
6404
|
-
|
|
6405
|
-
|
|
6406
|
-
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
|
|
6410
|
-
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6499
|
+
if (_ClaudeManager.isTransientTurnError(error) && transientRetries < MAX_TRANSIENT_RETRIES) {
|
|
6500
|
+
transientRetries++;
|
|
6501
|
+
const delayMs = TRANSIENT_RETRY_DELAYS_MS[transientRetries - 1] ?? TRANSIENT_RETRY_DELAYS_MS[TRANSIENT_RETRY_DELAYS_MS.length - 1];
|
|
6502
|
+
console.warn(
|
|
6503
|
+
`[ClaudeManager] Transient turn failure detected (attempt ${transientRetries}/${MAX_TRANSIENT_RETRIES}), retrying in ${delayMs}ms...`,
|
|
6504
|
+
error
|
|
6505
|
+
);
|
|
6506
|
+
await this.tearDownSession();
|
|
6507
|
+
await new Promise((resolve4) => setTimeout(resolve4, delayMs));
|
|
6508
|
+
attempt++;
|
|
6509
|
+
continue;
|
|
6415
6510
|
}
|
|
6511
|
+
throw error;
|
|
6416
6512
|
}
|
|
6417
6513
|
}
|
|
6418
6514
|
} finally {
|
|
@@ -6526,7 +6622,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
6526
6622
|
return;
|
|
6527
6623
|
}
|
|
6528
6624
|
await new Promise((resolve4, reject) => {
|
|
6529
|
-
this.pendingTurn = { resolve: resolve4, reject };
|
|
6625
|
+
this.pendingTurn = { resolve: resolve4, reject, sawActivity: false };
|
|
6530
6626
|
promptStream.push(userMessage);
|
|
6531
6627
|
});
|
|
6532
6628
|
}
|
|
@@ -6659,11 +6755,13 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
6659
6755
|
async runSessionLoop(response) {
|
|
6660
6756
|
const linearSessionId = ENGINE_ENV.LINEAR_SESSION_ID;
|
|
6661
6757
|
const iterator = response[Symbol.asyncIterator]();
|
|
6758
|
+
let loopError = null;
|
|
6662
6759
|
try {
|
|
6663
6760
|
while (true) {
|
|
6664
6761
|
const next = await iterator.next();
|
|
6665
6762
|
if (next.done) break;
|
|
6666
6763
|
const msg = next.value;
|
|
6764
|
+
if (!msg) break;
|
|
6667
6765
|
const authErrorMessage = _ClaudeManager.detectAuthErrorInMessage(msg);
|
|
6668
6766
|
if (authErrorMessage) {
|
|
6669
6767
|
this.failPendingTurn(new ClaudeAuthError(authErrorMessage));
|
|
@@ -6674,7 +6772,23 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
6674
6772
|
}
|
|
6675
6773
|
return;
|
|
6676
6774
|
}
|
|
6775
|
+
const transientErrorMessage = _ClaudeManager.detectTransientTurnErrorInMessage(
|
|
6776
|
+
msg,
|
|
6777
|
+
this.pendingTurn?.sawActivity ?? false
|
|
6778
|
+
);
|
|
6779
|
+
if (transientErrorMessage) {
|
|
6780
|
+
this.failPendingTurn(new ClaudeTransientTurnError(transientErrorMessage));
|
|
6781
|
+
try {
|
|
6782
|
+
response.close();
|
|
6783
|
+
} catch (err) {
|
|
6784
|
+
console.warn("[ClaudeManager] query.close() during transient failure failed:", err);
|
|
6785
|
+
}
|
|
6786
|
+
return;
|
|
6787
|
+
}
|
|
6677
6788
|
this.setAuthRetrying(false);
|
|
6789
|
+
if (this.pendingTurn && _ClaudeManager.isTurnActivity(msg)) {
|
|
6790
|
+
this.pendingTurn.sawActivity = true;
|
|
6791
|
+
}
|
|
6678
6792
|
await this.handleMessage(msg);
|
|
6679
6793
|
_ClaudeManager.updateBackgroundTaskState(msg, this.activeBackgroundTasks);
|
|
6680
6794
|
if (linearSessionId && this.sessionLinearForwarder) {
|
|
@@ -6687,9 +6801,16 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
6687
6801
|
this.resolvePendingTurn();
|
|
6688
6802
|
}
|
|
6689
6803
|
}
|
|
6804
|
+
} catch (error) {
|
|
6805
|
+
loopError = error;
|
|
6806
|
+
if (!_ClaudeManager.isTransientTurnError(error)) {
|
|
6807
|
+
console.error("[ClaudeManager] Session loop crashed:", error);
|
|
6808
|
+
}
|
|
6690
6809
|
} finally {
|
|
6691
6810
|
this.sessionLinearForwarder?.flushThoughtAsResponse();
|
|
6692
|
-
|
|
6811
|
+
const pending = this.pendingTurn;
|
|
6812
|
+
const pendingError = loopError ? pending?.sawActivity && _ClaudeManager.isTransientTurnError(loopError) ? new Error("Claude session ended unexpectedly") : loopError : pending && !pending.sawActivity ? new ClaudeTransientTurnError("Claude session ended unexpectedly before producing a response") : new Error("Claude session ended unexpectedly");
|
|
6813
|
+
this.failPendingTurn(pendingError);
|
|
6693
6814
|
if (this.activeQuery === response) {
|
|
6694
6815
|
this.clearSessionState();
|
|
6695
6816
|
}
|
|
@@ -6803,6 +6924,27 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
6803
6924
|
if (error instanceof ClaudeAuthError) return true;
|
|
6804
6925
|
return isClaudeAuthErrorText(error instanceof Error ? error.message : String(error));
|
|
6805
6926
|
}
|
|
6927
|
+
static isTransientTurnError(error) {
|
|
6928
|
+
if (error instanceof ClaudeTransientTurnError) return true;
|
|
6929
|
+
return _ClaudeManager.isTransientTurnErrorText(extractErrorText(error));
|
|
6930
|
+
}
|
|
6931
|
+
static isTransientTurnErrorText(text) {
|
|
6932
|
+
return isTransientErrorText(text, { httpStatuses: CLAUDE_TRANSIENT_HTTP_STATUSES });
|
|
6933
|
+
}
|
|
6934
|
+
static detectTransientTurnErrorInMessage(message, sawActivity) {
|
|
6935
|
+
if (sawActivity) return null;
|
|
6936
|
+
if (message.type === "assistant" && "error" in message && typeof message.error === "string") {
|
|
6937
|
+
return _ClaudeManager.isTransientTurnErrorText(message.error) ? message.error : null;
|
|
6938
|
+
}
|
|
6939
|
+
if (message.type === "result" && message.is_error) {
|
|
6940
|
+
const text = message.subtype === "success" ? message.result : message.errors.join("\n");
|
|
6941
|
+
return _ClaudeManager.isTransientTurnErrorText(text) ? text : null;
|
|
6942
|
+
}
|
|
6943
|
+
return null;
|
|
6944
|
+
}
|
|
6945
|
+
static isTurnActivity(message) {
|
|
6946
|
+
return message.type === "assistant" || message.type === "stream_event";
|
|
6947
|
+
}
|
|
6806
6948
|
// Done at the message-stream layer (rather than letting the failure flow
|
|
6807
6949
|
// downstream as a normal result) so we can suppress emission before the
|
|
6808
6950
|
// dashboard renders the raw 401 to the user.
|
|
@@ -7149,7 +7291,7 @@ var AspClient = class {
|
|
|
7149
7291
|
// src/managers/codex-asp/app-server-process.ts
|
|
7150
7292
|
var DEFAULT_CODEX_BINARY = "codex";
|
|
7151
7293
|
var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
|
|
7152
|
-
var ENGINE_PACKAGE_VERSION = "0.1.
|
|
7294
|
+
var ENGINE_PACKAGE_VERSION = "0.1.327";
|
|
7153
7295
|
var INITIALIZE_METHOD = "initialize";
|
|
7154
7296
|
var INITIALIZED_NOTIFICATION = "initialized";
|
|
7155
7297
|
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|