replicas-engine 0.1.409 → 0.1.410

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 +201 -56
  2. package/package.json +1 -1
package/dist/src/index.js CHANGED
@@ -479,7 +479,7 @@ var WORKSPACE_SIZES = ["small", "large"];
479
479
  var INVALID_WORKSPACE_SIZE_ERROR = `Invalid size: must be one of ${WORKSPACE_SIZES.join(", ")}`;
480
480
 
481
481
  // ../shared/src/e2b.ts
482
- var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-07-08-v4";
482
+ var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-07-08-v5";
483
483
 
484
484
  // ../shared/src/runtime-env.ts
485
485
  function parsePosixEnvFile(content) {
@@ -5533,27 +5533,81 @@ function linearThoughtToResponse(thought) {
5533
5533
  function summarizeInput(input) {
5534
5534
  if (!input) return "";
5535
5535
  if (typeof input === "string") return input;
5536
- if (typeof input === "object") {
5537
- const obj = input;
5538
- if (obj.file_path) return String(obj.file_path);
5539
- if (obj.command) return String(obj.command);
5540
- if (obj.pattern) return `pattern: ${String(obj.pattern)}`;
5541
- if (obj.query) return String(obj.query);
5542
- if (obj.url) return String(obj.url);
5543
- if (typeof obj.activeForm === "string" && obj.activeForm) return String(obj.activeForm);
5544
- if (typeof obj.subject === "string" && obj.subject) return String(obj.subject);
5545
- const keys = Object.keys(obj);
5546
- if (keys.length > 0) {
5547
- const firstKey = keys[0];
5548
- return `${firstKey}: ${String(obj[firstKey])}`;
5536
+ if (isRecord(input)) {
5537
+ if (input.file_path) return String(input.file_path);
5538
+ if (input.command) return String(input.command);
5539
+ if (input.pattern) return `pattern: ${String(input.pattern)}`;
5540
+ if (input.query) return String(input.query);
5541
+ if (input.url) return String(input.url);
5542
+ if (typeof input.activeForm === "string" && input.activeForm) return String(input.activeForm);
5543
+ if (typeof input.subject === "string" && input.subject) return String(input.subject);
5544
+ for (const [key, value] of Object.entries(input)) {
5545
+ return `${key}: ${String(value)}`;
5549
5546
  }
5550
5547
  }
5551
5548
  return "";
5552
5549
  }
5550
+ function summarizeResult(result) {
5551
+ if (!result) return "";
5552
+ if (typeof result === "string") return result;
5553
+ if (isRecord(result)) {
5554
+ if (typeof result.message === "string") return result.message;
5555
+ if (typeof result.error === "string") return result.error;
5556
+ if (typeof result.stdout === "string") return result.stdout;
5557
+ if (typeof result.stderr === "string") return result.stderr;
5558
+ if (typeof result.path === "string") return result.path;
5559
+ }
5560
+ try {
5561
+ return JSON.stringify(result);
5562
+ } catch {
5563
+ return String(result);
5564
+ }
5565
+ }
5566
+ function toolAction(toolName) {
5567
+ switch (toolName) {
5568
+ case "Bash":
5569
+ case "bash":
5570
+ case "shell":
5571
+ return "Running command";
5572
+ case "Edit":
5573
+ case "edit":
5574
+ return "Editing file";
5575
+ case "Write":
5576
+ case "write":
5577
+ return "Writing file";
5578
+ case "Read":
5579
+ case "read":
5580
+ return "Reading file";
5581
+ case "Glob":
5582
+ case "glob":
5583
+ return "Searching files";
5584
+ case "Grep":
5585
+ case "grep":
5586
+ case "semsearch":
5587
+ return "Searching code";
5588
+ case "WebSearch":
5589
+ return "Web search";
5590
+ case "WebFetch":
5591
+ return "Fetching URL";
5592
+ case "delete":
5593
+ return "Deleting file";
5594
+ case "Task":
5595
+ case "task":
5596
+ return "Spawning subagent";
5597
+ case "TaskCreate":
5598
+ case "TaskUpdate":
5599
+ case "TaskList":
5600
+ case "TaskGet":
5601
+ case "update_todos":
5602
+ case "create_plan":
5603
+ return "Updating plan";
5604
+ default:
5605
+ return toolName;
5606
+ }
5607
+ }
5553
5608
  function convertClaudeEvent(event, linearSessionId) {
5554
5609
  if (event.type === "assistant") {
5555
- const message = event;
5556
- const contentBlocks = normalizeContentBlocks(message.message?.content);
5610
+ const contentBlocks = normalizeContentBlocks(event.message.content);
5557
5611
  for (const block of contentBlocks) {
5558
5612
  if (block.type === "text" && block.text) {
5559
5613
  return {
@@ -5576,47 +5630,11 @@ function convertClaudeEvent(event, linearSessionId) {
5576
5630
  if (block.type === "tool_use" && block.name) {
5577
5631
  const toolName = block.name;
5578
5632
  const parameter = summarizeInput(block.input);
5579
- let action = toolName;
5580
- switch (toolName) {
5581
- case "Bash":
5582
- action = "Running command";
5583
- break;
5584
- case "Edit":
5585
- action = "Editing file";
5586
- break;
5587
- case "Write":
5588
- action = "Writing file";
5589
- break;
5590
- case "Read":
5591
- action = "Reading file";
5592
- break;
5593
- case "Glob":
5594
- action = "Searching files";
5595
- break;
5596
- case "Grep":
5597
- action = "Searching code";
5598
- break;
5599
- case "WebSearch":
5600
- action = "Web search";
5601
- break;
5602
- case "WebFetch":
5603
- action = "Fetching URL";
5604
- break;
5605
- case "Task":
5606
- action = "Spawning subagent";
5607
- break;
5608
- case "TaskCreate":
5609
- case "TaskUpdate":
5610
- case "TaskList":
5611
- case "TaskGet":
5612
- action = "Updating plan";
5613
- break;
5614
- }
5615
5633
  return {
5616
5634
  linearSessionId,
5617
5635
  content: {
5618
5636
  type: "action",
5619
- action,
5637
+ action: toolAction(toolName),
5620
5638
  parameter
5621
5639
  }
5622
5640
  };
@@ -5624,8 +5642,7 @@ function convertClaudeEvent(event, linearSessionId) {
5624
5642
  }
5625
5643
  }
5626
5644
  if (event.type === "user") {
5627
- const message = event;
5628
- const contentBlocks = normalizeContentBlocks(message.message?.content);
5645
+ const contentBlocks = normalizeContentBlocks(event.message.content);
5629
5646
  for (const block of contentBlocks) {
5630
5647
  if (block.type === "tool_result") {
5631
5648
  const resultText = extractToolResultText(block.content);
@@ -5645,6 +5662,106 @@ function convertClaudeEvent(event, linearSessionId) {
5645
5662
  }
5646
5663
  return null;
5647
5664
  }
5665
+ function convertCursorEvent(event, linearSessionId) {
5666
+ if (event.type === "assistant") {
5667
+ for (const block of event.message.content) {
5668
+ if (block.type === "text" && block.text) {
5669
+ return {
5670
+ linearSessionId,
5671
+ content: {
5672
+ type: "thought",
5673
+ body: block.text
5674
+ }
5675
+ };
5676
+ }
5677
+ if (block.type === "tool_use" && block.name) {
5678
+ return {
5679
+ linearSessionId,
5680
+ content: {
5681
+ type: "action",
5682
+ action: toolAction(block.name),
5683
+ parameter: summarizeInput(block.input)
5684
+ }
5685
+ };
5686
+ }
5687
+ }
5688
+ }
5689
+ if (event.type === "thinking" && event.text) {
5690
+ return {
5691
+ linearSessionId,
5692
+ content: {
5693
+ type: "thought",
5694
+ body: event.text
5695
+ }
5696
+ };
5697
+ }
5698
+ if (event.type === "tool_call") {
5699
+ const result = event.status === "running" ? void 0 : event.status === "error" ? `Error: ${summarizeResult(event.result) || "Tool failed"}` : summarizeResult(event.result) || "Done";
5700
+ return {
5701
+ linearSessionId,
5702
+ content: {
5703
+ type: "action",
5704
+ action: toolAction(event.name),
5705
+ parameter: summarizeInput(event.args),
5706
+ ...result ? { result } : {}
5707
+ }
5708
+ };
5709
+ }
5710
+ if (event.type === "task" && event.text) {
5711
+ return {
5712
+ linearSessionId,
5713
+ content: {
5714
+ type: "thought",
5715
+ body: event.text
5716
+ }
5717
+ };
5718
+ }
5719
+ return null;
5720
+ }
5721
+ function isOpencodePartEnded(part) {
5722
+ return "time" in part && isRecord(part.time) && part.time.end !== void 0;
5723
+ }
5724
+ function convertOpencodePart(part, linearSessionId) {
5725
+ if ((part.type === "text" || part.type === "reasoning") && isOpencodePartEnded(part)) {
5726
+ const body = typeof part.text === "string" ? part.text.trim() : "";
5727
+ if (!body) return null;
5728
+ return {
5729
+ linearSessionId,
5730
+ content: {
5731
+ type: "thought",
5732
+ body
5733
+ }
5734
+ };
5735
+ }
5736
+ if (part.type === "tool" && isRecord(part.state)) {
5737
+ const state = part.state;
5738
+ const status = typeof state.status === "string" ? state.status : void 0;
5739
+ const result = status === "completed" ? summarizeResult(state.output) || "Done" : status === "error" ? `Error: ${summarizeResult(state.error) || "Tool failed"}` : void 0;
5740
+ return {
5741
+ linearSessionId,
5742
+ content: {
5743
+ type: "action",
5744
+ action: toolAction(typeof part.tool === "string" ? part.tool : "Tool"),
5745
+ parameter: summarizeInput(state.input),
5746
+ ...result ? { result } : {}
5747
+ }
5748
+ };
5749
+ }
5750
+ if (part.type === "patch") {
5751
+ const files = "files" in part && Array.isArray(part.files) ? part.files.filter((file) => typeof file === "string") : [];
5752
+ if (files.length === 0) return null;
5753
+ return {
5754
+ linearSessionId,
5755
+ content: {
5756
+ type: "action",
5757
+ action: "File change",
5758
+ parameter: files.join(", "),
5759
+ result: "Done"
5760
+ }
5761
+ };
5762
+ }
5763
+ return null;
5764
+ }
5648
5765
  function mapTodoStatus(status) {
5649
5766
  if (status === "in_progress") {
5650
5767
  return "inProgress";
@@ -8087,7 +8204,7 @@ var AspClient = class {
8087
8204
  // src/managers/codex-asp/app-server-process.ts
8088
8205
  var DEFAULT_CODEX_BINARY = "codex";
8089
8206
  var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
8090
- var ENGINE_PACKAGE_VERSION = "0.1.409";
8207
+ var ENGINE_PACKAGE_VERSION = "0.1.410";
8091
8208
  var INITIALIZE_METHOD = "initialize";
8092
8209
  var INITIALIZED_NOTIFICATION = "initialized";
8093
8210
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -10294,6 +10411,8 @@ var CursorManager = class extends CodingAgentManager {
10294
10411
  return this.agent;
10295
10412
  }
10296
10413
  async processMessageInternal(request) {
10414
+ const linearSessionId = ENGINE_ENV.LINEAR_SESSION_ID;
10415
+ const linearForwarder = new LinearEventForwarder(linearSessionId);
10297
10416
  try {
10298
10417
  const agent = await this.ensureAgent(request);
10299
10418
  const message = await this.toCursorMessage(request);
@@ -10310,6 +10429,9 @@ var CursorManager = class extends CodingAgentManager {
10310
10429
  this.activeModel = model;
10311
10430
  for await (const event of run.stream()) {
10312
10431
  this.recordCursorEvent(event);
10432
+ if (linearSessionId) {
10433
+ linearForwarder.sendEvent(convertCursorEvent(event, linearSessionId));
10434
+ }
10313
10435
  }
10314
10436
  const result = await run.wait();
10315
10437
  if (result.status === "error") {
@@ -10318,6 +10440,8 @@ var CursorManager = class extends CodingAgentManager {
10318
10440
  message: result.result || "Cursor run failed",
10319
10441
  runId: result.id
10320
10442
  }, this.historyFile);
10443
+ } else {
10444
+ linearForwarder.flushThoughtAsResponse();
10321
10445
  }
10322
10446
  } catch (error) {
10323
10447
  this.recordHistoryEvent("cursor-error", {
@@ -10572,6 +10696,8 @@ var OpencodeManager = class extends CodingAgentManager {
10572
10696
  textParts = /* @__PURE__ */ new Map();
10573
10697
  reasoningParts = /* @__PURE__ */ new Map();
10574
10698
  nonAssistantMessageIds = /* @__PURE__ */ new Set();
10699
+ activeLinearForwarder = null;
10700
+ forwardedLinearPartKeys = /* @__PURE__ */ new Set();
10575
10701
  modelVariants = /* @__PURE__ */ new Map();
10576
10702
  slashCommandsCache = null;
10577
10703
  slashCommandsRequest = null;
@@ -10738,7 +10864,11 @@ var OpencodeManager = class extends CodingAgentManager {
10738
10864
  async processMessageInternal(request) {
10739
10865
  const model = request.model ?? DEFAULT_OPENCODE_MODEL;
10740
10866
  const controller = new AbortController();
10867
+ const linearSessionId = ENGINE_ENV.LINEAR_SESSION_ID;
10868
+ const linearForwarder = new LinearEventForwarder(linearSessionId);
10741
10869
  this.activeAbortController = controller;
10870
+ this.activeLinearForwarder = linearForwarder;
10871
+ this.forwardedLinearPartKeys.clear();
10742
10872
  try {
10743
10873
  const client = await this.ensureClient(model);
10744
10874
  const agent = request.planMode ? "plan" : "build";
@@ -10760,6 +10890,7 @@ var OpencodeManager = class extends CodingAgentManager {
10760
10890
  }, { signal: controller.signal, throwOnError: true });
10761
10891
  this.recordHistoryEvent("opencode-message.updated", { info: result.data.info }, this.historyFile);
10762
10892
  for (const part of result.data.parts) this.recordOpencodePart(part);
10893
+ linearForwarder.flushThoughtAsResponse();
10763
10894
  this.recordHistoryEvent("opencode-session.idle", { sessionID: sessionId }, this.historyFile);
10764
10895
  } catch (error) {
10765
10896
  if (controller.signal.aborted) {
@@ -10770,6 +10901,8 @@ var OpencodeManager = class extends CodingAgentManager {
10770
10901
  }
10771
10902
  } finally {
10772
10903
  this.activeAbortController = null;
10904
+ this.activeLinearForwarder = null;
10905
+ this.forwardedLinearPartKeys.clear();
10773
10906
  await this.historyFile.flush();
10774
10907
  await this.onTurnComplete();
10775
10908
  }
@@ -10893,8 +11026,20 @@ var OpencodeManager = class extends CodingAgentManager {
10893
11026
  }
10894
11027
  return false;
10895
11028
  }
11029
+ forwardOpencodePartToLinear(part) {
11030
+ const linearSessionId = ENGINE_ENV.LINEAR_SESSION_ID;
11031
+ if (!linearSessionId || !this.activeLinearForwarder) return;
11032
+ const event = convertOpencodePart(part, linearSessionId);
11033
+ if (!event) return;
11034
+ if (typeof part.id !== "string") return;
11035
+ const key = `${part.type}:${part.id}:${JSON.stringify(event.content)}`;
11036
+ if (this.forwardedLinearPartKeys.has(key)) return;
11037
+ this.forwardedLinearPartKeys.add(key);
11038
+ this.activeLinearForwarder.sendEvent(event);
11039
+ }
10896
11040
  recordOpencodePart(part) {
10897
11041
  this.recordHistoryEvent(`opencode-part-${part.type}`, { part }, this.historyFile);
11042
+ this.forwardOpencodePartToLinear(part);
10898
11043
  }
10899
11044
  };
10900
11045
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.409",
3
+ "version": "0.1.410",
4
4
  "description": "Lightweight API server for Replicas workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",