replicas-engine 0.1.222 → 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 +130 -65
- 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
|
|
@@ -555,22 +556,19 @@ Docker is pre-installed in Replicas workspaces, but the daemon does **not** auto
|
|
|
555
556
|
|
|
556
557
|
\`\`\`bash
|
|
557
558
|
sudo service docker start
|
|
559
|
+
until docker info >/dev/null 2>&1; do sleep 0.2; done
|
|
558
560
|
\`\`\`
|
|
559
561
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
\`\`\`bash
|
|
563
|
-
docker info
|
|
564
|
-
\`\`\`
|
|
562
|
+
\`service docker start\` returns before the socket is accepting connections, so immediate commands may fail without the poll.
|
|
565
563
|
|
|
566
564
|
## Important Notes
|
|
567
565
|
|
|
568
566
|
- **Start once per session.** The daemon stays running until the workspace shuts down. You do not need to restart it between commands.
|
|
569
567
|
- **Check before starting.** If you are unsure whether the daemon is already running, check first to avoid an unnecessary restart:
|
|
570
568
|
\`\`\`bash
|
|
571
|
-
docker info
|
|
569
|
+
docker info >/dev/null 2>&1 || { sudo service docker start && until docker info >/dev/null 2>&1; do sleep 0.2; done; }
|
|
572
570
|
\`\`\`
|
|
573
|
-
- **Sudo is required
|
|
571
|
+
- **Sudo is only required for starting the daemon.** The workspace user is in the \`docker\` group, so regular \`docker\` commands work without sudo.
|
|
574
572
|
`;
|
|
575
573
|
var DOCKER_ABILITY = {
|
|
576
574
|
label: "Docker",
|
|
@@ -1762,8 +1760,14 @@ function parseReplicasConfigString(content, filename) {
|
|
|
1762
1760
|
return parseReplicasConfig(parsed, filename);
|
|
1763
1761
|
}
|
|
1764
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
|
+
|
|
1765
1769
|
// ../shared/src/engine/environment.ts
|
|
1766
|
-
var DAYTONA_SNAPSHOT_ID = "
|
|
1770
|
+
var DAYTONA_SNAPSHOT_ID = "28-05-2026-royal-york-v1";
|
|
1767
1771
|
|
|
1768
1772
|
// ../shared/src/engine/types.ts
|
|
1769
1773
|
var DEFAULT_CHAT_TITLES = {
|
|
@@ -4529,10 +4533,15 @@ var CodingAgentManager = class {
|
|
|
4529
4533
|
setCompacting(active) {
|
|
4530
4534
|
if (this.compacting === active) return;
|
|
4531
4535
|
this.compacting = active;
|
|
4536
|
+
this.emitSyntheticEvent(COMPACTION_STATUS_EVENT_TYPE, {
|
|
4537
|
+
state: active ? "in_progress" : "completed"
|
|
4538
|
+
});
|
|
4539
|
+
}
|
|
4540
|
+
emitSyntheticEvent(type, payload) {
|
|
4532
4541
|
this.onEvent({
|
|
4533
4542
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4534
|
-
type
|
|
4535
|
-
payload
|
|
4543
|
+
type,
|
|
4544
|
+
payload
|
|
4536
4545
|
});
|
|
4537
4546
|
}
|
|
4538
4547
|
initializeManager(processMessage) {
|
|
@@ -4895,6 +4904,12 @@ var TOOL_INPUT_HANDLERS = {
|
|
|
4895
4904
|
}
|
|
4896
4905
|
}
|
|
4897
4906
|
};
|
|
4907
|
+
var ClaudeAuthError = class extends Error {
|
|
4908
|
+
constructor(message) {
|
|
4909
|
+
super(message);
|
|
4910
|
+
this.name = "ClaudeAuthError";
|
|
4911
|
+
}
|
|
4912
|
+
};
|
|
4898
4913
|
var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
4899
4914
|
historyFile;
|
|
4900
4915
|
sessionId = null;
|
|
@@ -4908,6 +4923,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
4908
4923
|
disallowedToolsOverride;
|
|
4909
4924
|
/** Active tool-input requests keyed by requestId; resolved when the user selects an option. */
|
|
4910
4925
|
pendingToolInputs = /* @__PURE__ */ new Map();
|
|
4926
|
+
authRetrying = false;
|
|
4911
4927
|
constructor(options) {
|
|
4912
4928
|
super(options);
|
|
4913
4929
|
this.historyFile = options.historyFilePath ?? join13(homedir11(), ".replicas", "claude", "history.jsonl");
|
|
@@ -4942,6 +4958,14 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
4942
4958
|
isAwaitingInput() {
|
|
4943
4959
|
return this.pendingToolInputs.size > 0;
|
|
4944
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
|
+
}
|
|
4945
4969
|
async respondToToolInput(requestId, selectionId) {
|
|
4946
4970
|
const pending = this.pendingToolInputs.get(requestId);
|
|
4947
4971
|
if (!pending) {
|
|
@@ -5018,29 +5042,73 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
5018
5042
|
return result;
|
|
5019
5043
|
};
|
|
5020
5044
|
}
|
|
5021
|
-
/**
|
|
5022
|
-
* Internal method that actually processes the message.
|
|
5023
|
-
* On auth failure, refreshes credentials and retries once.
|
|
5024
|
-
*/
|
|
5025
5045
|
async processMessageInternal(request) {
|
|
5046
|
+
const MAX_AUTH_RETRIES = 2;
|
|
5047
|
+
let lastError;
|
|
5048
|
+
let authRetryExhausted = false;
|
|
5026
5049
|
try {
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
console.warn("[ClaudeManager] Auth failure detected, refreshing credentials and retrying...", error);
|
|
5031
|
-
const refreshed = await claudeTokenManager.fetchFreshCredentials(error instanceof Error ? error.message : String(error));
|
|
5032
|
-
if (refreshed) {
|
|
5033
|
-
await this.executeQuery(request);
|
|
5050
|
+
for (let attempt = 0; attempt <= MAX_AUTH_RETRIES; attempt++) {
|
|
5051
|
+
try {
|
|
5052
|
+
await this.executeQuery(request, { skipUserMessageRecord: attempt > 0 });
|
|
5034
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
|
+
}
|
|
5035
5075
|
}
|
|
5036
5076
|
}
|
|
5037
|
-
|
|
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
|
+
}
|
|
5038
5087
|
}
|
|
5039
5088
|
}
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
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 = {}) {
|
|
5044
5112
|
const {
|
|
5045
5113
|
message,
|
|
5046
5114
|
model,
|
|
@@ -5084,7 +5152,9 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
5084
5152
|
parent_tool_use_id: null,
|
|
5085
5153
|
session_id: this.sessionId ?? ""
|
|
5086
5154
|
};
|
|
5087
|
-
|
|
5155
|
+
if (!options.skipUserMessageRecord) {
|
|
5156
|
+
await this.recordEvent(userMessage);
|
|
5157
|
+
}
|
|
5088
5158
|
const promptStream = new PromptStream();
|
|
5089
5159
|
promptStream.push(userMessage);
|
|
5090
5160
|
this.activePromptStream = promptStream;
|
|
@@ -5136,6 +5206,11 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
5136
5206
|
}
|
|
5137
5207
|
const linearForwarder = new LinearEventForwarder(linearSessionId);
|
|
5138
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
|
+
}
|
|
5139
5214
|
await this.handleMessage(msg);
|
|
5140
5215
|
if (linearSessionId) {
|
|
5141
5216
|
linearForwarder.sendPlan(extractPlanFromClaudeEvent(msg));
|
|
@@ -5153,11 +5228,6 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
5153
5228
|
this.activePromptStream?.close();
|
|
5154
5229
|
this.activePromptStream = null;
|
|
5155
5230
|
this.pendingInterrupt = false;
|
|
5156
|
-
try {
|
|
5157
|
-
await this.onTurnComplete();
|
|
5158
|
-
} catch (error) {
|
|
5159
|
-
console.error("[ClaudeManager] onTurnComplete failed:", error);
|
|
5160
|
-
}
|
|
5161
5231
|
}
|
|
5162
5232
|
}
|
|
5163
5233
|
getContextUsageProvider() {
|
|
@@ -5203,17 +5273,33 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
5203
5273
|
console.warn("[ClaudeManager] Failed to record context usage:", error instanceof Error ? error.message : error);
|
|
5204
5274
|
}
|
|
5205
5275
|
}
|
|
5206
|
-
/**
|
|
5207
|
-
* Determines if an error is an OAuth authentication failure from the Claude SDK.
|
|
5208
|
-
* Known patterns:
|
|
5209
|
-
* - "Not logged in · Please run /login"
|
|
5210
|
-
* - "authentication_failed"
|
|
5211
|
-
* - "unauthorized"
|
|
5212
|
-
*/
|
|
5213
5276
|
static isAuthError(error) {
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
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;
|
|
5217
5303
|
}
|
|
5218
5304
|
async getHistory() {
|
|
5219
5305
|
await this.initialized;
|
|
@@ -5231,34 +5317,12 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
|
|
|
5231
5317
|
console.log(`[ClaudeManager] Restored session ID from persisted state: ${this.sessionId}`);
|
|
5232
5318
|
}
|
|
5233
5319
|
}
|
|
5234
|
-
/**
|
|
5235
|
-
* Checks if an SDK message indicates an OAuth authentication failure.
|
|
5236
|
-
* When detected, triggers a force-refresh of credentials from the monolith.
|
|
5237
|
-
*/
|
|
5238
|
-
async checkForAuthFailure(message) {
|
|
5239
|
-
if (message.type === "assistant" && "error" in message && message.error === "authentication_failed") {
|
|
5240
|
-
console.warn("[ClaudeManager] Detected authentication_failed in assistant message, force-refreshing credentials...");
|
|
5241
|
-
await claudeTokenManager.fetchFreshCredentials();
|
|
5242
|
-
return;
|
|
5243
|
-
}
|
|
5244
|
-
if (message.type === "result" && "is_error" in message && message.is_error && "errors" in message) {
|
|
5245
|
-
const errors = message.errors ?? [];
|
|
5246
|
-
const hasAuthError = errors.some(
|
|
5247
|
-
(err) => err.toLowerCase().includes("authentication") || err.toLowerCase().includes("unauthorized") || err.toLowerCase().includes("not logged in") || err.toLowerCase().includes("login")
|
|
5248
|
-
);
|
|
5249
|
-
if (hasAuthError) {
|
|
5250
|
-
console.warn("[ClaudeManager] Detected auth-related error in result, force-refreshing credentials...");
|
|
5251
|
-
await claudeTokenManager.fetchFreshCredentials();
|
|
5252
|
-
}
|
|
5253
|
-
}
|
|
5254
|
-
}
|
|
5255
5320
|
async handleMessage(message) {
|
|
5256
5321
|
if ("session_id" in message && message.session_id && !this.sessionId) {
|
|
5257
5322
|
this.sessionId = message.session_id;
|
|
5258
5323
|
await this.onSaveSessionId(this.sessionId);
|
|
5259
5324
|
console.log(`[ClaudeManager] Captured and persisted session ID: ${this.sessionId}`);
|
|
5260
5325
|
}
|
|
5261
|
-
await this.checkForAuthFailure(message);
|
|
5262
5326
|
this.trackNativeCompaction(message);
|
|
5263
5327
|
await this.recordEvent(message);
|
|
5264
5328
|
}
|
|
@@ -7902,6 +7966,7 @@ var ChatService = class {
|
|
|
7902
7966
|
processing: chat.provider.isProcessing(),
|
|
7903
7967
|
awaitingInput: chat.provider.isAwaitingInput?.() ?? false,
|
|
7904
7968
|
isCompacting: chat.provider.isCompacting?.() ?? false,
|
|
7969
|
+
isAuthRetrying: chat.provider.isAuthRetrying?.() ?? false,
|
|
7905
7970
|
goal: chat.provider.getGoal?.() ?? null,
|
|
7906
7971
|
parentChatId: chat.persisted.parentChatId
|
|
7907
7972
|
};
|
|
@@ -7965,7 +8030,7 @@ var ChatService = class {
|
|
|
7965
8030
|
}
|
|
7966
8031
|
}).catch(() => {
|
|
7967
8032
|
});
|
|
7968
|
-
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) {
|
|
7969
8034
|
this.publish({
|
|
7970
8035
|
type: "chat.updated",
|
|
7971
8036
|
payload: { chat: this.toSummary(chat) }
|