replicas-engine 0.1.1266 → 0.1.1268

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-5VLMXM2M.js";
12
+ import "./chunk-L3I3HTJC.js";
13
+ import "./chunk-4M66PUK6.js";
14
+ import "./chunk-47XPVTWF.js";
15
15
  import "./chunk-UZSNFLDQ.js";
16
- import "./chunk-FNPPBKJI.js";
16
+ import "./chunk-EVSWPNVE.js";
17
17
  import "./chunk-VEQXQN22.js";
18
18
  export {
19
19
  CODEX_ULTRAFAST_SERVICE_TIER,
@@ -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-EVSWPNVE.js";
7
7
 
8
8
  // src/utils/exec.ts
9
9
  import { exec, execFile } from "child_process";
@@ -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-47XPVTWF.js";
7
7
  import {
8
8
  isVersionBelow
9
- } from "./chunk-FNPPBKJI.js";
9
+ } from "./chunk-EVSWPNVE.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.1268";
244
244
  var INITIALIZE_METHOD = "initialize";
245
245
  var INITIALIZED_NOTIFICATION = "initialized";
246
246
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -10,15 +10,15 @@ import {
10
10
  resolveDiffBase,
11
11
  runGitCommand,
12
12
  setAgentCredentialSnapshot
13
- } from "./chunk-SJIWGPT3.js";
13
+ } from "./chunk-L3I3HTJC.js";
14
14
  import {
15
15
  AppServerProcess,
16
16
  buildCodexAgentEnv
17
- } from "./chunk-6SRLEHOV.js";
17
+ } from "./chunk-4M66PUK6.js";
18
18
  import {
19
19
  SUBPROCESS_MAX_BUFFER,
20
20
  execFileAsync
21
- } from "./chunk-AHPBQSXT.js";
21
+ } from "./chunk-47XPVTWF.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-EVSWPNVE.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-PWBMRGII.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-PWBMRGII.js");
317
317
  await restartCodexAspHostIfRunning2();
318
318
  }
319
319
  setAgentCredentialSnapshot("codex", data);
@@ -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;
@@ -2448,6 +2458,7 @@ var REPLICAS_MCP_TOOLS = {
2448
2458
  saveChannelPreset: "save_channel_preset",
2449
2459
  deleteChannelPreset: "delete_channel_preset",
2450
2460
  updateChannelSettings: "update_channel_settings",
2461
+ setOrganizationProactivity: "set_organization_proactivity",
2451
2462
  setThreadMuted: "set_thread_muted",
2452
2463
  spawnSubagent: "spawn_subagent",
2453
2464
  messageSubagent: "message_subagent",
@@ -2517,6 +2528,7 @@ var createEnvironmentDeviceToolInputSchema = z16.object({ ...environmentMcpPath,
2517
2528
 
2518
2529
  // ../shared/src/scout.ts
2519
2530
  var SCOUT_SOURCE_TYPES = ["slack", "linear"];
2531
+ var SCOUT_PROACTIVITY_LEVELS = ["conservative", "balanced", "proactive"];
2520
2532
  var SCOUT_PRESET_NAME_MAX_LENGTH = 50;
2521
2533
  var SCOUT_PRESET_ICONS = [
2522
2534
  "users",
@@ -3529,6 +3541,7 @@ Use this when:
3529
3541
  - You encounter a linear.app issue link and need to understand the task
3530
3542
  - You need to update an issue's state or add a comment
3531
3543
  - You need to search Linear issues
3544
+ - You start working on a Linear issue and need to attach it to this workspace
3532
3545
  - A Linear request failed with an authentication error`;
3533
3546
  var REFERENCE7 = `# Linear Integration
3534
3547
 
@@ -3538,6 +3551,16 @@ In all new workspaces, Linear credentials stay on the Replicas server and the wo
3538
3551
 
3539
3552
  Download protected attachments with \`await replicas.linear.download(url)\`; this returns a \`Response\` without exposing the provider token.
3540
3553
 
3554
+ ## Attach an issue you own
3555
+
3556
+ 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:
3557
+
3558
+ \`\`\`ts
3559
+ await replicas.linear.attachIssue({ issue: 'ENG-123' });
3560
+ \`\`\`
3561
+
3562
+ 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.
3563
+
3541
3564
  ## Check access
3542
3565
 
3543
3566
  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\`.
@@ -9610,7 +9633,11 @@ var scoutUpdateChannelSettingsToolInputSchema = scoutSlackConfirmationSchema.ext
9610
9633
  external_id: z23.string().describe("Slack channel id or Linear team id."),
9611
9634
  monitored: z23.boolean().optional().describe("`false` stops Scout from handling the source: it excludes a Slack channel or stops monitoring a Linear team. `true` resumes a Slack channel or starts monitoring a Linear team, and only an organization admin can ask for that. Omit to keep it."),
9612
9635
  preset_id: z23.string().nullable().optional().describe("Preset to assign; `null` removes the preset. Omit to keep it."),
9613
- instructions: z23.string().nullable().optional().describe("Complete channel-specific instructions, applied after the preset; replaces the existing text. `null` clears them. Omit to keep them.")
9636
+ instructions: z23.string().nullable().optional().describe("Complete channel-specific instructions, applied after the preset; replaces the existing text. `null` clears them. Omit to keep them."),
9637
+ proactivity: z23.enum([...SCOUT_PROACTIVITY_LEVELS, "organization"]).optional().describe("Slack only: this channel's proactivity level, overriding the organization's for this channel or group DM alone. Set it only when the person explicitly asks for this channel. `organization` makes it follow the organization's level again. Omit to keep it. 1:1 DMs are always addressed to Replicas, so they take no level.")
9638
+ });
9639
+ var scoutSetOrganizationProactivityToolInputSchema = scoutSlackConfirmationSchema.extend({
9640
+ proactivity: z23.enum(SCOUT_PROACTIVITY_LEVELS).describe("The level every Slack channel and group DM follows unless it has its own.")
9614
9641
  });
9615
9642
  var scoutDeleteChannelPresetToolInputSchema = scoutSlackConfirmationSchema.extend({
9616
9643
  preset_id: z23.string().describe(`Id of the preset to delete, from \`${REPLICAS_MCP_TOOLS.listChannelSettings}\`.`)
@@ -10545,6 +10572,8 @@ export {
10545
10572
  REPLICAS_RUNTIME_ENV_ALIASES,
10546
10573
  readReplicasRuntimeEnv,
10547
10574
  shellQuotePosix,
10575
+ serializePosixEnvFile,
10576
+ parsePosixEnvUnsetKeys,
10548
10577
  parsePosixEnvFile,
10549
10578
  ENGINE_PORT,
10550
10579
  DESKTOP_STREAM_PORT,
@@ -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-4M66PUK6.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-EVSWPNVE.js";
17
17
 
18
18
  // src/managers/codex-asp/notification-dispatch.ts
19
19
  var TURN_STARTED_METHOD = "turn/started";
@@ -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-47XPVTWF.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-EVSWPNVE.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
@@ -5,7 +5,7 @@ import {
5
5
  extractCommandProtectionCommandText,
6
6
  isRecord,
7
7
  parseCodeHostPrUrl
8
- } from "./chunk-FNPPBKJI.js";
8
+ } from "./chunk-EVSWPNVE.js";
9
9
 
10
10
  // src/services/published-pull-request-urls.ts
11
11
  function publishedPullRequestUrls(result) {
@@ -5,14 +5,14 @@ import {
5
5
  getOriginDefaultBranch,
6
6
  monolithRequest,
7
7
  runGitCommand
8
- } from "./chunk-SJIWGPT3.js";
8
+ } from "./chunk-L3I3HTJC.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-EVSWPNVE.js";
16
16
 
17
17
  // src/services/command-protection-service.ts
18
18
  import { readFile, stat } from "fs/promises";
@@ -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-UP4LVTOW.js";
7
+ import "./chunk-L3I3HTJC.js";
8
+ import "./chunk-47XPVTWF.js";
9
9
  import {
10
10
  isRecord
11
11
  } from "./chunk-UZSNFLDQ.js";
12
- import "./chunk-FNPPBKJI.js";
12
+ import "./chunk-EVSWPNVE.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-JI4QXAY3.js";
17
17
  import {
18
18
  AppServerProcess,
19
19
  buildCodexAgentEnv
20
- } from "./chunk-6SRLEHOV.js";
21
- import "./chunk-AHPBQSXT.js";
20
+ } from "./chunk-4M66PUK6.js";
21
+ import "./chunk-47XPVTWF.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-EVSWPNVE.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-UP4LVTOW.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-JI4QXAY3.js";
68
68
  import {
69
69
  publishedPullRequestUrls
70
- } from "./chunk-KGZ2ER7G.js";
70
+ } from "./chunk-RS4AYG3B.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-5VLMXM2M.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-L3I3HTJC.js";
153
154
  import {
154
155
  getCodexModelProvider
155
- } from "./chunk-6SRLEHOV.js";
156
+ } from "./chunk-4M66PUK6.js";
156
157
  import {
157
158
  SUBPROCESS_MAX_BUFFER,
158
159
  execAsync,
159
160
  execFileAsync
160
- } from "./chunk-AHPBQSXT.js";
161
+ } from "./chunk-47XPVTWF.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-EVSWPNVE.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-RS4AYG3B.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-EVSWPNVE.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-EVSWPNVE.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.1268",
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>;