replicas-engine 0.1.223 → 0.1.224
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 +126 -58
- package/package.json +1 -1
package/dist/src/index.js
CHANGED
|
@@ -38,6 +38,7 @@ var CODEX_ASP_ITEM_ID_PAYLOAD_KEY = "codexAspItemId";
|
|
|
38
38
|
var CODEX_QUOTA_STATUS_EVENT_TYPE = "codex-quota-status";
|
|
39
39
|
var COMPACTION_STATUS_EVENT_TYPE = "compaction-status";
|
|
40
40
|
var CHAT_GOAL_EVENT_TYPE = "chat-goal";
|
|
41
|
+
var AUTH_RETRY_STATUS_EVENT_TYPE = "auth-retry-status";
|
|
41
42
|
var CONTEXT_USAGE_EVENT_TYPE = "context-usage";
|
|
42
43
|
|
|
43
44
|
// ../shared/src/languages.ts
|
|
@@ -1759,8 +1760,14 @@ function parseReplicasConfigString(content, filename) {
|
|
|
1759
1760
|
return parseReplicasConfig(parsed, filename);
|
|
1760
1761
|
}
|
|
1761
1762
|
|
|
1763
|
+
// ../shared/src/claude-auth.ts
|
|
1764
|
+
function isClaudeAuthErrorText(text) {
|
|
1765
|
+
const lower = text.toLowerCase();
|
|
1766
|
+
return lower.includes("failed to authenticate") || lower.includes("authentication_error") || lower.includes("authentication_failed") || lower.includes("authentication failed") || lower.includes("invalid authentication credentials") || lower.includes("not logged in") || lower.includes("please run /login") || lower.includes("401") && lower.includes("authentic");
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1762
1769
|
// ../shared/src/engine/environment.ts
|
|
1763
|
-
var DAYTONA_SNAPSHOT_ID = "
|
|
1770
|
+
var DAYTONA_SNAPSHOT_ID = "28-05-2026-royal-york-v1";
|
|
1764
1771
|
|
|
1765
1772
|
// ../shared/src/engine/types.ts
|
|
1766
1773
|
var DEFAULT_CHAT_TITLES = {
|
|
@@ -4526,10 +4533,15 @@ var CodingAgentManager = class {
|
|
|
4526
4533
|
setCompacting(active) {
|
|
4527
4534
|
if (this.compacting === active) return;
|
|
4528
4535
|
this.compacting = active;
|
|
4536
|
+
this.emitSyntheticEvent(COMPACTION_STATUS_EVENT_TYPE, {
|
|
4537
|
+
state: active ? "in_progress" : "completed"
|
|
4538
|
+
});
|
|
4539
|
+
}
|
|
4540
|
+
emitSyntheticEvent(type, payload) {
|
|
4529
4541
|
this.onEvent({
|
|
4530
4542
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4531
|
-
type
|
|
4532
|
-
payload
|
|
4543
|
+
type,
|
|
4544
|
+
payload
|
|
4533
4545
|
});
|
|
4534
4546
|
}
|
|
4535
4547
|
initializeManager(processMessage) {
|
|
@@ -4892,6 +4904,12 @@ var TOOL_INPUT_HANDLERS = {
|
|
|
4892
4904
|
}
|
|
4893
4905
|
}
|
|
4894
4906
|
};
|
|
4907
|
+
var ClaudeAuthError = class extends Error {
|
|
4908
|
+
constructor(message) {
|
|
4909
|
+
super(message);
|
|
4910
|
+
this.name = "ClaudeAuthError";
|
|
4911
|
+
}
|
|
4912
|
+
};
|
|
4895
4913
|
var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
4896
4914
|
historyFile;
|
|
4897
4915
|
sessionId = null;
|
|
@@ -4905,6 +4923,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
4905
4923
|
disallowedToolsOverride;
|
|
4906
4924
|
/** Active tool-input requests keyed by requestId; resolved when the user selects an option. */
|
|
4907
4925
|
pendingToolInputs = /* @__PURE__ */ new Map();
|
|
4926
|
+
authRetrying = false;
|
|
4908
4927
|
constructor(options) {
|
|
4909
4928
|
super(options);
|
|
4910
4929
|
this.historyFile = options.historyFilePath ?? join13(homedir11(), ".replicas", "claude", "history.jsonl");
|
|
@@ -4939,6 +4958,14 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
4939
4958
|
isAwaitingInput() {
|
|
4940
4959
|
return this.pendingToolInputs.size > 0;
|
|
4941
4960
|
}
|
|
4961
|
+
isAuthRetrying() {
|
|
4962
|
+
return this.authRetrying;
|
|
4963
|
+
}
|
|
4964
|
+
setAuthRetrying(value) {
|
|
4965
|
+
if (this.authRetrying === value) return;
|
|
4966
|
+
this.authRetrying = value;
|
|
4967
|
+
this.emitSyntheticEvent(AUTH_RETRY_STATUS_EVENT_TYPE, { isAuthRetrying: value });
|
|
4968
|
+
}
|
|
4942
4969
|
async respondToToolInput(requestId, selectionId) {
|
|
4943
4970
|
const pending = this.pendingToolInputs.get(requestId);
|
|
4944
4971
|
if (!pending) {
|
|
@@ -5015,29 +5042,73 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
5015
5042
|
return result;
|
|
5016
5043
|
};
|
|
5017
5044
|
}
|
|
5018
|
-
/**
|
|
5019
|
-
* Internal method that actually processes the message.
|
|
5020
|
-
* On auth failure, refreshes credentials and retries once.
|
|
5021
|
-
*/
|
|
5022
5045
|
async processMessageInternal(request) {
|
|
5046
|
+
const MAX_AUTH_RETRIES = 2;
|
|
5047
|
+
let lastError;
|
|
5048
|
+
let authRetryExhausted = false;
|
|
5023
5049
|
try {
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
console.warn("[ClaudeManager] Auth failure detected, refreshing credentials and retrying...", error);
|
|
5028
|
-
const refreshed = await claudeTokenManager.fetchFreshCredentials(error instanceof Error ? error.message : String(error));
|
|
5029
|
-
if (refreshed) {
|
|
5030
|
-
await this.executeQuery(request);
|
|
5050
|
+
for (let attempt = 0; attempt <= MAX_AUTH_RETRIES; attempt++) {
|
|
5051
|
+
try {
|
|
5052
|
+
await this.executeQuery(request, { skipUserMessageRecord: attempt > 0 });
|
|
5031
5053
|
return;
|
|
5054
|
+
} catch (error) {
|
|
5055
|
+
lastError = error;
|
|
5056
|
+
if (!_ClaudeManager.isAuthError(error)) {
|
|
5057
|
+
throw error;
|
|
5058
|
+
}
|
|
5059
|
+
if (attempt === MAX_AUTH_RETRIES) {
|
|
5060
|
+
authRetryExhausted = true;
|
|
5061
|
+
throw error;
|
|
5062
|
+
}
|
|
5063
|
+
console.error(
|
|
5064
|
+
`[ClaudeManager] Auth failure detected (attempt ${attempt + 1}/${MAX_AUTH_RETRIES + 1}), refreshing credentials and retrying...`,
|
|
5065
|
+
error
|
|
5066
|
+
);
|
|
5067
|
+
this.setAuthRetrying(true);
|
|
5068
|
+
const refreshed = await claudeTokenManager.fetchFreshCredentials(
|
|
5069
|
+
error instanceof Error ? error.message : String(error)
|
|
5070
|
+
);
|
|
5071
|
+
if (!refreshed) {
|
|
5072
|
+
authRetryExhausted = true;
|
|
5073
|
+
throw error;
|
|
5074
|
+
}
|
|
5032
5075
|
}
|
|
5033
5076
|
}
|
|
5034
|
-
|
|
5077
|
+
} finally {
|
|
5078
|
+
this.setAuthRetrying(false);
|
|
5079
|
+
if (authRetryExhausted) {
|
|
5080
|
+
await this.emitAuthRetryExhaustedEvent(lastError);
|
|
5081
|
+
}
|
|
5082
|
+
try {
|
|
5083
|
+
await this.onTurnComplete();
|
|
5084
|
+
} catch (error) {
|
|
5085
|
+
console.error("[ClaudeManager] onTurnComplete failed:", error);
|
|
5086
|
+
}
|
|
5035
5087
|
}
|
|
5036
5088
|
}
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5089
|
+
async emitAuthRetryExhaustedEvent(error) {
|
|
5090
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
5091
|
+
const event = {
|
|
5092
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5093
|
+
type: "claude-result",
|
|
5094
|
+
payload: {
|
|
5095
|
+
type: "result",
|
|
5096
|
+
subtype: "error_during_execution",
|
|
5097
|
+
is_error: true,
|
|
5098
|
+
result: "Couldn't authenticate with Claude after multiple attempts. Check your credentials in Settings \u2192 Agents and try again.",
|
|
5099
|
+
errors: [detail],
|
|
5100
|
+
session_id: this.sessionId ?? "",
|
|
5101
|
+
parent_tool_use_id: null
|
|
5102
|
+
}
|
|
5103
|
+
};
|
|
5104
|
+
try {
|
|
5105
|
+
await appendFile4(this.historyFile, JSON.stringify(event) + "\n", "utf-8");
|
|
5106
|
+
} catch (writeError) {
|
|
5107
|
+
console.error("[ClaudeManager] Failed to record auth-retry-exhausted event:", writeError);
|
|
5108
|
+
}
|
|
5109
|
+
this.onEvent(event);
|
|
5110
|
+
}
|
|
5111
|
+
async executeQuery(request, options = {}) {
|
|
5041
5112
|
const {
|
|
5042
5113
|
message,
|
|
5043
5114
|
model,
|
|
@@ -5081,7 +5152,9 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
5081
5152
|
parent_tool_use_id: null,
|
|
5082
5153
|
session_id: this.sessionId ?? ""
|
|
5083
5154
|
};
|
|
5084
|
-
|
|
5155
|
+
if (!options.skipUserMessageRecord) {
|
|
5156
|
+
await this.recordEvent(userMessage);
|
|
5157
|
+
}
|
|
5085
5158
|
const promptStream = new PromptStream();
|
|
5086
5159
|
promptStream.push(userMessage);
|
|
5087
5160
|
this.activePromptStream = promptStream;
|
|
@@ -5133,6 +5206,11 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
5133
5206
|
}
|
|
5134
5207
|
const linearForwarder = new LinearEventForwarder(linearSessionId);
|
|
5135
5208
|
for await (const msg of response) {
|
|
5209
|
+
const authErrorMessage = _ClaudeManager.detectAuthErrorInMessage(msg);
|
|
5210
|
+
if (authErrorMessage) {
|
|
5211
|
+
this.activePromptStream?.close();
|
|
5212
|
+
throw new ClaudeAuthError(authErrorMessage);
|
|
5213
|
+
}
|
|
5136
5214
|
await this.handleMessage(msg);
|
|
5137
5215
|
if (linearSessionId) {
|
|
5138
5216
|
linearForwarder.sendPlan(extractPlanFromClaudeEvent(msg));
|
|
@@ -5150,11 +5228,6 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
5150
5228
|
this.activePromptStream?.close();
|
|
5151
5229
|
this.activePromptStream = null;
|
|
5152
5230
|
this.pendingInterrupt = false;
|
|
5153
|
-
try {
|
|
5154
|
-
await this.onTurnComplete();
|
|
5155
|
-
} catch (error) {
|
|
5156
|
-
console.error("[ClaudeManager] onTurnComplete failed:", error);
|
|
5157
|
-
}
|
|
5158
5231
|
}
|
|
5159
5232
|
}
|
|
5160
5233
|
getContextUsageProvider() {
|
|
@@ -5200,17 +5273,33 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
5200
5273
|
console.warn("[ClaudeManager] Failed to record context usage:", error instanceof Error ? error.message : error);
|
|
5201
5274
|
}
|
|
5202
5275
|
}
|
|
5203
|
-
/**
|
|
5204
|
-
* Determines if an error is an OAuth authentication failure from the Claude SDK.
|
|
5205
|
-
* Known patterns:
|
|
5206
|
-
* - "Not logged in · Please run /login"
|
|
5207
|
-
* - "authentication_failed"
|
|
5208
|
-
* - "unauthorized"
|
|
5209
|
-
*/
|
|
5210
5276
|
static isAuthError(error) {
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
|
|
5277
|
+
if (error instanceof ClaudeAuthError) return true;
|
|
5278
|
+
return isClaudeAuthErrorText(error instanceof Error ? error.message : String(error));
|
|
5279
|
+
}
|
|
5280
|
+
// Done at the message-stream layer (rather than letting the failure flow
|
|
5281
|
+
// downstream as a normal result) so we can suppress emission before the
|
|
5282
|
+
// dashboard renders the raw 401 to the user.
|
|
5283
|
+
static detectAuthErrorInMessage(message) {
|
|
5284
|
+
if (message.type === "assistant" && "error" in message) {
|
|
5285
|
+
const error = message.error;
|
|
5286
|
+
if (typeof error === "string") {
|
|
5287
|
+
const errCode = error.toLowerCase();
|
|
5288
|
+
if (errCode === "authentication_failed" || errCode === "authentication_error") {
|
|
5289
|
+
return error;
|
|
5290
|
+
}
|
|
5291
|
+
}
|
|
5292
|
+
}
|
|
5293
|
+
if (message.type === "result" && message.is_error) {
|
|
5294
|
+
if (message.subtype === "success") {
|
|
5295
|
+
if (isClaudeAuthErrorText(message.result)) return message.result;
|
|
5296
|
+
} else {
|
|
5297
|
+
for (const err of message.errors) {
|
|
5298
|
+
if (isClaudeAuthErrorText(err)) return err;
|
|
5299
|
+
}
|
|
5300
|
+
}
|
|
5301
|
+
}
|
|
5302
|
+
return null;
|
|
5214
5303
|
}
|
|
5215
5304
|
async getHistory() {
|
|
5216
5305
|
await this.initialized;
|
|
@@ -5228,34 +5317,12 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
5228
5317
|
console.log(`[ClaudeManager] Restored session ID from persisted state: ${this.sessionId}`);
|
|
5229
5318
|
}
|
|
5230
5319
|
}
|
|
5231
|
-
/**
|
|
5232
|
-
* Checks if an SDK message indicates an OAuth authentication failure.
|
|
5233
|
-
* When detected, triggers a force-refresh of credentials from the monolith.
|
|
5234
|
-
*/
|
|
5235
|
-
async checkForAuthFailure(message) {
|
|
5236
|
-
if (message.type === "assistant" && "error" in message && message.error === "authentication_failed") {
|
|
5237
|
-
console.warn("[ClaudeManager] Detected authentication_failed in assistant message, force-refreshing credentials...");
|
|
5238
|
-
await claudeTokenManager.fetchFreshCredentials();
|
|
5239
|
-
return;
|
|
5240
|
-
}
|
|
5241
|
-
if (message.type === "result" && "is_error" in message && message.is_error && "errors" in message) {
|
|
5242
|
-
const errors = message.errors ?? [];
|
|
5243
|
-
const hasAuthError = errors.some(
|
|
5244
|
-
(err) => err.toLowerCase().includes("authentication") || err.toLowerCase().includes("unauthorized") || err.toLowerCase().includes("not logged in") || err.toLowerCase().includes("login")
|
|
5245
|
-
);
|
|
5246
|
-
if (hasAuthError) {
|
|
5247
|
-
console.warn("[ClaudeManager] Detected auth-related error in result, force-refreshing credentials...");
|
|
5248
|
-
await claudeTokenManager.fetchFreshCredentials();
|
|
5249
|
-
}
|
|
5250
|
-
}
|
|
5251
|
-
}
|
|
5252
5320
|
async handleMessage(message) {
|
|
5253
5321
|
if ("session_id" in message && message.session_id && !this.sessionId) {
|
|
5254
5322
|
this.sessionId = message.session_id;
|
|
5255
5323
|
await this.onSaveSessionId(this.sessionId);
|
|
5256
5324
|
console.log(`[ClaudeManager] Captured and persisted session ID: ${this.sessionId}`);
|
|
5257
5325
|
}
|
|
5258
|
-
await this.checkForAuthFailure(message);
|
|
5259
5326
|
this.trackNativeCompaction(message);
|
|
5260
5327
|
await this.recordEvent(message);
|
|
5261
5328
|
}
|
|
@@ -7899,6 +7966,7 @@ var ChatService = class {
|
|
|
7899
7966
|
processing: chat.provider.isProcessing(),
|
|
7900
7967
|
awaitingInput: chat.provider.isAwaitingInput?.() ?? false,
|
|
7901
7968
|
isCompacting: chat.provider.isCompacting?.() ?? false,
|
|
7969
|
+
isAuthRetrying: chat.provider.isAuthRetrying?.() ?? false,
|
|
7902
7970
|
goal: chat.provider.getGoal?.() ?? null,
|
|
7903
7971
|
parentChatId: chat.persisted.parentChatId
|
|
7904
7972
|
};
|
|
@@ -7962,7 +8030,7 @@ var ChatService = class {
|
|
|
7962
8030
|
}
|
|
7963
8031
|
}).catch(() => {
|
|
7964
8032
|
});
|
|
7965
|
-
if (event.type === "replicas-tool-input-request" || event.type === "replicas-tool-input-resolved" || event.type === "compaction-status" || event.type === CHAT_GOAL_EVENT_TYPE) {
|
|
8033
|
+
if (event.type === "replicas-tool-input-request" || event.type === "replicas-tool-input-resolved" || event.type === "compaction-status" || event.type === AUTH_RETRY_STATUS_EVENT_TYPE || event.type === CHAT_GOAL_EVENT_TYPE) {
|
|
7966
8034
|
this.publish({
|
|
7967
8035
|
type: "chat.updated",
|
|
7968
8036
|
payload: { chat: this.toSummary(chat) }
|