replicas-engine 0.1.236 → 0.1.237

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 +307 -100
  2. package/package.json +1 -1
package/dist/src/index.js CHANGED
@@ -1779,11 +1779,11 @@ function parseReplicasConfigString(content, filename) {
1779
1779
  // ../shared/src/claude-auth.ts
1780
1780
  function isClaudeAuthErrorText(text) {
1781
1781
  const lower = text.toLowerCase();
1782
- 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");
1782
+ 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("credit balance is too low") || lower.includes("401") && lower.includes("authentic");
1783
1783
  }
1784
1784
 
1785
1785
  // ../shared/src/engine/environment.ts
1786
- var DAYTONA_SNAPSHOT_ID = "29-05-2026-royal-york-v7";
1786
+ var DAYTONA_SNAPSHOT_ID = "29-05-2026-royal-york-v8";
1787
1787
  var DESKTOP_NOVNC_PORT = 6080;
1788
1788
 
1789
1789
  // ../shared/src/engine/types.ts
@@ -1905,6 +1905,53 @@ var AUDIT_LOG_ACTION = {
1905
1905
  };
1906
1906
  var AUDIT_LOG_ACTIONS = Object.values(AUDIT_LOG_ACTION);
1907
1907
 
1908
+ // ../shared/src/display-message/types.ts
1909
+ var BACKGROUND_TASK_SUBTYPES = /* @__PURE__ */ new Set([
1910
+ "task_started",
1911
+ "task_progress",
1912
+ "task_updated",
1913
+ "task_notification"
1914
+ ]);
1915
+ function isBackgroundTaskSubtype(subtype) {
1916
+ return typeof subtype === "string" && BACKGROUND_TASK_SUBTYPES.has(subtype);
1917
+ }
1918
+ function optionalString(value) {
1919
+ return typeof value === "string" ? value : void 0;
1920
+ }
1921
+ function coerceBackgroundTaskPayload(payload) {
1922
+ if (!isRecord(payload)) return null;
1923
+ const subtype = payload.subtype;
1924
+ if (!isBackgroundTaskSubtype(subtype)) return null;
1925
+ const taskId = payload.task_id;
1926
+ if (typeof taskId !== "string" || !taskId) return null;
1927
+ const patch = isRecord(payload.patch) ? {
1928
+ status: optionalString(payload.patch.status),
1929
+ description: optionalString(payload.patch.description),
1930
+ error: optionalString(payload.patch.error)
1931
+ } : void 0;
1932
+ return {
1933
+ subtype,
1934
+ taskId,
1935
+ description: optionalString(payload.description),
1936
+ summary: optionalString(payload.summary),
1937
+ outputFile: optionalString(payload.output_file),
1938
+ status: optionalString(payload.status),
1939
+ patch
1940
+ };
1941
+ }
1942
+ function normalizeBackgroundTaskStatus(status) {
1943
+ if (status === "completed" || status === "failed" || status === "stopped") {
1944
+ return status;
1945
+ }
1946
+ if (status === "killed") {
1947
+ return "stopped";
1948
+ }
1949
+ return "in_progress";
1950
+ }
1951
+ function isTerminalBackgroundTaskStatus(status) {
1952
+ return normalizeBackgroundTaskStatus(status) !== "in_progress";
1953
+ }
1954
+
1908
1955
  // ../shared/src/agent-event-utils.ts
1909
1956
  function getUserMessage(event) {
1910
1957
  return event.type === "event_msg" && event.payload.type === "user_message" && typeof event.payload.message === "string" ? event.payload.message : null;
@@ -3282,15 +3329,15 @@ function withPreview(stored) {
3282
3329
  function isObject(value) {
3283
3330
  return typeof value === "object" && value !== null;
3284
3331
  }
3285
- function optionalString(value) {
3332
+ function optionalString2(value) {
3286
3333
  return typeof value === "string" ? value : void 0;
3287
3334
  }
3288
3335
  function normalizeStored(raw) {
3289
3336
  if (!isObject(raw)) return null;
3290
3337
  if (typeof raw.output !== "string" || typeof raw.exitCode !== "number") return null;
3291
3338
  const hookType = raw.hookType === "environment" ? "environment" : "repository";
3292
- const repoNameField = optionalString(raw.repoName);
3293
- const hookName = optionalString(raw.hookName) ?? repoNameField ?? "";
3339
+ const repoNameField = optionalString2(raw.repoName);
3340
+ const hookName = optionalString2(raw.hookName) ?? repoNameField ?? "";
3294
3341
  const repoName = repoNameField ?? hookName;
3295
3342
  const hookCommands = Array.isArray(raw.hookCommands) ? raw.hookCommands.filter((c) => typeof c === "string") : [];
3296
3343
  return {
@@ -3301,7 +3348,7 @@ function normalizeStored(raw) {
3301
3348
  output: raw.output,
3302
3349
  exitCode: raw.exitCode,
3303
3350
  timedOut: typeof raw.timedOut === "boolean" ? raw.timedOut : false,
3304
- executedAt: optionalString(raw.executedAt) ?? ""
3351
+ executedAt: optionalString2(raw.executedAt) ?? ""
3305
3352
  };
3306
3353
  }
3307
3354
  var StartHookLogsService = class {
@@ -5144,7 +5191,14 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
5144
5191
  sessionId = null;
5145
5192
  activeQuery = null;
5146
5193
  activePromptStream = null;
5194
+ activeSessionSignature = null;
5195
+ activeSessionModel = null;
5196
+ activeSessionPermissionMode = null;
5197
+ sessionLoop = null;
5198
+ sessionLinearForwarder = null;
5199
+ pendingTurn = null;
5147
5200
  pendingInterrupt = false;
5201
+ activeBackgroundTasks = /* @__PURE__ */ new Set();
5148
5202
  systemPromptOverride;
5149
5203
  toolsOverride;
5150
5204
  mcpServersConfig;
@@ -5165,7 +5219,6 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
5165
5219
  }
5166
5220
  async interruptActiveTurn() {
5167
5221
  this.pendingInterrupt = true;
5168
- this.activePromptStream?.close();
5169
5222
  if (this.activeQuery) {
5170
5223
  await this.activeQuery.interrupt();
5171
5224
  }
@@ -5347,117 +5400,271 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
5347
5400
  thinkingLevel,
5348
5401
  enableInteractiveTools
5349
5402
  } = request;
5350
- const linearSessionId = ENGINE_ENV.LINEAR_SESSION_ID;
5351
5403
  if (!message || !message.trim()) {
5352
5404
  throw new Error("Message cannot be empty");
5353
5405
  }
5354
5406
  await this.initialized;
5355
- try {
5356
- const content = [
5357
- {
5358
- type: "text",
5359
- text: message
5407
+ this.pendingInterrupt = false;
5408
+ const content = [
5409
+ {
5410
+ type: "text",
5411
+ text: message
5412
+ }
5413
+ ];
5414
+ if (images && images.length > 0) {
5415
+ const normalizedImages = await normalizeImages(images);
5416
+ for (const image of normalizedImages) {
5417
+ content.push({
5418
+ type: "image",
5419
+ source: {
5420
+ type: "base64",
5421
+ media_type: image.source.media_type,
5422
+ data: image.source.data
5423
+ }
5424
+ });
5425
+ }
5426
+ }
5427
+ const userMessage = {
5428
+ type: "user",
5429
+ message: {
5430
+ role: "user",
5431
+ content
5432
+ },
5433
+ parent_tool_use_id: null,
5434
+ session_id: this.sessionId ?? ""
5435
+ };
5436
+ if (!options.skipUserMessageRecord) {
5437
+ await this.recordEvent(userMessage);
5438
+ }
5439
+ const combinedInstructions = this.buildCombinedInstructions(customInstructions);
5440
+ const resolvedModel = normalizeClaudeModel(model) || CLAUDE_OPUS_1M_MODEL;
5441
+ const resolvedPermissionMode = permissionMode === "read" ? "plan" : "bypassPermissions";
5442
+ const signature = {
5443
+ combinedInstructions,
5444
+ thinkingLevel,
5445
+ // enableInteractiveTools only matters when permissionMode is 'read'; the
5446
+ // session signature tracks the effective flag so a permissionMode change
5447
+ // can hot-swap via setPermissionMode without restarting.
5448
+ enableInteractiveTools: Boolean(enableInteractiveTools)
5449
+ };
5450
+ await this.ensureSession({
5451
+ signature,
5452
+ combinedInstructions,
5453
+ resolvedModel,
5454
+ resolvedPermissionMode,
5455
+ enableInteractiveTools: signature.enableInteractiveTools,
5456
+ thinkingLevel
5457
+ });
5458
+ const promptStream = this.activePromptStream;
5459
+ const activeQuery = this.activeQuery;
5460
+ if (!promptStream || !activeQuery) {
5461
+ throw new Error("Claude session unavailable after ensureSession");
5462
+ }
5463
+ if (this.pendingInterrupt) {
5464
+ this.pendingInterrupt = false;
5465
+ return;
5466
+ }
5467
+ await new Promise((resolve3, reject) => {
5468
+ this.pendingTurn = { resolve: resolve3, reject };
5469
+ promptStream.push(userMessage);
5470
+ });
5471
+ }
5472
+ async ensureSession(args) {
5473
+ const {
5474
+ signature,
5475
+ combinedInstructions,
5476
+ resolvedModel,
5477
+ resolvedPermissionMode,
5478
+ enableInteractiveTools,
5479
+ thinkingLevel
5480
+ } = args;
5481
+ if (this.activeQuery && this.activeSessionSignature && this.sessionSignaturesMatch(this.activeSessionSignature, signature)) {
5482
+ if (this.activeSessionModel !== resolvedModel) {
5483
+ try {
5484
+ await this.activeQuery.setModel(resolvedModel);
5485
+ this.activeSessionModel = resolvedModel;
5486
+ } catch (err) {
5487
+ console.warn("[ClaudeManager] setModel failed; recreating session:", err);
5488
+ await this.tearDownSession();
5360
5489
  }
5361
- ];
5362
- if (images && images.length > 0) {
5363
- const normalizedImages = await normalizeImages(images);
5364
- for (const image of normalizedImages) {
5365
- content.push({
5366
- type: "image",
5367
- source: {
5368
- type: "base64",
5369
- media_type: image.source.media_type,
5370
- data: image.source.data
5371
- }
5372
- });
5490
+ }
5491
+ if (this.activeQuery && this.activeSessionPermissionMode !== resolvedPermissionMode) {
5492
+ try {
5493
+ await this.activeQuery.setPermissionMode(resolvedPermissionMode);
5494
+ this.activeSessionPermissionMode = resolvedPermissionMode;
5495
+ } catch (err) {
5496
+ console.warn("[ClaudeManager] setPermissionMode failed; recreating session:", err);
5497
+ await this.tearDownSession();
5373
5498
  }
5374
5499
  }
5375
- const userMessage = {
5376
- type: "user",
5377
- message: {
5378
- role: "user",
5379
- content
5380
- },
5381
- parent_tool_use_id: null,
5382
- session_id: this.sessionId ?? ""
5383
- };
5384
- if (!options.skipUserMessageRecord) {
5385
- await this.recordEvent(userMessage);
5500
+ if (this.activeQuery) return;
5501
+ } else if (this.activeQuery) {
5502
+ await this.tearDownSession();
5503
+ }
5504
+ await this.startSession({
5505
+ combinedInstructions,
5506
+ resolvedModel,
5507
+ resolvedPermissionMode,
5508
+ enableInteractiveTools,
5509
+ thinkingLevel,
5510
+ signature
5511
+ });
5512
+ }
5513
+ sessionSignaturesMatch(a, b) {
5514
+ return a.combinedInstructions === b.combinedInstructions && a.thinkingLevel === b.thinkingLevel && a.enableInteractiveTools === b.enableInteractiveTools;
5515
+ }
5516
+ async startSession(args) {
5517
+ const {
5518
+ combinedInstructions,
5519
+ resolvedModel,
5520
+ resolvedPermissionMode,
5521
+ enableInteractiveTools,
5522
+ thinkingLevel,
5523
+ signature
5524
+ } = args;
5525
+ const systemPrompt = this.systemPromptOverride ? this.systemPromptOverride(combinedInstructions) : {
5526
+ type: "preset",
5527
+ preset: "claude_code",
5528
+ append: combinedInstructions
5529
+ };
5530
+ const queryEnv = buildClaudeAgentEnv(this.envOverrides);
5531
+ const additionalDirectories = await getAgentAdditionalDirectories();
5532
+ const interactiveAllowed = enableInteractiveTools && resolvedPermissionMode === "plan";
5533
+ const useDefaultToolPolicy = !this.toolsOverride;
5534
+ const allowedTools = useDefaultToolPolicy ? [
5535
+ ...ALWAYS_ALLOWED_TOOLS,
5536
+ ...interactiveAllowed ? INTERACTIVE_TOOL_NAMES : []
5537
+ ] : void 0;
5538
+ const disallowedTools = [
5539
+ ...this.disallowedToolsOverride ?? [],
5540
+ ...useDefaultToolPolicy ? ALWAYS_DISALLOWED_TOOLS : [],
5541
+ ...interactiveAllowed ? [] : INTERACTIVE_TOOL_NAMES
5542
+ ];
5543
+ const promptStream = new PromptStream();
5544
+ const response = query({
5545
+ prompt: promptStream,
5546
+ options: {
5547
+ resume: this.sessionId || void 0,
5548
+ cwd: this.workingDirectory,
5549
+ additionalDirectories,
5550
+ permissionMode: resolvedPermissionMode,
5551
+ allowDangerouslySkipPermissions: resolvedPermissionMode === "bypassPermissions",
5552
+ ...this.toolsOverride ? { tools: this.toolsOverride } : {},
5553
+ ...allowedTools ? { allowedTools } : {},
5554
+ ...disallowedTools.length > 0 ? { disallowedTools } : {},
5555
+ settingSources: ["user", "project", "local"],
5556
+ systemPrompt,
5557
+ ...this.mcpServersConfig ? { mcpServers: this.mcpServersConfig } : {},
5558
+ env: queryEnv,
5559
+ model: resolvedModel,
5560
+ ...thinkingLevel ? { effort: thinkingLevel } : {},
5561
+ canUseTool: this.buildCanUseTool()
5386
5562
  }
5387
- const promptStream = new PromptStream();
5388
- promptStream.push(userMessage);
5389
- this.activePromptStream = promptStream;
5390
- const combinedInstructions = this.buildCombinedInstructions(customInstructions);
5391
- const systemPrompt = this.systemPromptOverride ? this.systemPromptOverride(combinedInstructions) : {
5392
- type: "preset",
5393
- preset: "claude_code",
5394
- append: combinedInstructions
5395
- };
5396
- const queryEnv = buildClaudeAgentEnv(this.envOverrides);
5397
- const additionalDirectories = await getAgentAdditionalDirectories();
5398
- const resolvedModel = normalizeClaudeModel(model) || CLAUDE_OPUS_1M_MODEL;
5399
- const interactiveAllowed = enableInteractiveTools && permissionMode === "read";
5400
- const useDefaultToolPolicy = !this.toolsOverride;
5401
- const allowedTools = useDefaultToolPolicy ? [
5402
- ...ALWAYS_ALLOWED_TOOLS,
5403
- ...interactiveAllowed ? INTERACTIVE_TOOL_NAMES : []
5404
- ] : void 0;
5405
- const disallowedTools = [
5406
- ...this.disallowedToolsOverride ?? [],
5407
- ...useDefaultToolPolicy ? ALWAYS_DISALLOWED_TOOLS : [],
5408
- ...interactiveAllowed ? [] : INTERACTIVE_TOOL_NAMES
5409
- ];
5410
- const response = query({
5411
- prompt: promptStream,
5412
- options: {
5413
- resume: this.sessionId || void 0,
5414
- cwd: this.workingDirectory,
5415
- additionalDirectories,
5416
- permissionMode: permissionMode === "read" ? "plan" : "bypassPermissions",
5417
- allowDangerouslySkipPermissions: permissionMode !== "read",
5418
- ...this.toolsOverride ? { tools: this.toolsOverride } : {},
5419
- ...allowedTools ? { allowedTools } : {},
5420
- ...disallowedTools.length > 0 ? { disallowedTools } : {},
5421
- settingSources: ["user", "project", "local"],
5422
- systemPrompt,
5423
- ...this.mcpServersConfig ? { mcpServers: this.mcpServersConfig } : {},
5424
- env: queryEnv,
5425
- model: resolvedModel,
5426
- ...thinkingLevel ? { effort: thinkingLevel } : {},
5427
- canUseTool: this.buildCanUseTool()
5428
- }
5429
- });
5430
- this.activeQuery = response;
5431
- if (this.pendingInterrupt) {
5432
- this.pendingInterrupt = false;
5433
- this.activePromptStream?.close();
5434
- await this.activeQuery.interrupt();
5435
- }
5436
- const linearForwarder = new LinearEventForwarder(linearSessionId);
5437
- for await (const msg of response) {
5563
+ });
5564
+ this.activeQuery = response;
5565
+ this.activePromptStream = promptStream;
5566
+ this.activeSessionSignature = signature;
5567
+ this.activeSessionModel = resolvedModel;
5568
+ this.activeSessionPermissionMode = resolvedPermissionMode;
5569
+ this.sessionLinearForwarder = new LinearEventForwarder(ENGINE_ENV.LINEAR_SESSION_ID);
5570
+ this.activeBackgroundTasks.clear();
5571
+ this.sessionLoop = this.runSessionLoop(response).catch((err) => {
5572
+ console.error("[ClaudeManager] Session loop crashed:", err);
5573
+ });
5574
+ }
5575
+ async runSessionLoop(response) {
5576
+ const linearSessionId = ENGINE_ENV.LINEAR_SESSION_ID;
5577
+ const iterator = response[Symbol.asyncIterator]();
5578
+ try {
5579
+ while (true) {
5580
+ const next = await iterator.next();
5581
+ if (next.done) break;
5582
+ const msg = next.value;
5438
5583
  const authErrorMessage = _ClaudeManager.detectAuthErrorInMessage(msg);
5439
5584
  if (authErrorMessage) {
5440
- this.activePromptStream?.close();
5441
- throw new ClaudeAuthError(authErrorMessage);
5585
+ this.failPendingTurn(new ClaudeAuthError(authErrorMessage));
5586
+ try {
5587
+ response.close();
5588
+ } catch (err) {
5589
+ console.warn("[ClaudeManager] query.close() during auth error failed:", err);
5590
+ }
5591
+ return;
5442
5592
  }
5443
5593
  this.setAuthRetrying(false);
5444
5594
  await this.handleMessage(msg);
5445
- if (linearSessionId) {
5446
- linearForwarder.sendPlan(extractPlanFromClaudeEvent(msg));
5447
- linearForwarder.sendEvent(convertClaudeEvent(msg, linearSessionId));
5595
+ _ClaudeManager.updateBackgroundTaskState(msg, this.activeBackgroundTasks);
5596
+ if (linearSessionId && this.sessionLinearForwarder) {
5597
+ this.sessionLinearForwarder.sendPlan(extractPlanFromClaudeEvent(msg));
5598
+ this.sessionLinearForwarder.sendEvent(convertClaudeEvent(msg, linearSessionId));
5448
5599
  }
5449
5600
  if (msg.type === "result") {
5450
5601
  await this.recordContextUsage(response);
5451
- this.activePromptStream?.close();
5452
- break;
5602
+ this.sessionLinearForwarder?.flushThoughtAsResponse();
5603
+ this.resolvePendingTurn();
5453
5604
  }
5454
5605
  }
5455
- linearForwarder.flushThoughtAsResponse();
5456
5606
  } finally {
5457
- this.activeQuery = null;
5458
- this.activePromptStream?.close();
5459
- this.activePromptStream = null;
5460
- this.pendingInterrupt = false;
5607
+ this.sessionLinearForwarder?.flushThoughtAsResponse();
5608
+ this.failPendingTurn(new Error("Claude session ended unexpectedly"));
5609
+ if (this.activeQuery === response) {
5610
+ this.clearSessionState();
5611
+ }
5612
+ }
5613
+ }
5614
+ clearSessionState() {
5615
+ this.activeQuery = null;
5616
+ this.activePromptStream = null;
5617
+ this.activeSessionSignature = null;
5618
+ this.activeSessionModel = null;
5619
+ this.activeSessionPermissionMode = null;
5620
+ this.sessionLinearForwarder = null;
5621
+ this.sessionLoop = null;
5622
+ this.activeBackgroundTasks.clear();
5623
+ }
5624
+ resolvePendingTurn() {
5625
+ const pending = this.pendingTurn;
5626
+ if (!pending) return;
5627
+ this.pendingTurn = null;
5628
+ this.pendingInterrupt = false;
5629
+ pending.resolve();
5630
+ }
5631
+ failPendingTurn(err) {
5632
+ const pending = this.pendingTurn;
5633
+ if (!pending) return;
5634
+ this.pendingTurn = null;
5635
+ this.pendingInterrupt = false;
5636
+ pending.reject(err);
5637
+ }
5638
+ async tearDownSession() {
5639
+ const query2 = this.activeQuery;
5640
+ const stream = this.activePromptStream;
5641
+ const loop = this.sessionLoop;
5642
+ this.failPendingTurn(new Error("Claude session torn down"));
5643
+ this.clearSessionState();
5644
+ if (query2) {
5645
+ try {
5646
+ query2.close();
5647
+ } catch (err) {
5648
+ console.warn("[ClaudeManager] query.close() failed:", err);
5649
+ }
5650
+ }
5651
+ stream?.close();
5652
+ if (loop) {
5653
+ try {
5654
+ await loop;
5655
+ } catch {
5656
+ }
5657
+ }
5658
+ }
5659
+ static updateBackgroundTaskState(message, activeTasks) {
5660
+ if (message.type !== "system") return;
5661
+ const payload = coerceBackgroundTaskPayload(message);
5662
+ if (!payload) return;
5663
+ const status = payload.subtype === "task_updated" ? payload.patch?.status : payload.status;
5664
+ if (isTerminalBackgroundTaskStatus(status)) {
5665
+ activeTasks.delete(payload.taskId);
5666
+ } else {
5667
+ activeTasks.add(payload.taskId);
5461
5668
  }
5462
5669
  }
5463
5670
  getContextUsageProvider() {
@@ -5775,7 +5982,7 @@ var AspClient = class {
5775
5982
  // src/managers/codex-asp/app-server-process.ts
5776
5983
  var DEFAULT_CODEX_BINARY = "codex";
5777
5984
  var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
5778
- var ENGINE_PACKAGE_VERSION = "0.1.213";
5985
+ var ENGINE_PACKAGE_VERSION = "0.1.237";
5779
5986
  var INITIALIZE_METHOD = "initialize";
5780
5987
  var INITIALIZED_NOTIFICATION = "initialized";
5781
5988
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.236",
3
+ "version": "0.1.237",
4
4
  "description": "Lightweight API server for Replicas workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",