replicas-engine 0.1.726 → 0.1.727

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.
@@ -12,7 +12,7 @@ import {
12
12
  isValidAgentProvider,
13
13
  parsePosixEnvFile,
14
14
  readReplicasRuntimeEnv
15
- } from "./chunk-DFBYJH6I.js";
15
+ } from "./chunk-Y22KEEKB.js";
16
16
 
17
17
  // src/engine-env.ts
18
18
  import { readFileSync as readFileSync2 } from "fs";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  HOOK_EXEC_MAX_BUFFER_BYTES,
4
4
  isVersionBelow
5
- } from "./chunk-DFBYJH6I.js";
5
+ } from "./chunk-Y22KEEKB.js";
6
6
 
7
7
  // src/utils/presigned-upload.ts
8
8
  import { createReadStream } from "fs";
@@ -267,7 +267,7 @@ var DEFAULT_CODEX_ARGS = [
267
267
  var MIN_CODEX_CLI_VERSION = "0.144.6";
268
268
  var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
269
269
  var codexCliVersionEnsured = null;
270
- var ENGINE_PACKAGE_VERSION = "0.1.726";
270
+ var ENGINE_PACKAGE_VERSION = "0.1.727";
271
271
  var INITIALIZE_METHOD = "initialize";
272
272
  var INITIALIZED_NOTIFICATION = "initialized";
273
273
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  mayCreatePullRequest
4
- } from "./chunk-DFBYJH6I.js";
4
+ } from "./chunk-Y22KEEKB.js";
5
5
 
6
6
  // src/services/post-tool-pr-notifier.ts
7
7
  async function notifyPostToolUse(toolName, toolInput) {
@@ -4168,6 +4168,7 @@ function coerceBackgroundTaskPayload(payload) {
4168
4168
  prompt: optionalString(payload.prompt),
4169
4169
  lastToolName: optionalString(payload.last_tool_name),
4170
4170
  usage,
4171
+ ambient: optionalBoolean(payload.ambient),
4171
4172
  patch
4172
4173
  };
4173
4174
  }
@@ -5566,6 +5567,7 @@ function parseClaudeEvents(events, parentToolUseId) {
5566
5567
  });
5567
5568
  const toolCallMap = /* @__PURE__ */ new Map();
5568
5569
  const taskMessageMap = /* @__PURE__ */ new Map();
5570
+ const ambientTaskIds = /* @__PURE__ */ new Set();
5569
5571
  const partialIndexes = /* @__PURE__ */ new Map();
5570
5572
  const completedStreamIds = /* @__PURE__ */ new Set();
5571
5573
  const supersededStreamIds = /* @__PURE__ */ new Set();
@@ -5574,9 +5576,10 @@ function parseClaudeEvents(events, parentToolUseId) {
5574
5576
  const assistantTextCounts = /* @__PURE__ */ new Map();
5575
5577
  const acceptedUserMessageIndexes = /* @__PURE__ */ new Set();
5576
5578
  const canonicalUserMessageIndexes = /* @__PURE__ */ new Set();
5579
+ const supersededUserMessageIndexes = /* @__PURE__ */ new Set();
5577
5580
  const findMatchingUserMessageIndex = (indexes, content, timestamp, messageId) => {
5578
5581
  if (typeof messageId === "string") {
5579
- const byId = messages.findIndex((message) => message.type === "user" && message.id === messageId);
5582
+ const byId = messages.findIndex((message, index) => message.type === "user" && message.id === messageId && !supersededUserMessageIndexes.has(index));
5580
5583
  if (byId !== -1) return byId;
5581
5584
  }
5582
5585
  return [...indexes].find((index) => {
@@ -5688,9 +5691,12 @@ function parseClaudeEvents(events, parentToolUseId) {
5688
5691
  };
5689
5692
  if (acceptedIndex === void 0) {
5690
5693
  canonicalUserMessageIndexes.add(messages.push(message) - 1);
5694
+ } else if (acceptedUserMessageIndexes.has(acceptedIndex)) {
5695
+ supersededUserMessageIndexes.add(acceptedIndex);
5696
+ acceptedUserMessageIndexes.delete(acceptedIndex);
5697
+ canonicalUserMessageIndexes.add(messages.push(message) - 1);
5691
5698
  } else {
5692
5699
  messages[acceptedIndex] = message;
5693
- acceptedUserMessageIndexes.delete(acceptedIndex);
5694
5700
  }
5695
5701
  }
5696
5702
  }
@@ -5926,7 +5932,8 @@ function parseClaudeEvents(events, parentToolUseId) {
5926
5932
  }
5927
5933
  if (event.type === "claude-system") {
5928
5934
  const payload = coerceBackgroundTaskPayload(event.payload);
5929
- if (payload) {
5935
+ if (payload?.ambient) ambientTaskIds.add(payload.taskId);
5936
+ if (payload && !ambientTaskIds.has(payload.taskId)) {
5930
5937
  const existing = taskMessageMap.get(payload.taskId);
5931
5938
  const nextStatus = payload.subtype === "task_notification" ? normalizeBackgroundTaskStatus(payload.status) : payload.subtype === "task_updated" ? normalizeBackgroundTaskStatus(payload.patch?.status) : existing?.status ?? "in_progress";
5932
5939
  const nextMessage = {
@@ -6043,7 +6050,7 @@ function parseClaudeEvents(events, parentToolUseId) {
6043
6050
  message.targetProvider = target.subagentType;
6044
6051
  }
6045
6052
  }
6046
- const staleIndexes = /* @__PURE__ */ new Set();
6053
+ const staleIndexes = new Set(supersededUserMessageIndexes);
6047
6054
  for (const streamId of [...completedStreamIds, ...supersededStreamIds]) {
6048
6055
  const refs = partialIndexes.get(streamId);
6049
6056
  if (refs?.reasoning !== void 0) staleIndexes.add(refs.reasoning);
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  evaluateCommandProtection
4
- } from "./chunk-L3TAK4RD.js";
4
+ } from "./chunk-6BLBZSQ5.js";
5
5
  import {
6
6
  isRecord
7
7
  } from "./chunk-2RB7SIP3.js";
8
- import "./chunk-DFBYJH6I.js";
8
+ import "./chunk-Y22KEEKB.js";
9
9
 
10
10
  // src/command-protection-hook.ts
11
11
  var provider = process.argv[2];
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  evaluateCommandProtection
4
- } from "./chunk-L3TAK4RD.js";
4
+ } from "./chunk-6BLBZSQ5.js";
5
5
  import {
6
6
  notifyPostToolUse
7
- } from "./chunk-KZODFP3F.js";
7
+ } from "./chunk-S62ADFCN.js";
8
8
  import "./chunk-2RB7SIP3.js";
9
- import "./chunk-DFBYJH6I.js";
9
+ import "./chunk-Y22KEEKB.js";
10
10
 
11
11
  // src/deepseek-command-protection-plugin.ts
12
12
  function replicasCommandProtection(context) {
@@ -4,12 +4,12 @@ import {
4
4
  buildCodexAgentEnv,
5
5
  putPresignedFile,
6
6
  recoverCompletedTurn
7
- } from "./chunk-QL2YWG6O.js";
7
+ } from "./chunk-MICZ3XPR.js";
8
8
  import {
9
9
  AGENT,
10
10
  getMemoryOutputSafetyViolation,
11
11
  headlessAgentRequestSchema
12
- } from "./chunk-DFBYJH6I.js";
12
+ } from "./chunk-Y22KEEKB.js";
13
13
 
14
14
  // src/headless-agent.ts
15
15
  import { createHash } from "crypto";
package/dist/src/index.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  monolithService,
9
9
  reportCommandProtectionBlock,
10
10
  setAgentCredentialSnapshot
11
- } from "./chunk-L3TAK4RD.js";
11
+ } from "./chunk-6BLBZSQ5.js";
12
12
  import {
13
13
  ACCOUNT_RATE_LIMITS_UPDATED_METHOD,
14
14
  AGENT_MESSAGE_DELTA_METHOD,
@@ -35,7 +35,7 @@ import {
35
35
  execFileAsync,
36
36
  putPresignedFile,
37
37
  recoverCompletedTurn
38
- } from "./chunk-QL2YWG6O.js";
38
+ } from "./chunk-MICZ3XPR.js";
39
39
  import {
40
40
  isRecord as isRecord2
41
41
  } from "./chunk-2RB7SIP3.js";
@@ -216,7 +216,7 @@ import {
216
216
  shellQuotePosix,
217
217
  stripAgentDiagnosticErrors,
218
218
  withTimeout
219
- } from "./chunk-DFBYJH6I.js";
219
+ } from "./chunk-Y22KEEKB.js";
220
220
 
221
221
  // src/index.ts
222
222
  import { serve } from "@hono/node-server";
@@ -2677,6 +2677,12 @@ function workspaceChatEventSignals(event) {
2677
2677
  userMessageId: getUserMessageId(event)
2678
2678
  };
2679
2679
  }
2680
+ var emptyIndex = () => ({
2681
+ byStreamId: /* @__PURE__ */ new Map(),
2682
+ byJson: /* @__PURE__ */ new Map(),
2683
+ byUserMessageId: /* @__PURE__ */ new Map(),
2684
+ byUserMessage: /* @__PURE__ */ new Map()
2685
+ });
2680
2686
  function indexMergedEvent(index, event, position) {
2681
2687
  const { streamId, json, userMessage, userMessageId } = workspaceChatEventSignals(event);
2682
2688
  if (streamId !== null && !index.byStreamId.has(streamId)) {
@@ -2696,7 +2702,7 @@ function indexMergedEvent(index, event, position) {
2696
2702
  bucket.splice(insertAt === -1 ? bucket.length : insertAt, 0, { position, event });
2697
2703
  }
2698
2704
  }
2699
- function reindexReplacedEvent(index, previous, event, position) {
2705
+ function unindexEvent(index, previous, position) {
2700
2706
  const { streamId, json, userMessage, userMessageId } = workspaceChatEventSignals(previous);
2701
2707
  if (streamId !== null && index.byStreamId.get(streamId) === position) {
2702
2708
  index.byStreamId.delete(streamId);
@@ -2713,7 +2719,6 @@ function reindexReplacedEvent(index, previous, event, position) {
2713
2719
  index.byUserMessage.delete(userMessage);
2714
2720
  }
2715
2721
  }
2716
- indexMergedEvent(index, event, position);
2717
2722
  }
2718
2723
  function findDuplicatePosition(index, event) {
2719
2724
  const { streamId, json, userMessage, userMessageId } = workspaceChatEventSignals(event);
@@ -2737,28 +2742,57 @@ function findDuplicatePosition(index, event) {
2737
2742
  function mergeWorkspaceChatHistoryEvents(primary, supplemental) {
2738
2743
  if (supplemental.length === 0) return [...primary];
2739
2744
  const merged = [...primary];
2740
- const index = {
2741
- byStreamId: /* @__PURE__ */ new Map(),
2742
- byJson: /* @__PURE__ */ new Map(),
2743
- byUserMessageId: /* @__PURE__ */ new Map(),
2744
- byUserMessage: /* @__PURE__ */ new Map()
2745
+ const index = emptyIndex();
2746
+ for (let position = 0; position < primary.length; position++) {
2747
+ indexMergedEvent(index, primary[position], position);
2748
+ }
2749
+ const additions = [];
2750
+ const additionsIndex = emptyIndex();
2751
+ const addEvent = (event) => {
2752
+ indexMergedEvent(additionsIndex, event, additions.length);
2753
+ additions.push(event);
2745
2754
  };
2746
- for (let position = 0; position < merged.length; position++) {
2747
- indexMergedEvent(index, merged[position], position);
2748
- }
2749
2755
  for (const event of supplemental) {
2750
- const position = findDuplicatePosition(index, event);
2751
- const messageId = getUserMessageId(event);
2756
+ let list = merged;
2757
+ let listIndex = index;
2758
+ let position = findDuplicatePosition(index, event);
2752
2759
  if (position === -1) {
2753
- indexMergedEvent(index, event, merged.length);
2754
- merged.push(event);
2755
- } else if (getClaudePartialMessageStreamId(event) !== null || isAcceptedUserMessage(merged[position]) && !isAcceptedUserMessage(event) || messageId !== null && messageId === getUserMessageId(merged[position])) {
2756
- const previous = merged[position];
2757
- merged[position] = event;
2758
- reindexReplacedEvent(index, previous, event, position);
2760
+ list = additions;
2761
+ listIndex = additionsIndex;
2762
+ position = findDuplicatePosition(additionsIndex, event);
2763
+ }
2764
+ const previous = position === -1 ? null : list[position];
2765
+ if (!previous) {
2766
+ addEvent(event);
2767
+ continue;
2759
2768
  }
2769
+ const messageId = getUserMessageId(event);
2770
+ if (isAcceptedUserMessage(previous) && !isAcceptedUserMessage(event)) {
2771
+ list[position] = null;
2772
+ unindexEvent(listIndex, previous, position);
2773
+ addEvent(event);
2774
+ } else if (getClaudePartialMessageStreamId(event) !== null || messageId !== null && messageId === getUserMessageId(previous)) {
2775
+ list[position] = event;
2776
+ unindexEvent(listIndex, previous, position);
2777
+ indexMergedEvent(listIndex, event, position);
2778
+ }
2779
+ }
2780
+ return insertChronologically(
2781
+ merged.filter((event) => event !== null),
2782
+ additions.filter((event) => event !== null)
2783
+ );
2784
+ }
2785
+ function insertChronologically(existing, additions) {
2786
+ const sorted = [...additions].sort((a, b) => getEventTimestampMs(a) - getEventTimestampMs(b));
2787
+ const result = [];
2788
+ let next = 0;
2789
+ for (const event of existing) {
2790
+ const ms = getEventTimestampMs(event);
2791
+ while (next < sorted.length && getEventTimestampMs(sorted[next]) < ms) result.push(sorted[next++]);
2792
+ result.push(event);
2760
2793
  }
2761
- return merged;
2794
+ result.push(...sorted.slice(next));
2795
+ return result;
2762
2796
  }
2763
2797
 
2764
2798
  // src/managers/claude-manager.ts
@@ -4624,6 +4658,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
4624
4658
  backgroundContinuationTimer = null;
4625
4659
  pendingInterrupt = false;
4626
4660
  activeBackgroundTasks = /* @__PURE__ */ new Set();
4661
+ ambientBackgroundTasks = /* @__PURE__ */ new Set();
4627
4662
  // Set when background tasks outlive a turn; cleared once their completion
4628
4663
  // has been reported through onTurnComplete.
4629
4664
  pendingBackgroundCompletion = false;
@@ -5254,6 +5289,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
5254
5289
  this.activeSessionPermissionMode = resolvedPermissionMode;
5255
5290
  this.sessionLinearForwarder = new LinearEventForwarder(ENGINE_ENV.REPLICAS_LINEAR_SESSION_ID);
5256
5291
  this.activeBackgroundTasks.clear();
5292
+ this.ambientBackgroundTasks.clear();
5257
5293
  this.clearBackgroundContinuationTimer();
5258
5294
  resetClaudeSessionActivity(this.sessionActivity);
5259
5295
  this.sessionLoop = this.runSessionLoop(response).catch((err) => {
@@ -5319,7 +5355,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
5319
5355
  }
5320
5356
  updateClaudeSessionActivity(this.sessionActivity, msg);
5321
5357
  const hadActiveBackgroundTasks = this.activeBackgroundTasks.size > 0;
5322
- _ClaudeManager.updateBackgroundTaskState(msg, this.activeBackgroundTasks);
5358
+ _ClaudeManager.updateBackgroundTaskState(msg, this.activeBackgroundTasks, this.ambientBackgroundTasks);
5323
5359
  if (hadActiveBackgroundTasks && this.activeBackgroundTasks.size === 0) {
5324
5360
  this.startBackgroundContinuationGrace();
5325
5361
  }
@@ -5376,6 +5412,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
5376
5412
  this.clearBackgroundContinuationTimer();
5377
5413
  resetClaudeSessionActivity(this.sessionActivity);
5378
5414
  this.activeBackgroundTasks.clear();
5415
+ this.ambientBackgroundTasks.clear();
5379
5416
  this.pendingBackgroundCompletion = false;
5380
5417
  for (const timer of this.partialMessageFlushTimers.values()) {
5381
5418
  clearTimeout(timer);
@@ -5444,7 +5481,10 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
5444
5481
  }
5445
5482
  }
5446
5483
  }
5447
- static updateBackgroundTaskState(message, activeTasks) {
5484
+ // Ambient tasks are CLI housekeeping (skip_transcript tasks, auto-started
5485
+ // watchers) that the SDK asks hosts to keep out of activity indicators;
5486
+ // counted as active, they would keep the chat processing after its turn.
5487
+ static updateBackgroundTaskState(message, activeTasks, ambientTasks) {
5448
5488
  if (message.type !== "system") return;
5449
5489
  if (message.subtype === "session_state_changed" && message.state === "idle") {
5450
5490
  activeTasks.clear();
@@ -5453,14 +5493,18 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
5453
5493
  if (message.subtype === "background_tasks_changed") {
5454
5494
  activeTasks.clear();
5455
5495
  for (const task of message.tasks) {
5456
- activeTasks.add(task.task_id);
5496
+ if (task.ambient) ambientTasks.add(task.task_id);
5497
+ else ambientTasks.delete(task.task_id);
5498
+ if (!task.ambient) activeTasks.add(task.task_id);
5457
5499
  }
5458
5500
  return;
5459
5501
  }
5460
5502
  const payload = coerceBackgroundTaskPayload(message);
5461
5503
  if (!payload) return;
5504
+ if (payload.ambient === true) ambientTasks.add(payload.taskId);
5505
+ else if (payload.ambient === false) ambientTasks.delete(payload.taskId);
5462
5506
  const status = payload.subtype === "task_updated" ? payload.patch?.status : payload.status;
5463
- if (isTerminalBackgroundTaskStatus(status)) {
5507
+ if (isTerminalBackgroundTaskStatus(status) || ambientTasks.has(payload.taskId)) {
5464
5508
  activeTasks.delete(payload.taskId);
5465
5509
  } else {
5466
5510
  activeTasks.add(payload.taskId);
@@ -5675,6 +5719,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
5675
5719
  this.handlePartialAssistantMessage(message);
5676
5720
  return;
5677
5721
  }
5722
+ if (message.type === "system" && message.subtype === "thinking_tokens") return;
5678
5723
  if (message.type === "system" && message.subtype === "commands_changed") {
5679
5724
  this.supportedSlashCommands = normalizeClaudeSlashCommands(message.commands);
5680
5725
  this.slashCommandsDiscoveredAt = Date.now();
@@ -13408,7 +13453,7 @@ var ChatService = class {
13408
13453
  const { event: acceptedEvent, sender } = createTurnMetadata(
13409
13454
  message,
13410
13455
  message.id,
13411
- message.queuedAt
13456
+ (/* @__PURE__ */ new Date()).toISOString()
13412
13457
  );
13413
13458
  chat.acceptedUserEvents.set(message.id, acceptedEvent);
13414
13459
  this.activateTurn(chat, message.id);
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  notifyPostToolUse
4
- } from "./chunk-KZODFP3F.js";
4
+ } from "./chunk-S62ADFCN.js";
5
5
  import {
6
6
  isRecord
7
7
  } from "./chunk-2RB7SIP3.js";
8
- import "./chunk-DFBYJH6I.js";
8
+ import "./chunk-Y22KEEKB.js";
9
9
 
10
10
  // src/post-tool-pr-hook.ts
11
11
  async function main() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.726",
3
+ "version": "0.1.727",
4
4
  "description": "Lightweight API server for Replicas workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",