@mrrlin-dev/mcp 0.4.39 → 0.4.41

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/bin.cjs +85 -18
  2. package/package.json +2 -2
package/dist/bin.cjs CHANGED
@@ -20646,7 +20646,7 @@ var require_dist = __commonJS({
20646
20646
  // src/bin.ts
20647
20647
  var import_node_path31 = __toESM(require("node:path"), 1);
20648
20648
  var import_node_child_process18 = require("node:child_process");
20649
- var import_node_fs18 = require("node:fs");
20649
+ var import_node_fs19 = require("node:fs");
20650
20650
  var import_node_os15 = require("node:os");
20651
20651
  var import_node_path32 = __toESM(require("node:path"), 1);
20652
20652
 
@@ -36942,6 +36942,7 @@ var openApiOperationIds = {
36942
36942
  getProviderReadiness: "getProviderReadiness",
36943
36943
  putProviderReadiness: "putProviderReadiness",
36944
36944
  getConsensusConfig: "getConsensusConfig",
36945
+ getAgentProviderConfig: "getAgentProviderConfig",
36945
36946
  updateWikiPageCas: "updateWikiPageCas",
36946
36947
  promoteSpecReadyCas: "promoteSpecReadyCas",
36947
36948
  recordSpecConsensusReview: "recordSpecConsensusReview",
@@ -37027,6 +37028,10 @@ var operatorPresenceResponseSchema = external_exports.object({ data: external_ex
37027
37028
  var operatorPresenceRequestSchema = external_exports.object({ projectSlug: external_exports.string().min(1).optional() }).strict().optional();
37028
37029
  var mrrlinConsensusConfigSchema = external_exports.object({ consensusEnabled: external_exports.boolean() });
37029
37030
  var consensusConfigResponseSchema = external_exports.object({ data: mrrlinConsensusConfigSchema });
37031
+ var mrrlinAgentProviderConfigSchema = external_exports.object({
37032
+ agentProvider: external_exports.enum(["codex", "claude"])
37033
+ });
37034
+ var agentProviderConfigResponseSchema = external_exports.object({ data: mrrlinAgentProviderConfigSchema });
37030
37035
  var agentPoolSnapshotSchema = external_exports.object({
37031
37036
  collected_at: external_exports.string(),
37032
37037
  status: external_exports.enum(["ok", "unavailable"]),
@@ -41397,6 +41402,10 @@ function createMrrlinClient(config2) {
41397
41402
  const body = await request(`/operator/settings`);
41398
41403
  return operatorSettingsGetResponseSchema.parse(body).data;
41399
41404
  },
41405
+ async getAgentProviderConfig() {
41406
+ const body = await request(`/operator/agent-provider`);
41407
+ return agentProviderConfigResponseSchema.parse(body).data;
41408
+ },
41400
41409
  async updateOperatorSettings(input) {
41401
41410
  const body = await request(`/operator/settings`, {
41402
41411
  body: JSON.stringify(input),
@@ -42071,7 +42080,7 @@ Do NOT derail the current task - if the operator has an in-flight question, answ
42071
42080
  }
42072
42081
 
42073
42082
  // src/_generated/version.ts
42074
- var PKG_VERSION = "0.4.39";
42083
+ var PKG_VERSION = "0.4.41";
42075
42084
 
42076
42085
  // src/api-base-url-migrate.ts
42077
42086
  var import_node_fs3 = __toESM(require("node:fs"), 1);
@@ -42101,6 +42110,7 @@ function renderEcosystemConfig(opts) {
42101
42110
  PATH: opts.pathEnv,
42102
42111
  MRRLIN_DIRECTOR_BRIDGE_LOG: "1"
42103
42112
  };
42113
+ if (opts.user) env.USER = opts.user;
42104
42114
  if (opts.codexHome) env.CODEX_HOME = opts.codexHome;
42105
42115
  const retargeted = opts.apiBaseUrl ? retargetRetiredApiBaseUrl(opts.apiBaseUrl).baseUrl : void 0;
42106
42116
  if (opts.staging || retargeted && isStagingApiBaseUrl(retargeted)) env.MRRLIN_STAGING = "1";
@@ -48961,10 +48971,6 @@ var BROWSER_OUTWARD_TOOL_NAMES = /* @__PURE__ */ new Set([
48961
48971
  "browser_select_option"
48962
48972
  ]);
48963
48973
  var IN_PRODUCT_WRITE_TOOL_NAMES = /* @__PURE__ */ new Set(["create_task", "update_task", "create_wiki_page", "update_wiki_page", "create_inbox_item"]);
48964
- function resolveTurnRecordingObligationEnabled(env = process.env) {
48965
- const raw = (env.MRRLIN_TURN_RECORDING_OBLIGATION ?? "").trim().toLowerCase();
48966
- return !(raw === "0" || raw === "false");
48967
- }
48968
48974
  function buildBrowserAttemptReceipt(toolName) {
48969
48975
  return {
48970
48976
  kind: "attempt",
@@ -49015,7 +49021,7 @@ function createBridgeLogger(stateDir, env = process.env) {
49015
49021
  if (!oldest.done) contextSlugBySession.delete(oldest.value);
49016
49022
  }
49017
49023
  };
49018
- const turnRecordingObligationEnabled = resolveTurnRecordingObligationEnabled(env);
49024
+ const turnRecordingObligationEnabled = true;
49019
49025
  const obligationBySession = /* @__PURE__ */ new Map();
49020
49026
  const getObligationState = (sessionId) => {
49021
49027
  let state = obligationBySession.get(sessionId);
@@ -56630,6 +56636,23 @@ function checkTelemetryDefaultProject(env, warn) {
56630
56636
  "[mrrlin-mcp director-bridge] MRRLIN_TELEMETRY_DEFAULT_PROJECT is not set \u2014 telemetry for turns with no project-scoped tool call will not be uploaded. Set it in the pm2 ecosystem config to enable unattributed telemetry upload."
56631
56637
  );
56632
56638
  }
56639
+ function createSelectedProviderRefresher(deps) {
56640
+ let lastError = null;
56641
+ return () => {
56642
+ deps.read().then((config2) => {
56643
+ lastError = null;
56644
+ deps.apply(config2.agentProvider);
56645
+ }).catch((error51) => {
56646
+ const message = error51 instanceof Error ? error51.message : String(error51);
56647
+ if (message !== lastError) {
56648
+ lastError = message;
56649
+ deps.warn(
56650
+ `[mrrlin-mcp director-bridge] agent-provider refresh failed; keeping the held seat: ${message}`
56651
+ );
56652
+ }
56653
+ });
56654
+ };
56655
+ }
56633
56656
  async function startDirectorBridge() {
56634
56657
  const config2 = parseConfig();
56635
56658
  const failureLog = createFailureLog();
@@ -57403,10 +57426,12 @@ async function startDirectorBridge() {
57403
57426
  }
57404
57427
  let selectedProviderTimer = null;
57405
57428
  if (tokenProvider) {
57406
- const refreshSelectedProvider = () => {
57407
- client.getOperatorSettings().then((settings) => setSelectedProvider(settings.agentProvider)).catch(() => {
57408
- });
57409
- };
57429
+ const refreshSelectedProvider = createSelectedProviderRefresher({
57430
+ read: () => client.getAgentProviderConfig(),
57431
+ apply: setSelectedProvider,
57432
+ warn: (m) => process.stderr.write(`${m}
57433
+ `)
57434
+ });
57410
57435
  refreshSelectedProvider();
57411
57436
  selectedProviderTimer = setInterval(refreshSelectedProvider, 6e4);
57412
57437
  selectedProviderTimer.unref?.();
@@ -64996,8 +65021,42 @@ function runSetCredential(args) {
64996
65021
 
64997
65022
  // src/install-service.ts
64998
65023
  var import_node_os13 = __toESM(require("node:os"), 1);
65024
+ var import_node_fs18 = require("node:fs");
64999
65025
  var import_node_path28 = __toESM(require("node:path"), 1);
65000
65026
  var SYSTEM_PATH_DIRS = ["/usr/bin", "/bin", "/usr/sbin", "/sbin"];
65027
+ function defaultHomeOwnerUid(home) {
65028
+ try {
65029
+ return (0, import_node_fs18.statSync)(home).uid;
65030
+ } catch {
65031
+ return null;
65032
+ }
65033
+ }
65034
+ function resolveBridgeUser(deps) {
65035
+ if (deps.env.SUDO_USER?.trim()) {
65036
+ deps.log(
65037
+ "Running under sudo, so USER is left out of the service config: HOME, the pm2 daemon and the resolved user would all be root's, and Claude reads its credentials from a user's own keychain. Re-run install-service WITHOUT sudo unless you really mean to run as root."
65038
+ );
65039
+ return void 0;
65040
+ }
65041
+ let info;
65042
+ try {
65043
+ info = deps.userInfo();
65044
+ } catch {
65045
+ deps.log(
65046
+ "Could not resolve the OS user, so USER is left out of the service config. If the Claude CLI reports 'Not logged in' despite a real login, this is why."
65047
+ );
65048
+ return void 0;
65049
+ }
65050
+ const ownerUid = deps.homeOwnerUid(deps.home);
65051
+ const uidsAreMeaningful = info.uid >= 0 && ownerUid !== null && ownerUid >= 0;
65052
+ if (uidsAreMeaningful && ownerUid !== info.uid) {
65053
+ deps.log(
65054
+ `USER is left out of the service config: this process runs as '${info.username}' (uid ${info.uid}) but HOME ${deps.home} is owned by uid ${ownerUid}. Install as the user who owns that home directory, whose keychain Claude will read.`
65055
+ );
65056
+ return void 0;
65057
+ }
65058
+ return info.username;
65059
+ }
65001
65060
  function installService(deps) {
65002
65061
  if (!deps.hasSecret()) {
65003
65062
  deps.log("No agent credential found. Issue one in Settings, then run: mrrlin-mcp set-credential '<secret>'.");
@@ -65009,6 +65068,13 @@ function installService(deps) {
65009
65068
  return { ok: false };
65010
65069
  }
65011
65070
  const home = deps.env.HOME ?? import_node_os13.default.homedir();
65071
+ const user = resolveBridgeUser({
65072
+ env: deps.env,
65073
+ home,
65074
+ userInfo: deps.userInfo ?? (() => import_node_os13.default.userInfo()),
65075
+ homeOwnerUid: deps.homeOwnerUid ?? defaultHomeOwnerUid,
65076
+ log: deps.log
65077
+ });
65012
65078
  const bins = ["node", "codex", "mrrlin-mcp"].map((b) => deps.which(b));
65013
65079
  if (bins.some((b) => !b)) {
65014
65080
  deps.log("Could not resolve absolute paths for node/codex/mrrlin-mcp on PATH. Install them or fix PATH.");
@@ -65028,6 +65094,7 @@ function installService(deps) {
65028
65094
  const text = renderEcosystemConfig({
65029
65095
  cwd: resolved.cwd,
65030
65096
  home,
65097
+ user,
65031
65098
  codexHome: deps.env.CODEX_HOME?.trim() || void 0,
65032
65099
  pathEnv,
65033
65100
  staging,
@@ -65299,7 +65366,7 @@ function bootHookStatus() {
65299
65366
  for (const candidate of candidates) {
65300
65367
  const printed = (0, import_node_child_process18.spawnSync)("launchctl", ["print", `gui/${uid}/${candidate.label}`], { encoding: "utf8" });
65301
65368
  if (printed.status !== 0) continue;
65302
- if (!(0, import_node_fs18.existsSync)(candidate.plist)) continue;
65369
+ if (!(0, import_node_fs19.existsSync)(candidate.plist)) continue;
65303
65370
  const out = printed.stdout ?? "";
65304
65371
  const runs = /^\s*runs\s*=\s*(\d+)/m.exec(out);
65305
65372
  const exitCode = /^\s*last exit code\s*=\s*(-?\d+)/m.exec(out);
@@ -65583,7 +65650,7 @@ async function main() {
65583
65650
  }
65584
65651
  try {
65585
65652
  const codexHome = process.env.CODEX_HOME ?? import_node_path32.default.join(process.env.HOME ?? (0, import_node_os15.homedir)(), ".codex");
65586
- (0, import_node_fs18.rmSync)(import_node_path32.default.join(codexHome, "prompts", "report-issue.md"), { force: true });
65653
+ (0, import_node_fs19.rmSync)(import_node_path32.default.join(codexHome, "prompts", "report-issue.md"), { force: true });
65587
65654
  } catch {
65588
65655
  }
65589
65656
  const claudeResult = await installClaude({ binPath, force, serveEnv });
@@ -65644,8 +65711,8 @@ async function main() {
65644
65711
  env: process.env,
65645
65712
  cwd: process.cwd(),
65646
65713
  writeFile: (p, c) => {
65647
- (0, import_node_fs18.mkdirSync)(import_node_path32.default.dirname(p), { recursive: true, mode: 448 });
65648
- (0, import_node_fs18.writeFileSync)(p, c, { mode: 384 });
65714
+ (0, import_node_fs19.mkdirSync)(import_node_path32.default.dirname(p), { recursive: true, mode: 448 });
65715
+ (0, import_node_fs19.writeFileSync)(p, c, { mode: 384 });
65649
65716
  },
65650
65717
  runPm2: pm2Runner,
65651
65718
  which: whichBin,
@@ -65663,7 +65730,7 @@ async function main() {
65663
65730
  runPm2: (a) => ({ code: pm2Runner(a).code }),
65664
65731
  removeFile: (p) => {
65665
65732
  try {
65666
- (0, import_node_fs18.rmSync)(p, { force: true });
65733
+ (0, import_node_fs19.rmSync)(p, { force: true });
65667
65734
  } catch {
65668
65735
  }
65669
65736
  },
@@ -65684,7 +65751,7 @@ async function main() {
65684
65751
  runPm2: (a) => ({ code: pm2Runner(a).code }),
65685
65752
  removeFile: (p) => {
65686
65753
  try {
65687
- (0, import_node_fs18.rmSync)(p, { force: true });
65754
+ (0, import_node_fs19.rmSync)(p, { force: true });
65688
65755
  } catch {
65689
65756
  }
65690
65757
  },
@@ -65711,7 +65778,7 @@ async function main() {
65711
65778
  log(`codex config NOT modified: ${error51 instanceof Error ? error51.message : String(error51)}`);
65712
65779
  }
65713
65780
  try {
65714
- (0, import_node_fs18.rmSync)(import_node_path32.default.join(home, ".mrrlin"), { recursive: true, force: true });
65781
+ (0, import_node_fs19.rmSync)(import_node_path32.default.join(home, ".mrrlin"), { recursive: true, force: true });
65715
65782
  } catch {
65716
65783
  }
65717
65784
  log("removed ~/.mrrlin");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrrlin-dev/mcp",
3
- "version": "0.4.39",
3
+ "version": "0.4.41",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "mrrlin-mcp": "dist/bin.cjs"
@@ -21,8 +21,8 @@
21
21
  "@types/ws": "^8.18.1",
22
22
  "esbuild": "^0.24.0",
23
23
  "tsx": "^4.22.3",
24
- "@mrrlin/agent-client": "0.0.0",
25
24
  "@mrrlin/client": "0.0.0",
25
+ "@mrrlin/agent-client": "0.0.0",
26
26
  "@mrrlin/director-e2e": "0.0.0",
27
27
  "@mrrlin/schemas": "0.0.0",
28
28
  "@mrrlin/tsconfig": "0.0.0",