replicas-engine 0.1.1266 → 0.1.1267

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.
@@ -8,12 +8,12 @@ import {
8
8
  listRunningCodexModels,
9
9
  restartCodexAspHost,
10
10
  restartCodexAspHostIfRunning
11
- } from "./chunk-V6EDWBWV.js";
12
- import "./chunk-SJIWGPT3.js";
13
- import "./chunk-6SRLEHOV.js";
14
- import "./chunk-AHPBQSXT.js";
11
+ } from "./chunk-6VDGJBXA.js";
12
+ import "./chunk-WZT5BWBM.js";
13
+ import "./chunk-LR6YGW3W.js";
14
+ import "./chunk-A24AON3O.js";
15
15
  import "./chunk-UZSNFLDQ.js";
16
- import "./chunk-FNPPBKJI.js";
16
+ import "./chunk-RLVAL5RN.js";
17
17
  import "./chunk-VEQXQN22.js";
18
18
  export {
19
19
  CODEX_ULTRAFAST_SERVICE_TIER,
@@ -5,14 +5,14 @@ import {
5
5
  getOriginDefaultBranch,
6
6
  monolithRequest,
7
7
  runGitCommand
8
- } from "./chunk-SJIWGPT3.js";
8
+ } from "./chunk-WZT5BWBM.js";
9
9
  import {
10
10
  extractCommandProtectionCommandText,
11
11
  findCommandProtectionGitLookups,
12
12
  findGitCommitSignals,
13
13
  findPrMergeSignals,
14
14
  parseCommandProtectionRequest
15
- } from "./chunk-FNPPBKJI.js";
15
+ } from "./chunk-RLVAL5RN.js";
16
16
 
17
17
  // src/services/command-protection-service.ts
18
18
  import { readFile, stat } from "fs/promises";
@@ -10,15 +10,15 @@ import {
10
10
  resolveDiffBase,
11
11
  runGitCommand,
12
12
  setAgentCredentialSnapshot
13
- } from "./chunk-SJIWGPT3.js";
13
+ } from "./chunk-WZT5BWBM.js";
14
14
  import {
15
15
  AppServerProcess,
16
16
  buildCodexAgentEnv
17
- } from "./chunk-6SRLEHOV.js";
17
+ } from "./chunk-LR6YGW3W.js";
18
18
  import {
19
19
  SUBPROCESS_MAX_BUFFER,
20
20
  execFileAsync
21
- } from "./chunk-AHPBQSXT.js";
21
+ } from "./chunk-A24AON3O.js";
22
22
  import {
23
23
  isRecord
24
24
  } from "./chunk-UZSNFLDQ.js";
@@ -55,7 +55,7 @@ import {
55
55
  resolveOpenAICompatibleModelsUrl,
56
56
  splitMothershipInstructions,
57
57
  withTimeout
58
- } from "./chunk-FNPPBKJI.js";
58
+ } from "./chunk-RLVAL5RN.js";
59
59
 
60
60
  // src/managers/codex-token-manager.ts
61
61
  import { promises as fs } from "fs";
@@ -291,7 +291,7 @@ var CodexTokenManager = class extends BaseRefreshManager {
291
291
  await this.applyCredentialUpdate(++this.credentialGeneration, async () => {
292
292
  await this.applyCredentialsResponse(data);
293
293
  setAgentCredentialSnapshot("codex", data);
294
- const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-RAZFDDTB.js");
294
+ const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-PM7AJ6GF.js");
295
295
  await restartCodexAspHostIfRunning2();
296
296
  });
297
297
  await this.start(true);
@@ -313,7 +313,7 @@ var CodexTokenManager = class extends BaseRefreshManager {
313
313
  const accountChanged = ENGINE_ENV.REPLICAS_AGENT_CREDENTIALS.codex?.credentialId !== data.credentialId;
314
314
  await this.applyCredentialsResponse(data);
315
315
  if (restartOnChange && (accountChanged || CODEX_AUTH_ENV_KEYS.some((key, index) => process.env[key] !== previousEnv[index]))) {
316
- const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-RAZFDDTB.js");
316
+ const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-PM7AJ6GF.js");
317
317
  await restartCodexAspHostIfRunning2();
318
318
  }
319
319
  setAgentCredentialSnapshot("codex", data);
@@ -3,7 +3,7 @@ import { createRequire as __createRequire } from 'node:module';
3
3
  const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  HOOK_EXEC_MAX_BUFFER_BYTES
6
- } from "./chunk-FNPPBKJI.js";
6
+ } from "./chunk-RLVAL5RN.js";
7
7
 
8
8
  // src/utils/exec.ts
9
9
  import { exec, execFile } from "child_process";
@@ -5,7 +5,7 @@ import {
5
5
  extractCommandProtectionCommandText,
6
6
  isRecord,
7
7
  parseCodeHostPrUrl
8
- } from "./chunk-FNPPBKJI.js";
8
+ } from "./chunk-RLVAL5RN.js";
9
9
 
10
10
  // src/services/published-pull-request-urls.ts
11
11
  function publishedPullRequestUrls(result) {
@@ -3,10 +3,10 @@ import { createRequire as __createRequire } from 'node:module';
3
3
  const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  execFileAsync
6
- } from "./chunk-AHPBQSXT.js";
6
+ } from "./chunk-A24AON3O.js";
7
7
  import {
8
8
  isVersionBelow
9
- } from "./chunk-FNPPBKJI.js";
9
+ } from "./chunk-RLVAL5RN.js";
10
10
 
11
11
  // src/utils/codex-agent-env.ts
12
12
  function buildCodexAgentEnv(source = process.env) {
@@ -240,7 +240,7 @@ function getCodexModelProvider(method) {
240
240
  if (method === "foundry") return "azure";
241
241
  return method === "ollama" || method === "openai-compatible" ? "replicas_openai_compatible" : "openai";
242
242
  }
243
- var ENGINE_PACKAGE_VERSION = "0.1.1266";
243
+ var ENGINE_PACKAGE_VERSION = "0.1.1267";
244
244
  var INITIALIZE_METHOD = "initialize";
245
245
  var INITIALIZED_NOTIFICATION = "initialized";
246
246
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -3,7 +3,7 @@ import { createRequire as __createRequire } from 'node:module';
3
3
  const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  AspClient
6
- } from "./chunk-6SRLEHOV.js";
6
+ } from "./chunk-LR6YGW3W.js";
7
7
  import {
8
8
  ASTER_BASE_URL,
9
9
  ASTER_PROVIDER,
@@ -13,7 +13,7 @@ import {
13
13
  isRecord,
14
14
  readOllamaAuthEnv,
15
15
  readOpenAICompatibleAuthEnv
16
- } from "./chunk-FNPPBKJI.js";
16
+ } from "./chunk-RLVAL5RN.js";
17
17
 
18
18
  // src/managers/codex-asp/notification-dispatch.ts
19
19
  var TURN_STARTED_METHOD = "turn/started";
@@ -1950,6 +1950,16 @@ function readReplicasRuntimeEnv(readEnv, [namespacedKey, legacyKey]) {
1950
1950
  function shellQuotePosix(value) {
1951
1951
  return `'${value.split("'").join("'\\''")}'`;
1952
1952
  }
1953
+ function serializePosixEnvFile(env, unsetKeys = []) {
1954
+ return `${[
1955
+ ...[...unsetKeys].map((key) => `unset ${key}`),
1956
+ ...Object.entries(env).filter(([, value]) => value.length > 0).map(([key, value]) => `export ${key}=${shellQuotePosix(value)}`)
1957
+ ].join("\n")}
1958
+ `;
1959
+ }
1960
+ function parsePosixEnvUnsetKeys(content) {
1961
+ return content.split("\n").filter((line) => line.startsWith("unset ")).map((line) => line.slice("unset ".length).trim());
1962
+ }
1953
1963
  function parsePosixEnvFile(content) {
1954
1964
  const result = {};
1955
1965
  let pos = 0;
@@ -3529,6 +3539,7 @@ Use this when:
3529
3539
  - You encounter a linear.app issue link and need to understand the task
3530
3540
  - You need to update an issue's state or add a comment
3531
3541
  - You need to search Linear issues
3542
+ - You start working on a Linear issue and need to attach it to this workspace
3532
3543
  - A Linear request failed with an authentication error`;
3533
3544
  var REFERENCE7 = `# Linear Integration
3534
3545
 
@@ -3538,6 +3549,16 @@ In all new workspaces, Linear credentials stay on the Replicas server and the wo
3538
3549
 
3539
3550
  Download protected attachments with \`await replicas.linear.download(url)\`; this returns a \`Response\` without exposing the provider token.
3540
3551
 
3552
+ ## Attach an issue you own
3553
+
3554
+ When you are the one working on an issue (assigned to it, or asked to take it over), attach it once, right when you start:
3555
+
3556
+ \`\`\`ts
3557
+ await replicas.linear.attachIssue({ issue: 'ENG-123' });
3558
+ \`\`\`
3559
+
3560
+ This opens a Replicas agent session on the issue, like delegating it to Replicas: your progress and final responses stream into it, replies there reach this workspace, and the issue moves to In Progress. Attaching the same issue again is a no-op. Do not attach issues you only read, file, or hand to someone else.
3561
+
3541
3562
  ## Check access
3542
3563
 
3543
3564
  Call Linear directly; integration listing is optional. If \`replicas.integrations.list()\` returns a 5xx or \`Internal server error\`, skip it and continue through \`replicas.linear.graphql\`.
@@ -10545,6 +10566,8 @@ export {
10545
10566
  REPLICAS_RUNTIME_ENV_ALIASES,
10546
10567
  readReplicasRuntimeEnv,
10547
10568
  shellQuotePosix,
10569
+ serializePosixEnvFile,
10570
+ parsePosixEnvUnsetKeys,
10548
10571
  parsePosixEnvFile,
10549
10572
  ENGINE_PORT,
10550
10573
  DESKTOP_STREAM_PORT,
@@ -4,7 +4,7 @@ const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  SUBPROCESS_MAX_BUFFER,
6
6
  execFileAsync
7
- } from "./chunk-AHPBQSXT.js";
7
+ } from "./chunk-A24AON3O.js";
8
8
  import {
9
9
  isRecord as isRecord2
10
10
  } from "./chunk-UZSNFLDQ.js";
@@ -18,9 +18,11 @@ import {
18
18
  isRecord,
19
19
  isValidAgentProvider,
20
20
  parsePosixEnvFile,
21
+ parsePosixEnvUnsetKeys,
21
22
  provisionedDeviceSchema,
22
- readReplicasRuntimeEnv
23
- } from "./chunk-FNPPBKJI.js";
23
+ readReplicasRuntimeEnv,
24
+ serializePosixEnvFile
25
+ } from "./chunk-RLVAL5RN.js";
24
26
 
25
27
  // src/runtime-env-loader.ts
26
28
  import { readFileSync } from "fs";
@@ -46,7 +48,7 @@ function loadRuntimeEnvFile(values = readRuntimeEnvFile()) {
46
48
  }
47
49
 
48
50
  // src/engine-env.ts
49
- import { readFileSync as readFileSync2 } from "fs";
51
+ import { readFileSync as readFileSync2, writeFileSync } from "fs";
50
52
  import { homedir as homedir2 } from "os";
51
53
  import { join as join2 } from "path";
52
54
  var SANDBOX_IMAGE_VERSION_FILE = "/usr/local/lib/replicas-sandbox-image-version";
@@ -180,6 +182,17 @@ function reloadEngineEnv(runtimeEnvValues) {
180
182
  ENGINE_ENV = loadEngineEnv(runtimeEnvValues);
181
183
  return ENGINE_ENV;
182
184
  }
185
+ function setLinearSessionId(linearSessionId) {
186
+ const path = join2(homedir2(), ".replicas", "runtime-env.sh");
187
+ const content = readFileSync2(path, "utf-8");
188
+ const key = REPLICAS_RUNTIME_ENV_ALIASES.linearSessionId[0];
189
+ writeFileSync(path, serializePosixEnvFile(
190
+ { ...parsePosixEnvFile(content), [key]: linearSessionId },
191
+ parsePosixEnvUnsetKeys(content).filter((unset) => unset !== key)
192
+ ));
193
+ process.env[key] = linearSessionId;
194
+ ENGINE_ENV.REPLICAS_LINEAR_SESSION_ID = linearSessionId;
195
+ }
183
196
  function setAgentCredentialSnapshot(provider, { type, scope, revision, account, credentialId }) {
184
197
  if (!scope) return;
185
198
  ENGINE_ENV.REPLICAS_AGENT_CREDENTIALS = {
@@ -349,6 +362,7 @@ export {
349
362
  readRuntimeEnvFile,
350
363
  ENGINE_ENV,
351
364
  reloadEngineEnv,
365
+ setLinearSessionId,
352
366
  setAgentCredentialSnapshot,
353
367
  monolithRequest,
354
368
  monolithService
@@ -3,13 +3,13 @@ import { createRequire as __createRequire } from 'node:module';
3
3
  const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  evaluateCommandProtection
6
- } from "./chunk-BN2QDNKJ.js";
7
- import "./chunk-SJIWGPT3.js";
8
- import "./chunk-AHPBQSXT.js";
6
+ } from "./chunk-4OUPQ3AD.js";
7
+ import "./chunk-WZT5BWBM.js";
8
+ import "./chunk-A24AON3O.js";
9
9
  import {
10
10
  isRecord
11
11
  } from "./chunk-UZSNFLDQ.js";
12
- import "./chunk-FNPPBKJI.js";
12
+ import "./chunk-RLVAL5RN.js";
13
13
  import "./chunk-VEQXQN22.js";
14
14
 
15
15
  // src/command-protection-hook.ts
@@ -13,12 +13,12 @@ import {
13
13
  recoverCompletedTurn,
14
14
  spawnMuseMsp,
15
15
  startMuseSession
16
- } from "./chunk-CKJ7VTKU.js";
16
+ } from "./chunk-NRCWWD5S.js";
17
17
  import {
18
18
  AppServerProcess,
19
19
  buildCodexAgentEnv
20
- } from "./chunk-6SRLEHOV.js";
21
- import "./chunk-AHPBQSXT.js";
20
+ } from "./chunk-LR6YGW3W.js";
21
+ import "./chunk-A24AON3O.js";
22
22
  import {
23
23
  AGENT,
24
24
  OPENCODE_GO_PROVIDER,
@@ -28,7 +28,7 @@ import {
28
28
  headlessAgentUsagePath,
29
29
  isRecord,
30
30
  withTimeout
31
- } from "./chunk-FNPPBKJI.js";
31
+ } from "./chunk-RLVAL5RN.js";
32
32
  import "./chunk-VEQXQN22.js";
33
33
 
34
34
  // src/headless-agent.ts
package/dist/src/index.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  evaluateCommandProtection,
28
28
  extractToolCommand,
29
29
  reportCommandProtectionBlock
30
- } from "./chunk-BN2QDNKJ.js";
30
+ } from "./chunk-4OUPQ3AD.js";
31
31
  import {
32
32
  ACCOUNT_RATE_LIMITS_UPDATED_METHOD,
33
33
  AGENT_MESSAGE_DELTA_METHOD,
@@ -64,10 +64,10 @@ import {
64
64
  spawnMuseMsp,
65
65
  startMuseSession,
66
66
  uuidV7
67
- } from "./chunk-CKJ7VTKU.js";
67
+ } from "./chunk-NRCWWD5S.js";
68
68
  import {
69
69
  publishedPullRequestUrls
70
- } from "./chunk-KGZ2ER7G.js";
70
+ } from "./chunk-FRKSSPNO.js";
71
71
  import {
72
72
  ACCOUNT_RATE_LIMITS_READ_METHOD,
73
73
  AsyncLock,
@@ -140,7 +140,7 @@ import {
140
140
  timestampFromSeconds,
141
141
  upsertCredentialFileLines,
142
142
  writeSecureCredentialFile
143
- } from "./chunk-V6EDWBWV.js";
143
+ } from "./chunk-6VDGJBXA.js";
144
144
  import {
145
145
  ENGINE_ENV,
146
146
  monolithRequest,
@@ -148,16 +148,17 @@ import {
148
148
  readRuntimeEnvFile,
149
149
  reloadEngineEnv,
150
150
  resolveDiffBase,
151
- setAgentCredentialSnapshot
152
- } from "./chunk-SJIWGPT3.js";
151
+ setAgentCredentialSnapshot,
152
+ setLinearSessionId
153
+ } from "./chunk-WZT5BWBM.js";
153
154
  import {
154
155
  getCodexModelProvider
155
- } from "./chunk-6SRLEHOV.js";
156
+ } from "./chunk-LR6YGW3W.js";
156
157
  import {
157
158
  SUBPROCESS_MAX_BUFFER,
158
159
  execAsync,
159
160
  execFileAsync
160
- } from "./chunk-AHPBQSXT.js";
161
+ } from "./chunk-A24AON3O.js";
161
162
  import {
162
163
  isRecord as isRecord2
163
164
  } from "./chunk-UZSNFLDQ.js";
@@ -399,7 +400,7 @@ import {
399
400
  workspaceTokenRequestSchema,
400
401
  workspaceTokenResponseSchema,
401
402
  wrapInTag
402
- } from "./chunk-FNPPBKJI.js";
403
+ } from "./chunk-RLVAL5RN.js";
403
404
  import {
404
405
  cloneMcpConfig,
405
406
  ensureCompatibilityImports,
@@ -11604,7 +11605,7 @@ var CodingAgentManager = class {
11604
11605
  onSaveSessionId;
11605
11606
  onEvent;
11606
11607
  onUsageUpdate;
11607
- linearSessionId;
11608
+ topLevel;
11608
11609
  chatId;
11609
11610
  originChatId;
11610
11611
  hostOnTurnComplete;
@@ -11636,7 +11637,7 @@ var CodingAgentManager = class {
11636
11637
  });
11637
11638
  this.subagentMcpChatId = options.parentChatId === null && options.provider && SUBAGENT_MCP_HARNESSES.includes(options.provider) ? options.chatId : void 0;
11638
11639
  this.usesAutoCompactTokens = options.provider === "claude" || options.provider === "codex";
11639
- this.linearSessionId = options.linearSessionId;
11640
+ this.topLevel = options.parentChatId === null;
11640
11641
  this.chatId = options.chatId;
11641
11642
  this.originChatId = options.originChatId;
11642
11643
  this.hostOnTurnComplete = options.onTurnComplete;
@@ -11990,6 +11991,10 @@ ${note}` };
11990
11991
  }
11991
11992
  return parts.length > 0 ? parts.join("\n\n") : void 0;
11992
11993
  }
11994
+ // Read per turn, since an agent can attach its workspace to a Linear issue mid-chat.
11995
+ get linearSessionId() {
11996
+ return this.topLevel ? ENGINE_ENV.REPLICAS_LINEAR_SESSION_ID : void 0;
11997
+ }
11993
11998
  emitInterruptedQueueEvent(queue) {
11994
11999
  const linearSessionId = this.linearSessionId;
11995
12000
  if (!linearSessionId || queue.length === 0) {
@@ -12084,11 +12089,14 @@ function isLinearThoughtEvent(event) {
12084
12089
  return event.content.type === "thought";
12085
12090
  }
12086
12091
  var LinearEventForwarder = class {
12087
- linearSessionId;
12092
+ getLinearSessionId;
12088
12093
  taskAccumulator = new TaskAccumulator();
12089
12094
  latestThoughtEvent = null;
12090
- constructor(linearSessionId) {
12091
- this.linearSessionId = linearSessionId;
12095
+ constructor(getLinearSessionId) {
12096
+ this.getLinearSessionId = getLinearSessionId;
12097
+ }
12098
+ get linearSessionId() {
12099
+ return this.getLinearSessionId();
12092
12100
  }
12093
12101
  sendPlan(plan) {
12094
12102
  if (!this.linearSessionId || !plan) return;
@@ -13751,7 +13759,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
13751
13759
  this.activePromptStream = promptStream;
13752
13760
  this.activeSessionSignature = signature;
13753
13761
  this.activeSessionModel = claudeCodeModel;
13754
- this.sessionLinearForwarder = new LinearEventForwarder(this.linearSessionId);
13762
+ this.sessionLinearForwarder = new LinearEventForwarder(() => this.linearSessionId);
13755
13763
  this.sessionLoop = this.runSessionLoop(response).catch((err) => {
13756
13764
  console.error("[ClaudeManager] Session loop crashed:", err);
13757
13765
  });
@@ -13762,7 +13770,6 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
13762
13770
  });
13763
13771
  }
13764
13772
  async runSessionLoop(response) {
13765
- const linearSessionId = this.linearSessionId;
13766
13773
  const iterator = response[Symbol.asyncIterator]();
13767
13774
  let loopError = null;
13768
13775
  let suppressLinearResponseFlush = false;
@@ -13820,6 +13827,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
13820
13827
  }
13821
13828
  await this.handleMessage(msg);
13822
13829
  if (this.activeQuery !== response) break;
13830
+ const linearSessionId = this.linearSessionId;
13823
13831
  if (linearSessionId && this.sessionLinearForwarder) {
13824
13832
  this.sessionLinearForwarder.processClaudeEventForPlan(msg);
13825
13833
  this.sessionLinearForwarder.sendEvent(convertClaudeEvent(msg, linearSessionId));
@@ -15148,10 +15156,9 @@ ${text.slice(-24e3)}`
15148
15156
  let completedResolved = false;
15149
15157
  const completedItems = [];
15150
15158
  const agentMessageDeltas = /* @__PURE__ */ new Map();
15151
- const linearSessionId = this.linearSessionId;
15152
15159
  const model = request.model ?? DEFAULT_MODEL;
15153
15160
  let tempImagePaths = [];
15154
- const linearForwarder = new LinearEventForwarder(linearSessionId);
15161
+ const linearForwarder = new LinearEventForwarder(() => this.linearSessionId);
15155
15162
  const matchesTurn = (notificationThreadId, notificationTurnId) => notificationThreadId === threadId && (!observedTurnId || notificationTurnId === null || notificationTurnId === observedTurnId || notificationTurnId === this.activeTurnId);
15156
15163
  const resolveIfGoalIdle = () => {
15157
15164
  if (!lastCompletedTurn || completedResolved) return;
@@ -15197,7 +15204,7 @@ ${text.slice(-24e3)}`
15197
15204
  agentMessageDeltas.clear();
15198
15205
  this.startTurn(notification.params.turn);
15199
15206
  interruptIfStopped();
15200
- linearForwarder.sendEvent(convertCodexAspNotification(notification, linearSessionId ?? ""));
15207
+ linearForwarder.sendEvent(convertCodexAspNotification(notification, this.linearSessionId ?? ""));
15201
15208
  },
15202
15209
  [TURN_PLAN_UPDATED_METHOD]: (notification) => {
15203
15210
  if (!matchesTurn(notification.params.threadId, notification.params.turnId)) return;
@@ -15214,7 +15221,7 @@ ${text.slice(-24e3)}`
15214
15221
  notification.params.turnId,
15215
15222
  itemToTranscriptItem(notification.params.item, timestampFromMilliseconds(notification.params.startedAtMs), "in_progress")
15216
15223
  );
15217
- linearForwarder.sendEvent(convertCodexAspNotification(notification, linearSessionId ?? ""));
15224
+ linearForwarder.sendEvent(convertCodexAspNotification(notification, this.linearSessionId ?? ""));
15218
15225
  },
15219
15226
  [ITEM_COMPLETED_METHOD]: (notification) => {
15220
15227
  if (!matchesTurn(notification.params.threadId, notification.params.turnId)) return;
@@ -15229,7 +15236,7 @@ ${text.slice(-24e3)}`
15229
15236
  itemFailed ? "failed" : "completed"
15230
15237
  )
15231
15238
  );
15232
- linearForwarder.sendEvent(convertCodexAspNotification(notification, linearSessionId ?? ""));
15239
+ linearForwarder.sendEvent(convertCodexAspNotification(notification, this.linearSessionId ?? ""));
15233
15240
  const completedItem = notification.params.item;
15234
15241
  const toolResult = completedItem.type === "commandExecution" ? { toolName: "commandExecution", toolInput: { command: completedItem.command }, output: completedItem.aggregatedOutput, success: completedItem.exitCode === 0 } : completedItem.type === "mcpToolCall" ? { toolName: completedItem.tool, toolInput: completedItem.arguments, output: completedItem.result, success: completedItem.status === "completed" && !completedItem.error } : completedItem.type === "dynamicToolCall" ? { toolName: completedItem.tool, toolInput: completedItem.arguments, output: completedItem.contentItems, success: completedItem.success === true } : null;
15235
15242
  if (toolResult) {
@@ -15994,8 +16001,7 @@ var CursorManager = class extends CodingAgentManager {
15994
16001
  const aborted = new Promise((resolve7) => {
15995
16002
  this.abortActiveTurn = () => resolve7(TURN_ABORTED);
15996
16003
  });
15997
- const linearSessionId = this.linearSessionId;
15998
- const linearForwarder = new LinearEventForwarder(linearSessionId);
16004
+ const linearForwarder = new LinearEventForwarder(() => this.linearSessionId);
15999
16005
  const clearReconnectNoticeTimer = () => {
16000
16006
  if (!reconnectNoticeTimer) return;
16001
16007
  clearTimeout(reconnectNoticeTimer);
@@ -16050,6 +16056,7 @@ var CursorManager = class extends CodingAgentManager {
16050
16056
  markCursorActivity();
16051
16057
  const event = next.value;
16052
16058
  this.recordHistoryEvent(`cursor-${event.type}`, event, this.historyFile);
16059
+ const linearSessionId = this.linearSessionId;
16053
16060
  if (linearSessionId) {
16054
16061
  linearForwarder.sendEvent(convertCursorEvent(event, linearSessionId));
16055
16062
  }
@@ -17094,8 +17101,7 @@ var OpencodeManager = class extends CodingAgentManager {
17094
17101
  async processMessageInternal(request) {
17095
17102
  const provider = await getOpencodeProvider();
17096
17103
  const controller = new AbortController();
17097
- const linearSessionId = this.linearSessionId;
17098
- const linearForwarder = new LinearEventForwarder(linearSessionId);
17104
+ const linearForwarder = new LinearEventForwarder(() => this.linearSessionId);
17099
17105
  this.handledAccountRateLimit = false;
17100
17106
  this.activeAbortController = controller;
17101
17107
  this.activeLinearForwarder = linearForwarder;
@@ -61134,7 +61140,6 @@ ${note}`;
61134
61140
  onChatCredential,
61135
61141
  lastSenderKey: persisted.lastSenderKey,
61136
61142
  onLastSenderKeyChanged,
61137
- linearSessionId: persisted.parentChatId === null ? ENGINE_ENV.REPLICAS_LINEAR_SESSION_ID : void 0,
61138
61143
  parentChatId: persisted.parentChatId
61139
61144
  };
61140
61145
  let provider;
@@ -63529,6 +63534,12 @@ data: ${JSON.stringify("Terminal session not found")}
63529
63534
  app2.post("/workspace-name", async (c) => {
63530
63535
  return c.json({ success: true, repos: [] });
63531
63536
  });
63537
+ app2.put("/linear-session", async (c) => {
63538
+ const body = z4.object({ linearSessionId: z4.string().min(1) }).safeParse(await c.req.json().catch(() => null));
63539
+ if (!body.success) return c.json(jsonError("linearSessionId is required"), 400);
63540
+ setLinearSessionId(body.data.linearSessionId);
63541
+ return c.json({ success: true });
63542
+ });
63532
63543
  app2.get("/previews", async (c) => {
63533
63544
  try {
63534
63545
  const previews = await previewService.listPreviews();
@@ -3,13 +3,13 @@ import { createRequire as __createRequire } from 'node:module';
3
3
  const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  publishedPullRequestUrls
6
- } from "./chunk-KGZ2ER7G.js";
6
+ } from "./chunk-FRKSSPNO.js";
7
7
  import {
8
8
  isRecord
9
9
  } from "./chunk-UZSNFLDQ.js";
10
10
  import {
11
11
  shouldRefreshPullRequests
12
- } from "./chunk-FNPPBKJI.js";
12
+ } from "./chunk-RLVAL5RN.js";
13
13
  import "./chunk-VEQXQN22.js";
14
14
 
15
15
  // src/services/post-tool-pr-notifier.ts
@@ -11,7 +11,7 @@ import {
11
11
  spawnSubagentRequestSchema,
12
12
  subagentResponseSchema,
13
13
  waitSubagentRequestSchema
14
- } from "./chunk-FNPPBKJI.js";
14
+ } from "./chunk-RLVAL5RN.js";
15
15
  import "./chunk-VEQXQN22.js";
16
16
 
17
17
  // src/subagent-mcp.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.1266",
3
+ "version": "0.1.1267",
4
4
  "description": "Lightweight API server for Replicas workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
@@ -90,6 +90,11 @@ const linear = {
90
90
  method: 'POST',
91
91
  body: { query, variables, operationName },
92
92
  }),
93
+ attachIssue: ({ issue }) =>
94
+ request('/v1/engine/linear/issues/attach', {
95
+ method: 'POST',
96
+ body: { issue },
97
+ }),
93
98
  };
94
99
 
95
100
  const slack = {
@@ -1,6 +1,14 @@
1
1
  // Generated from shared/src by generate-workspace-sdk-types.mjs; do not edit.
2
2
  import type { PluginDescribeRequest, PluginDescribeResponse, PluginExecuteRequest, PluginExecuteResponse, PluginSearchRequest, PluginSearchResponse, WorkspaceIntegrationsResponse, WorkspacePluginSummary } from './routes/plugins';
3
3
  export type { PluginConnectionStatus, PluginId, PluginToolSchema, WorkspaceIntegrationsResponse, WorkspacePluginSummary, } from './routes/plugins';
4
+ export interface AttachedLinearIssue {
5
+ session_id: string;
6
+ issue: {
7
+ identifier: string;
8
+ title: string;
9
+ url: string;
10
+ };
11
+ }
4
12
  export interface ProviderRequestOptions {
5
13
  method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
6
14
  body?: unknown;
@@ -24,6 +32,9 @@ export interface ReplicasSdk {
24
32
  variables?: Record<string, unknown> | null;
25
33
  operationName?: string | null;
26
34
  }): Promise<T>;
35
+ attachIssue(input: {
36
+ issue: string;
37
+ }): Promise<AttachedLinearIssue>;
27
38
  };
28
39
  slack: {
29
40
  call<T = unknown>(method: string, args?: Record<string, unknown>): Promise<T>;