replicas-engine 0.1.763 → 0.1.765

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.
@@ -5,11 +5,11 @@ import {
5
5
  getCodexAspHost,
6
6
  restartCodexAspHost,
7
7
  restartCodexAspHostIfRunning
8
- } from "./chunk-4L5B23W2.js";
9
- import "./chunk-F6AAYYY2.js";
10
- import "./chunk-27TRTL3O.js";
8
+ } from "./chunk-4OLXBASZ.js";
9
+ import "./chunk-WFWT2YFN.js";
10
+ import "./chunk-SQX57KJM.js";
11
11
  import "./chunk-UZSNFLDQ.js";
12
- import "./chunk-5YY2575X.js";
12
+ import "./chunk-UQETFAOK.js";
13
13
  import "./chunk-VEQXQN22.js";
14
14
  export {
15
15
  getCodexAspHost,
@@ -5,18 +5,18 @@ import {
5
5
  ENGINE_ENV,
6
6
  monolithRequest,
7
7
  setAgentCredentialSnapshot
8
- } from "./chunk-F6AAYYY2.js";
8
+ } from "./chunk-WFWT2YFN.js";
9
9
  import {
10
10
  AppServerProcess,
11
11
  buildCodexAgentEnv
12
- } from "./chunk-27TRTL3O.js";
12
+ } from "./chunk-SQX57KJM.js";
13
13
  import {
14
14
  CODEX_AUTH_ENV_KEYS,
15
15
  CODEX_AUTH_ENV_KEYS_BY_METHOD,
16
16
  codexAuthEnvFromResponse,
17
17
  createErrorResult,
18
18
  createSuccessResult
19
- } from "./chunk-5YY2575X.js";
19
+ } from "./chunk-UQETFAOK.js";
20
20
 
21
21
  // src/managers/codex-token-manager.ts
22
22
  import { promises as fs } from "fs";
@@ -232,7 +232,7 @@ var CodexTokenManager = class extends BaseRefreshManager {
232
232
  const data = await response.json();
233
233
  await this.applyCredentialsResponse(data);
234
234
  if (restartOnChange && CODEX_AUTH_ENV_KEYS.some((key, index) => process.env[key] !== previousEnv[index])) {
235
- const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-PFFZQGXZ.js");
235
+ const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-X3XQGPRO.js");
236
236
  await restartCodexAspHostIfRunning2();
237
237
  }
238
238
  if (data.scope) {
@@ -3,12 +3,12 @@ import { createRequire as __createRequire } from 'node:module';
3
3
  const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  monolithRequest
6
- } from "./chunk-F6AAYYY2.js";
6
+ } from "./chunk-WFWT2YFN.js";
7
7
  import {
8
8
  extractCommandProtectionCommandText,
9
9
  findGitCommitSignals,
10
10
  findPrMergeSignals
11
- } from "./chunk-5YY2575X.js";
11
+ } from "./chunk-UQETFAOK.js";
12
12
 
13
13
  // src/services/command-protection-service.ts
14
14
  var DEFAULT_COMMAND_PROTECTION_BLOCK_MESSAGE = "Blocked by Replicas command protection.";
@@ -4,7 +4,7 @@ const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  findCodeHostPullRequestUrls,
6
6
  mayCreatePullRequest
7
- } from "./chunk-5YY2575X.js";
7
+ } from "./chunk-UQETFAOK.js";
8
8
 
9
9
  // src/services/post-tool-pr-notifier.ts
10
10
  async function notifyPostToolUse(toolName, toolInput, toolResult) {
@@ -4,7 +4,7 @@ const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  HOOK_EXEC_MAX_BUFFER_BYTES,
6
6
  isVersionBelow
7
- } from "./chunk-5YY2575X.js";
7
+ } from "./chunk-UQETFAOK.js";
8
8
 
9
9
  // src/utils/codex-agent-env.ts
10
10
  function buildCodexAgentEnv(source = process.env) {
@@ -241,7 +241,7 @@ var DEFAULT_CODEX_ARGS = [
241
241
  var MIN_CODEX_CLI_VERSION = "0.153.3";
242
242
  var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
243
243
  var codexCliVersionEnsured = null;
244
- var ENGINE_PACKAGE_VERSION = "0.1.763";
244
+ var ENGINE_PACKAGE_VERSION = "0.1.765";
245
245
  var INITIALIZE_METHOD = "initialize";
246
246
  var INITIALIZED_NOTIFICATION = "initialized";
247
247
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -1056,10 +1056,17 @@ var INVALID_WORKSPACE_SIZE_ERROR = `Invalid size: must be one of ${WORKSPACE_SIZ
1056
1056
 
1057
1057
  // ../shared/src/github/url.ts
1058
1058
  var GITHUB_HOST_RE = /(^|@|\/\/)github\.com[:/]/;
1059
+ var GITHUB_REPO_SLUG_RE = /github\.com[/:]([^/]+)\/([^/]+?)(?:\.git)?(?:[/?#]|$)/i;
1059
1060
  function isGitHubUrl(url) {
1060
1061
  if (!url) return false;
1061
1062
  return GITHUB_HOST_RE.test(url);
1062
1063
  }
1064
+ function parseRepoUrlSlug(url) {
1065
+ if (!url) return null;
1066
+ const match = url.match(GITHUB_REPO_SLUG_RE);
1067
+ if (!match) return null;
1068
+ return { owner: match[1].toLowerCase(), repo: match[2].toLowerCase() };
1069
+ }
1063
1070
 
1064
1071
  // ../shared/src/runtime-env.ts
1065
1072
  var REPLICAS_RUNTIME_ENV_ALIASES = {
@@ -1147,8 +1154,19 @@ function githubOwnerTokens(access) {
1147
1154
  }
1148
1155
  return ownerTokens;
1149
1156
  }
1157
+ function getGitHubAccessToken(access, repositoryUrl) {
1158
+ if (repositoryUrl === void 0) {
1159
+ const tokens2 = new Set(Object.values(access));
1160
+ return tokens2.size === 1 ? tokens2.values().next().value ?? null : null;
1161
+ }
1162
+ const slug = parseRepoUrlSlug(repositoryUrl);
1163
+ if (!slug) return null;
1164
+ const exact = access[`${slug.owner}/${slug.repo}`];
1165
+ if (exact) return exact;
1166
+ const tokens = githubOwnerTokens(access).get(slug.owner);
1167
+ return tokens?.size === 1 ? tokens.values().next().value ?? null : null;
1168
+ }
1150
1169
  function githubCredentialLines(access) {
1151
- if (typeof access === "string") return [`https://x-access-token:${access}@github.com`];
1152
1170
  const entries = Object.entries(access);
1153
1171
  const ownerTokens = githubOwnerTokens(access);
1154
1172
  return [...entries.flatMap(([repository, token]) => [
@@ -1519,7 +1537,8 @@ function upsertDisplayMessage(messages, message) {
1519
1537
  }
1520
1538
  function applyToolInputEvent(event, messages, provider, state, questionFilter) {
1521
1539
  if (event.type === "replicas-tool-input-request" && typeof event.payload.toolUseId === "string" && typeof event.payload.requestId === "string" && (Array.isArray(event.payload.options) || Array.isArray(event.payload.questions))) {
1522
- const resolved = state.resolutions.get(event.payload.toolUseId);
1540
+ const previous = state.resolutions.get(event.payload.toolUseId);
1541
+ const resolved = previous && (!previous.requestId || previous.requestId === event.payload.requestId) ? previous : void 0;
1523
1542
  const inputRequest = {
1524
1543
  requestId: event.payload.requestId,
1525
1544
  status: resolved?.selectionId === "aborted" || resolved?.selectionId === "declined" ? "aborted" : resolved ? "resolved" : "pending",
@@ -1535,12 +1554,13 @@ function applyToolInputEvent(event, messages, provider, state, questionFilter) {
1535
1554
  }
1536
1555
  if (event.type === "replicas-tool-input-resolved" && typeof event.payload.toolUseId === "string" && typeof event.payload.selectionId === "string") {
1537
1556
  const resolved = {
1557
+ ...typeof event.payload.requestId === "string" ? { requestId: event.payload.requestId } : {},
1538
1558
  selectionId: event.payload.selectionId,
1539
1559
  ...typeof event.payload.selectionSummary === "string" ? { selectionSummary: event.payload.selectionSummary } : {}
1540
1560
  };
1541
1561
  state.resolutions.set(event.payload.toolUseId, resolved);
1542
1562
  const inputRequest = state.requests.get(event.payload.toolUseId);
1543
- if (inputRequest) {
1563
+ if (inputRequest && (!resolved.requestId || resolved.requestId === inputRequest.requestId)) {
1544
1564
  inputRequest.status = resolved.selectionId === "aborted" || resolved.selectionId === "declined" ? "aborted" : "resolved";
1545
1565
  inputRequest.selectionId = resolved.selectionId;
1546
1566
  if (resolved.selectionSummary) inputRequest.selectionSummary = resolved.selectionSummary;
@@ -1589,6 +1609,7 @@ function skillNameFromToolCall(tool, input) {
1589
1609
  return parseSkillFilePath(input);
1590
1610
  }
1591
1611
  function createCallDisplayMessage(message) {
1612
+ if (message.inputRequest) return { ...message, type: "tool_call" };
1592
1613
  const skillName = message.server.toLowerCase() === "skills" ? message.tool : skillNameFromToolCall(message.tool, message.input);
1593
1614
  if (skillName === null) return { ...message, type: "tool_call" };
1594
1615
  return {
@@ -4498,12 +4519,12 @@ function parseMuseEvents(events) {
4498
4519
  id: `muse-tool-${item.itemId}`,
4499
4520
  server: "muse",
4500
4521
  tool: typeof item.tool === "string" ? item.tool : "tool",
4522
+ inputRequest: inputState.requests.get(item.itemId),
4501
4523
  input: isRecord(input) ? input : typeof input === "string" ? input : void 0,
4502
4524
  output: typeof item.visibleOutput === "string" ? item.visibleOutput : item.failureReason === void 0 ? void 0 : stringifyDisplayValue(item.failureReason),
4503
4525
  status: item.status === "failed" || item.status === "rejected" ? "failed" : terminal ? "completed" : "in_progress",
4504
4526
  timestamp: typeof item.recordedAt === "string" ? item.recordedAt : event.timestamp
4505
4527
  });
4506
- if (message.type === "tool_call") message.inputRequest = inputState.requests.get(item.itemId);
4507
4528
  upsertDisplayMessage(messages, message);
4508
4529
  }
4509
4530
  }
@@ -7584,6 +7605,7 @@ export {
7584
7605
  GIT_CREDENTIAL_HELPER_FILENAME,
7585
7606
  GITHUB_CREDENTIAL_REFRESH_PATH,
7586
7607
  GITLAB_CREDENTIAL_REFRESH_PATH,
7608
+ getGitHubAccessToken,
7587
7609
  githubCredentialLines,
7588
7610
  buildGitCredentialHelperScript,
7589
7611
  parseGitRemote,
@@ -15,7 +15,7 @@ import {
15
15
  isValidRelayBaseProvider,
16
16
  parsePosixEnvFile,
17
17
  readReplicasRuntimeEnv
18
- } from "./chunk-5YY2575X.js";
18
+ } from "./chunk-UQETFAOK.js";
19
19
 
20
20
  // src/engine-env.ts
21
21
  import { readFileSync as readFileSync2 } from "fs";
@@ -3,12 +3,12 @@ import { createRequire as __createRequire } from 'node:module';
3
3
  const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  evaluateCommandProtection
6
- } from "./chunk-QSTCS5V3.js";
7
- import "./chunk-F6AAYYY2.js";
6
+ } from "./chunk-CWSZPPD6.js";
7
+ import "./chunk-WFWT2YFN.js";
8
8
  import {
9
9
  isRecord
10
10
  } from "./chunk-UZSNFLDQ.js";
11
- import "./chunk-5YY2575X.js";
11
+ import "./chunk-UQETFAOK.js";
12
12
  import "./chunk-VEQXQN22.js";
13
13
 
14
14
  // src/command-protection-hook.ts
@@ -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-QSTCS5V3.js";
6
+ } from "./chunk-CWSZPPD6.js";
7
7
  import {
8
8
  notifyPostToolUse
9
- } from "./chunk-UD6DSFSB.js";
10
- import "./chunk-F6AAYYY2.js";
9
+ } from "./chunk-L2BNNGQB.js";
10
+ import "./chunk-WFWT2YFN.js";
11
11
  import "./chunk-UZSNFLDQ.js";
12
- import "./chunk-5YY2575X.js";
12
+ import "./chunk-UQETFAOK.js";
13
13
  import "./chunk-VEQXQN22.js";
14
14
 
15
15
  // src/deepseek-command-protection-plugin.ts
@@ -8,12 +8,12 @@ import {
8
8
  import {
9
9
  AppServerProcess,
10
10
  buildCodexAgentEnv
11
- } from "./chunk-27TRTL3O.js";
11
+ } from "./chunk-SQX57KJM.js";
12
12
  import {
13
13
  AGENT,
14
14
  getMemoryOutputSafetyViolation,
15
15
  headlessAgentRequestSchema
16
- } from "./chunk-5YY2575X.js";
16
+ } from "./chunk-UQETFAOK.js";
17
17
  import "./chunk-VEQXQN22.js";
18
18
 
19
19
  // src/headless-agent.ts
package/dist/src/index.js CHANGED
@@ -91,7 +91,7 @@ import {
91
91
  evaluateCommandProtection,
92
92
  extractToolCommand,
93
93
  reportCommandProtectionBlock
94
- } from "./chunk-QSTCS5V3.js";
94
+ } from "./chunk-CWSZPPD6.js";
95
95
  import {
96
96
  ACCOUNT_RATE_LIMITS_UPDATED_METHOD,
97
97
  AGENT_MESSAGE_DELTA_METHOD,
@@ -124,20 +124,20 @@ import {
124
124
  recordCredentialFallback,
125
125
  recordExhaustedCredential,
126
126
  restartCodexAspHost
127
- } from "./chunk-4L5B23W2.js";
127
+ } from "./chunk-4OLXBASZ.js";
128
128
  import {
129
129
  ENGINE_ENV,
130
130
  IS_WARMING_MODE,
131
131
  monolithRequest,
132
132
  monolithService,
133
133
  setAgentCredentialSnapshot
134
- } from "./chunk-F6AAYYY2.js";
134
+ } from "./chunk-WFWT2YFN.js";
135
135
  import {
136
136
  AspClient,
137
137
  SUBPROCESS_MAX_BUFFER,
138
138
  execAsync,
139
139
  execFileAsync
140
- } from "./chunk-27TRTL3O.js";
140
+ } from "./chunk-SQX57KJM.js";
141
141
  import {
142
142
  isRecord as isRecord2
143
143
  } from "./chunk-UZSNFLDQ.js";
@@ -264,6 +264,7 @@ import {
264
264
  getCodexAspTurnResponse,
265
265
  getDefaultAgentModel,
266
266
  getEventTimestampMs,
267
+ getGitHubAccessToken,
267
268
  getGoalCommand,
268
269
  getGoalCommandObjectiveValidationError,
269
270
  getProviderDisplayName,
@@ -332,7 +333,7 @@ import {
332
333
  spawnRelaySubagentRequestSchema,
333
334
  stripAgentDiagnosticErrors,
334
335
  withTimeout
335
- } from "./chunk-5YY2575X.js";
336
+ } from "./chunk-UQETFAOK.js";
336
337
  import {
337
338
  __commonJS,
338
339
  __export,
@@ -9298,9 +9299,9 @@ var GitHubTokenManager = class extends BaseRefreshManager {
9298
9299
  throw new Error(`Token refresh failed: ${response.status} ${errorText}`);
9299
9300
  }
9300
9301
  const data = await response.json();
9301
- const ghToken = data.userToken?.token ?? data.token;
9302
+ const ghToken = getGitHubAccessToken(data.repositoryTokens) ?? "";
9302
9303
  const ghUsername = data.userToken?.username ?? "x-access-token";
9303
- await this.updateGitCredentials(data.repositoryTokens ?? ghToken);
9304
+ await this.updateGitCredentials(data.repositoryTokens);
9304
9305
  await this.updateGhHostsFile(ghToken, ghUsername);
9305
9306
  if (data.gitIdentity) {
9306
9307
  await updateGitIdentity(data.gitIdentity, "GitHubTokenManager", ["github.com"]);
@@ -17637,6 +17638,8 @@ var MuseManager = class extends CodingAgentManager {
17637
17638
  turnError = null;
17638
17639
  compactionComplete = null;
17639
17640
  pendingInput = null;
17641
+ pendingApprovals = /* @__PURE__ */ new Map();
17642
+ resolvedApprovals = /* @__PURE__ */ new Set();
17640
17643
  slashCommands = null;
17641
17644
  constructor(options) {
17642
17645
  super({ ...options, provider: "muse" });
@@ -17662,6 +17665,15 @@ var MuseManager = class extends CodingAgentManager {
17662
17665
  const client2 = new AspClient({ stdin: child.stdin, stdout: child.stdout, jsonRpcVersion: "2.0" });
17663
17666
  this.client = client2;
17664
17667
  client2.on("notification", (notification) => this.handleNotification(notification));
17668
+ client2.on("serverRequest", (request) => {
17669
+ const frame = request;
17670
+ if (isRecord(frame) && frame.method === "approval/request") {
17671
+ this.handleNotification({ method: "approval/requested", params: frame.params });
17672
+ client2.respond(request.id, {});
17673
+ } else {
17674
+ client2.reject(request.id, -32601, "Unsupported Muse request");
17675
+ }
17676
+ });
17665
17677
  child.stderr.on("data", (chunk) => console.error("[muse MSP]", chunk.toString().trimEnd()));
17666
17678
  child.on("error", (error) => this.handleProcessExit(child, error));
17667
17679
  child.on("exit", (code, signal) => this.handleProcessExit(
@@ -17680,6 +17692,7 @@ var MuseManager = class extends CodingAgentManager {
17680
17692
  } catch {
17681
17693
  this.sessionId = null;
17682
17694
  }
17695
+ if (this.sessionId) await this.refreshPendingApprovals();
17683
17696
  }
17684
17697
  if (!this.sessionId) {
17685
17698
  const result = await this.request("session/start", {
@@ -17702,12 +17715,92 @@ var MuseManager = class extends CodingAgentManager {
17702
17715
  notify(method, params) {
17703
17716
  this.client?.notify(method, params);
17704
17717
  }
17718
+ async refreshPendingApprovals() {
17719
+ if (!this.sessionId) return;
17720
+ const previous = new Map(this.pendingApprovals);
17721
+ const result = await this.request("approval/listPending", { sessionId: this.sessionId }).catch(() => null);
17722
+ if (!isRecord(result) || !Array.isArray(result.approvals)) return;
17723
+ for (const [approvalId, pending] of previous) {
17724
+ if (this.pendingApprovals.get(approvalId) === pending && !result.approvals.some((approval) => isRecord(approval) && approval.approvalId === approvalId)) {
17725
+ this.resolveApproval(approvalId, "resolved");
17726
+ }
17727
+ }
17728
+ for (const approval of result.approvals) {
17729
+ this.handleNotification({ method: "approval/requested", params: approval });
17730
+ }
17731
+ }
17732
+ resolveApproval(approvalId, selectionId, terminal = true) {
17733
+ const pending = this.pendingApprovals.get(approvalId);
17734
+ if (terminal) this.resolvedApprovals.add(approvalId);
17735
+ if (!pending) return;
17736
+ this.pendingApprovals.delete(approvalId);
17737
+ const choice = pending.availableChoices.find((choice2) => choice2.choiceId === selectionId);
17738
+ this.recordHistoryEvent("replicas-tool-input-resolved", {
17739
+ requestId: pending.requestId,
17740
+ toolUseId: pending.itemId,
17741
+ toolName: pending.toolName,
17742
+ selectionId: choice ? JSON.stringify({ approval: { options: [choice.choiceId] } }) : selectionId,
17743
+ selectionSummary: choice?.label,
17744
+ parent_tool_use_id: null
17745
+ }, this.historyFile);
17746
+ }
17747
+ handleApproval(params) {
17748
+ if (!this.sessionId || params.sessionId !== this.sessionId || typeof params.approvalId !== "string" || this.resolvedApprovals.has(params.approvalId)) return;
17749
+ const previous = this.pendingApprovals.get(params.approvalId);
17750
+ const value = { ...previous, ...params };
17751
+ const requirement = value.currentRequirementId;
17752
+ if (!isRecord(requirement) || requirement.approvalId !== params.approvalId || typeof requirement.sourceIndex !== "number" || !Number.isSafeInteger(requirement.sourceIndex) || requirement.sourceIndex < 0 || typeof value.itemId !== "string" || typeof value.toolName !== "string" || typeof value.rawArgs !== "string" || !isRecord(value.subject) || !Array.isArray(value.availableChoices)) return;
17753
+ const choices = value.availableChoices.filter((choice) => isRecord(choice) && typeof choice.choiceId === "string" && typeof choice.label === "string" && typeof choice.decision === "string" && (choice.rulePreview === void 0 || typeof choice.rulePreview === "string"));
17754
+ if (choices.length === 0 || choices.length !== value.availableChoices.length) return;
17755
+ if (previous && (requirement.sourceIndex < previous.currentRequirementId.sourceIndex || typeof params.viewCursor === "string" && params.viewCursor === previous.viewCursor)) return;
17756
+ const requestId = previous?.currentRequirementId.sourceIndex === requirement.sourceIndex ? previous.requestId : `muse-approval:${params.approvalId}:${requirement.sourceIndex}:${uuidV7()}`;
17757
+ const pending = {
17758
+ approvalId: params.approvalId,
17759
+ sessionId: this.sessionId,
17760
+ itemId: value.itemId,
17761
+ toolName: value.toolName,
17762
+ rawArgs: value.rawArgs,
17763
+ currentRequirementId: { approvalId: params.approvalId, sourceIndex: requirement.sourceIndex },
17764
+ availableChoices: choices,
17765
+ subject: value.subject,
17766
+ requestId,
17767
+ ...typeof params.viewCursor === "string" ? { viewCursor: params.viewCursor } : {},
17768
+ ...previous?.requestId === requestId ? { selectionId: previous.selectionId } : {}
17769
+ };
17770
+ if (previous && previous.requestId !== requestId) {
17771
+ this.resolveApproval(pending.approvalId, previous.selectionId ?? "resolved", false);
17772
+ }
17773
+ this.pendingApprovals.set(pending.approvalId, pending);
17774
+ const stages = Array.isArray(pending.subject.stages) ? pending.subject.stages : [];
17775
+ const stage = stages.find((stage2) => isRecord(stage2) && isRecord(stage2.requirementId) && stage2.requirementId.sourceIndex === requirement.sourceIndex);
17776
+ const stageLabel = isRecord(stage) ? ` (stage ${stage.position} of ${stage.totalStages})` : "";
17777
+ this.recordHistoryEvent("replicas-tool-input-request", {
17778
+ requestId,
17779
+ toolUseId: pending.itemId,
17780
+ toolName: pending.toolName,
17781
+ questions: [{
17782
+ id: "approval",
17783
+ prompt: `Allow ${pending.toolName}${stageLabel}?
17784
+
17785
+ ${typeof pending.subject.command === "string" ? pending.subject.command : JSON.stringify(pending.subject, null, 2)}`,
17786
+ multiSelect: false,
17787
+ allowCustom: false,
17788
+ options: choices.map((choice) => ({ id: choice.choiceId, label: choice.label, ...choice.rulePreview ? { preview: choice.rulePreview } : {} }))
17789
+ }],
17790
+ parent_tool_use_id: null
17791
+ }, this.historyFile);
17792
+ this.recordHistoryEvent("muse-item-started", {
17793
+ item: { itemId: pending.itemId, kind: "toolCall", tool: pending.toolName, args: pending.rawArgs, status: "inProgress" }
17794
+ }, this.historyFile);
17795
+ }
17705
17796
  handleProcessExit(child, error) {
17706
17797
  if (this.process !== child) return;
17707
17798
  const hadPendingRequest = (this.client?.pendingRequestCount ?? 0) > 0;
17708
17799
  this.process = null;
17709
17800
  this.client?.dispose(error);
17710
17801
  this.client = null;
17802
+ for (const approvalId of this.pendingApprovals.keys()) this.resolveApproval(approvalId, "aborted");
17803
+ this.resolvedApprovals.clear();
17711
17804
  if (this.turnComplete && !hadPendingRequest) {
17712
17805
  this.recordHistoryEvent("muse-error", { message: error.message }, this.historyFile);
17713
17806
  }
@@ -17721,6 +17814,8 @@ var MuseManager = class extends CodingAgentManager {
17721
17814
  this.process = null;
17722
17815
  this.client?.dispose();
17723
17816
  this.client = null;
17817
+ for (const approvalId of this.pendingApprovals.keys()) this.resolveApproval(approvalId, "aborted");
17818
+ this.resolvedApprovals.clear();
17724
17819
  process10?.kill("SIGTERM");
17725
17820
  }
17726
17821
  createTurnInput(text, images) {
@@ -17733,8 +17828,17 @@ var MuseManager = class extends CodingAgentManager {
17733
17828
  }
17734
17829
  handleNotification(frame) {
17735
17830
  if (!isRecord(frame) || typeof frame.method !== "string" || !isRecord(frame.params)) return;
17831
+ if (typeof frame.params.sessionId === "string" && this.sessionId && frame.params.sessionId !== this.sessionId) return;
17736
17832
  this.recordHistoryEvent(`muse-${frame.method.replaceAll("/", "-")}`, frame.params, this.historyFile);
17737
- if (frame.method === "turn/completed") {
17833
+ if (frame.method === "approval/requested" || frame.method === "approval/updated") {
17834
+ this.handleApproval(frame.params);
17835
+ } else if (frame.method === "approval/resolved" && typeof frame.params.approvalId === "string") {
17836
+ const pending = this.pendingApprovals.get(frame.params.approvalId);
17837
+ const decision = typeof frame.params.decision === "string" ? frame.params.decision : "resolved";
17838
+ const choice = pending?.availableChoices.find((choice2) => choice2.decision === decision && choice2.choiceId === pending.selectionId) ?? pending?.availableChoices.find((choice2) => choice2.decision === decision);
17839
+ this.resolveApproval(frame.params.approvalId, choice?.choiceId ?? decision);
17840
+ } else if (frame.method === "turn/completed") {
17841
+ for (const approvalId of this.pendingApprovals.keys()) this.resolveApproval(approvalId, "aborted");
17738
17842
  this.turnError = isRecord(frame.params.error) && typeof frame.params.error.message === "string" ? frame.params.error.message : null;
17739
17843
  this.activeTurnId = null;
17740
17844
  this.turnComplete?.resolve();
@@ -17877,6 +17981,7 @@ ${pending}
17877
17981
  this.activeTurnId = null;
17878
17982
  this.turnError = null;
17879
17983
  this.pendingInput = null;
17984
+ for (const approvalId of this.pendingApprovals.keys()) this.resolveApproval(approvalId, "aborted");
17880
17985
  this.compactionComplete?.resolve();
17881
17986
  this.compactionComplete = null;
17882
17987
  try {
@@ -17906,6 +18011,36 @@ ${pending}
17906
18011
  return true;
17907
18012
  }
17908
18013
  async respondToToolInput(requestId, selectionId) {
18014
+ const approval = [...this.pendingApprovals.values()].find((pending2) => pending2.requestId === requestId);
18015
+ if (approval) {
18016
+ if (!this.sessionId || approval.selectionId) return false;
18017
+ let selections;
18018
+ try {
18019
+ selections = JSON.parse(selectionId);
18020
+ } catch {
18021
+ }
18022
+ const answer = isRecord(selections) && isRecord(selections.approval) ? selections.approval : null;
18023
+ const choiceId = selectionId === "declined" ? approval.availableChoices.find((choice2) => choice2.decision === "abort" || choice2.decision === "denied")?.choiceId : answer && !answer.custom && Array.isArray(answer.options) && answer.options.length === 1 ? answer.options[0] : selectionId;
18024
+ const choice = approval.availableChoices.find((candidate) => candidate.choiceId === choiceId);
18025
+ if (!choice) return false;
18026
+ approval.selectionId = choice.choiceId;
18027
+ try {
18028
+ await this.request("approval/decide", {
18029
+ commandId: uuidV7(),
18030
+ sessionId: approval.sessionId,
18031
+ approvalId: approval.approvalId,
18032
+ requirementId: approval.currentRequirementId,
18033
+ choiceId: choice.choiceId
18034
+ });
18035
+ } catch (error) {
18036
+ approval.selectionId = void 0;
18037
+ const current = this.pendingApprovals.get(approval.approvalId);
18038
+ if (current?.requestId === requestId) current.selectionId = void 0;
18039
+ await this.refreshPendingApprovals();
18040
+ throw error;
18041
+ }
18042
+ return true;
18043
+ }
17909
18044
  if (!this.pendingInput || this.pendingInput.userInputId !== requestId || !this.sessionId) return false;
17910
18045
  const pending = this.pendingInput;
17911
18046
  if (selectionId === "declined") {
@@ -17943,7 +18078,7 @@ ${pending}
17943
18078
  return true;
17944
18079
  }
17945
18080
  isAwaitingInput() {
17946
- return this.pendingInput !== null;
18081
+ return this.pendingInput !== null || this.pendingApprovals.size > 0;
17947
18082
  }
17948
18083
  async getHistory(page2 = {}) {
17949
18084
  await this.historyFile.flush();
@@ -3,11 +3,11 @@ import { createRequire as __createRequire } from 'node:module';
3
3
  const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  notifyPostToolUse
6
- } from "./chunk-UD6DSFSB.js";
6
+ } from "./chunk-L2BNNGQB.js";
7
7
  import {
8
8
  isRecord
9
9
  } from "./chunk-UZSNFLDQ.js";
10
- import "./chunk-5YY2575X.js";
10
+ import "./chunk-UQETFAOK.js";
11
11
  import "./chunk-VEQXQN22.js";
12
12
 
13
13
  // src/post-tool-pr-hook.ts
@@ -4,7 +4,7 @@ const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  messageRelaySubagentRequestSchema,
6
6
  spawnRelaySubagentRequestSchema
7
- } from "./chunk-5YY2575X.js";
7
+ } from "./chunk-UQETFAOK.js";
8
8
  import "./chunk-VEQXQN22.js";
9
9
 
10
10
  // src/relay-mcp.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.763",
3
+ "version": "0.1.765",
4
4
  "description": "Lightweight API server for Replicas workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",