@myagentroam/node 0.9.64 → 0.9.65

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.
@@ -10,11 +10,18 @@ const runtimeCredentialCapability = () => ({
10
10
  websocket: true,
11
11
  httpVersions: ['1.1', '2']
12
12
  });
13
- function reportedPlatform() {
14
- return process.platform === 'win32' ? 'windows' : 'linux';
13
+ export function reportedPlatform(platform = process.platform) {
14
+ if (platform === 'win32')
15
+ return 'windows';
16
+ if (platform === 'darwin')
17
+ return 'macos';
18
+ return 'linux';
19
+ }
20
+ function isSupportedPlatform(platform = process.platform) {
21
+ return platform === 'win32' || platform === 'linux' || platform === 'darwin';
15
22
  }
16
23
  export function unavailableCapabilities() {
17
- if (process.platform !== 'win32' && process.platform !== 'linux') {
24
+ if (!isSupportedPlatform()) {
18
25
  throw new Error('NODE_PLATFORM_UNSUPPORTED');
19
26
  }
20
27
  return {
@@ -34,7 +41,7 @@ export function unavailableCapabilities() {
34
41
  };
35
42
  }
36
43
  export function detectCapabilities(commands = {}) {
37
- if (process.platform !== 'win32' && process.platform !== 'linux') {
44
+ if (!isSupportedPlatform()) {
38
45
  throw new Error('NODE_PLATFORM_UNSUPPORTED');
39
46
  }
40
47
  const codex = probeCodex(commands.codex);
@@ -66,7 +73,7 @@ export function detectCapabilities(commands = {}) {
66
73
  };
67
74
  }
68
75
  export async function detectCapabilitiesAsync(commands = {}) {
69
- if (process.platform !== 'win32' && process.platform !== 'linux') {
76
+ if (!isSupportedPlatform()) {
70
77
  throw new Error('NODE_PLATFORM_UNSUPPORTED');
71
78
  }
72
79
  const [codex, claudeCode, openCode, runtimeCommands] = await Promise.all([
@@ -56,9 +56,9 @@ export function isCodexRolloutMissingError(error) {
56
56
  /^thread not loaded:\s*/i.test(error.rpcMessage)));
57
57
  }
58
58
  /**
59
- * Local JSON-RPC client for a Node-supervised Codex App Server. Linux uses a
60
- * private Unix socket by default; Windows uses stdio. Neither is exposed to
61
- * MAR Server or the browser.
59
+ * Local JSON-RPC client for a Node-supervised Codex App Server. Linux/macOS
60
+ * use a private Unix socket by default; Windows uses stdio. Neither is exposed
61
+ * to MAR Server or the browser.
62
62
  */
63
63
  export class CodexAppServerClient {
64
64
  options;
@@ -345,8 +345,8 @@ export class CodexAppServerClient {
345
345
  transportMode() {
346
346
  const requested = this.options.transport ?? 'auto';
347
347
  if (requested === 'auto')
348
- return process.platform === 'linux' ? 'unix' : 'stdio';
349
- if (requested === 'unix' && process.platform !== 'linux') {
348
+ return process.platform === 'linux' || process.platform === 'darwin' ? 'unix' : 'stdio';
349
+ if (requested === 'unix' && process.platform !== 'linux' && process.platform !== 'darwin') {
350
350
  throw new Error('CODEX_UNIX_SOCKET_PLATFORM_UNSUPPORTED');
351
351
  }
352
352
  return requested;
@@ -483,8 +483,11 @@ function stdioTransport(child) {
483
483
  destroy: () => child.stdout.destroy()
484
484
  };
485
485
  }
486
- function privateSocketPath() {
487
- return join(tmpdir(), `myagentroam-codex-${process.pid}-${randomUUID()}.sock`);
486
+ export function privateSocketPath(directory = tmpdir(), processId = process.pid, entropy = randomUUID()) {
487
+ // macOS has a shorter Unix-domain socket pathname limit than Linux, and its
488
+ // per-user TMPDIR is comparatively long. The process ID plus 64 random bits
489
+ // keeps concurrent sockets distinct while leaving room for that directory.
490
+ return join(directory, `m-${processId}-${entropy.replaceAll('-', '').slice(0, 16)}.sock`);
488
491
  }
489
492
  function connectUnix(socketPath, timeoutMs) {
490
493
  return new Promise((resolve, reject) => {
package/dist/connector.js CHANGED
@@ -840,7 +840,8 @@ export class NodeConnector {
840
840
  this.clearMissionRetry(session.id);
841
841
  const prepared = this.prepareMissionSession(session);
842
842
  const missionSession = prepared.session;
843
- const replacing = this.missionRuntime.get(session.id)?.status === 'active';
843
+ const activeRun = this.runtime.activeSessionRun(session.id);
844
+ const replacing = activeRun !== undefined && this.runtime.currentExecutionId(activeRun.id) !== undefined;
844
845
  this.continuousRunCoordinator.removeMissionQueue(session.id);
845
846
  const mission = this.missionRuntime.start(session.id, objective);
846
847
  this.publishMissionState(missionSession, mission);
@@ -1019,7 +1020,11 @@ export class NodeConnector {
1019
1020
  this.terminalManager =
1020
1021
  options.terminalManager ??
1021
1022
  new TerminalManager({
1022
- platform: this.capabilities.platform === 'windows' ? 'win32' : 'linux'
1023
+ platform: this.capabilities.platform === 'windows'
1024
+ ? 'win32'
1025
+ : this.capabilities.platform === 'macos'
1026
+ ? 'darwin'
1027
+ : 'linux'
1023
1028
  });
1024
1029
  this.terminalManager.onSummary((summary) => this.workspaceCoordinator.persistTerminal(summary));
1025
1030
  this.terminalChannel = new NodeTerminalChannel({
@@ -1394,6 +1399,7 @@ export class NodeConnector {
1394
1399
  if (current?.status !== 'active' ||
1395
1400
  current.id !== input.mission.id ||
1396
1401
  current.revision !== input.mission.revision) {
1402
+ this.continuousRunCoordinator.removeMissionQueue(input.sessionId, current?.status === 'active' ? { id: current.id, revision: current.revision } : undefined);
1397
1403
  if (this.missionContinuationPending.get(input.sessionId) === attemptKey)
1398
1404
  this.missionContinuationPending.delete(input.sessionId);
1399
1405
  return;
@@ -56,19 +56,24 @@ async function credential(operation) {
56
56
  async function invoke(args) {
57
57
  const remote = await currentRemote(args);
58
58
  const matched = remote === undefined ? { matched: false } : await gitCredentialRequest('/identity', { remote });
59
- const environment = matched.matched === true &&
59
+ const identity = matched.matched === true &&
60
60
  typeof matched.name === 'string' &&
61
61
  typeof matched.email === 'string' &&
62
62
  !/[\r\n\0]/u.test(matched.name + matched.email)
63
- ? {
63
+ ? { name: matched.name, email: matched.email }
64
+ : undefined;
65
+ const environment = identity === undefined
66
+ ? process.env
67
+ : {
64
68
  ...process.env,
65
- GIT_AUTHOR_NAME: matched.name,
66
- GIT_COMMITTER_NAME: matched.name,
67
- GIT_AUTHOR_EMAIL: matched.email,
68
- GIT_COMMITTER_EMAIL: matched.email
69
- }
70
- : process.env;
71
- return run(gitExecutable(), args, { environment });
69
+ GIT_AUTHOR_NAME: identity.name,
70
+ GIT_COMMITTER_NAME: identity.name,
71
+ GIT_AUTHOR_EMAIL: identity.email,
72
+ GIT_COMMITTER_EMAIL: identity.email
73
+ };
74
+ return run(gitExecutable(), identity === undefined
75
+ ? args
76
+ : ['-c', `user.name=${identity.name}`, '-c', `user.email=${identity.email}`, ...args], { environment });
72
77
  }
73
78
  async function currentRemote(args) {
74
79
  const cwd = gitWorkingDirectory(args);
package/dist/main.js CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { dirname, resolve } from 'node:path';
3
+ import { homedir } from 'node:os';
3
4
  import { NodeConnector } from './connector.js';
4
5
  import { loadNodeConfig, nodeConfigPath, nodeDatabasePath, nodeDataDirectory } from './config.js';
5
6
  import { getNodeHealth } from './health.js';
@@ -45,9 +46,11 @@ function readOption(args, name) {
45
46
  return index >= 0 ? args[index + 1] : undefined;
46
47
  }
47
48
  function defaultServicePath() {
48
- return process.platform === 'win32'
49
- ? resolve('data/myagentroam-node-service.json')
50
- : resolve('data/myagentroam-node.service');
49
+ if (process.platform === 'win32')
50
+ return resolve('data/myagentroam-node-service.json');
51
+ if (process.platform === 'darwin')
52
+ return resolve(homedir(), 'Library', 'LaunchAgents', 'com.myagentroam.node.plist');
53
+ return resolve('data/myagentroam-node.service');
51
54
  }
52
55
  async function writeCurrentServiceDefinition(output, configPath) {
53
56
  const nodeConfig = await loadNodeConfig(configPath);
@@ -4,6 +4,8 @@ export const BUNDLED_RIPGREP_VERSION = '15.1.0';
4
4
  const TARGETS = {
5
5
  'linux-x64': ['linux-x64', 'rg'],
6
6
  'linux-arm64': ['linux-arm64', 'rg'],
7
+ 'darwin-x64': ['darwin-x64', 'rg'],
8
+ 'darwin-arm64': ['darwin-arm64', 'rg'],
7
9
  'win32-x64': ['win32-x64', 'rg.exe'],
8
10
  'win32-arm64': ['win32-arm64', 'rg.exe']
9
11
  };
@@ -350,10 +350,13 @@ export class ContinuousRunCoordinator {
350
350
  if (lease !== undefined)
351
351
  this.environmentLeases.set(nextId, lease);
352
352
  }
353
- removeMissionQueue(sessionId) {
353
+ removeMissionQueue(sessionId, preservedMission) {
354
354
  for (const [id, pending] of this.preparedInputs) {
355
355
  if (pending.sessionId !== sessionId || pending.mission === undefined)
356
356
  continue;
357
+ if (pending.mission.id === preservedMission?.id &&
358
+ pending.mission.revision === preservedMission.revision)
359
+ continue;
357
360
  const item = this.options.runtime.getQueueItem(id);
358
361
  if (item !== undefined)
359
362
  this.deleteQueueItem(id);
@@ -56,7 +56,7 @@ export class WorkbenchManifestService {
56
56
  terminal: {
57
57
  available: true,
58
58
  reasonCode: null,
59
- supportsPty: capabilities.platform === 'linux',
59
+ supportsPty: capabilities.platform === 'linux' || capabilities.platform === 'macos',
60
60
  supportsConPty: capabilities.platform === 'windows',
61
61
  supportsReplay: true,
62
62
  supportsReadonlyAttach: true,
package/dist/service.js CHANGED
@@ -17,14 +17,49 @@ export function windowsServiceDefinition(executable, configPath, entrypoint) {
17
17
  account: 'LocalService'
18
18
  }, undefined, 2);
19
19
  }
20
+ export function launchdServiceDefinition(executable, configPath, entrypoint) {
21
+ const argumentsList = [
22
+ executable,
23
+ ...(entrypoint === undefined ? [] : [entrypoint]),
24
+ 'supervise',
25
+ '--config',
26
+ configPath
27
+ ]
28
+ .map((argument) => ` <string>${escapeXml(argument)}</string>`)
29
+ .join('\n');
30
+ return `<?xml version="1.0" encoding="UTF-8"?>
31
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
32
+ <plist version="1.0">
33
+ <dict>
34
+ <key>Label</key>
35
+ <string>com.myagentroam.node</string>
36
+ <key>ProgramArguments</key>
37
+ <array>
38
+ ${argumentsList}
39
+ </array>
40
+ <key>EnvironmentVariables</key>
41
+ <dict>
42
+ <key>PATH</key>
43
+ <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
44
+ </dict>
45
+ <key>RunAtLoad</key>
46
+ <true/>
47
+ <key>KeepAlive</key>
48
+ <true/>
49
+ </dict>
50
+ </plist>
51
+ `;
52
+ }
20
53
  export async function writeServiceDefinition(outputPath, executable, configPath, platform = process.platform, entrypoint, writablePaths = []) {
21
54
  const contents = platform === 'linux'
22
55
  ? systemdUnit(executable, configPath, entrypoint, writablePaths)
23
56
  : platform === 'win32'
24
57
  ? windowsServiceDefinition(executable, configPath, entrypoint)
25
- : (() => {
26
- throw new Error('NODE_PLATFORM_UNSUPPORTED');
27
- })();
58
+ : platform === 'darwin'
59
+ ? launchdServiceDefinition(executable, configPath, entrypoint)
60
+ : (() => {
61
+ throw new Error('NODE_PLATFORM_UNSUPPORTED');
62
+ })();
28
63
  await mkdir(dirname(outputPath), { recursive: true, mode: 0o755 });
29
64
  await writeFile(outputPath, contents, { mode: 0o644 });
30
65
  if (platform !== 'win32')
@@ -36,3 +71,21 @@ export async function removeServiceDefinition(outputPath) {
36
71
  function escapeSystemd(value) {
37
72
  return JSON.stringify(value);
38
73
  }
74
+ function escapeXml(value) {
75
+ return value.replace(/[<>&'"]/gu, (character) => {
76
+ switch (character) {
77
+ case '<':
78
+ return '&lt;';
79
+ case '>':
80
+ return '&gt;';
81
+ case '&':
82
+ return '&amp;';
83
+ case "'":
84
+ return '&apos;';
85
+ case '"':
86
+ return '&quot;';
87
+ default:
88
+ return character;
89
+ }
90
+ });
91
+ }
package/dist/terminal.js CHANGED
@@ -34,7 +34,9 @@ export class TerminalManager {
34
34
  summaryListeners = new Set();
35
35
  idleTimer;
36
36
  constructor(options = {}) {
37
- this.platform = options.platform ?? (process.platform === 'win32' ? 'win32' : 'linux');
37
+ this.platform =
38
+ options.platform ??
39
+ (process.platform === 'win32' ? 'win32' : process.platform === 'darwin' ? 'darwin' : 'linux');
38
40
  this.cwd = options.cwd ?? homedir();
39
41
  this.profiles = options.profiles ?? defaultTerminalProfiles(this.platform);
40
42
  if (this.profiles.length === 0 || !this.profiles.some((profile) => profile.isDefault)) {
package/dist/workspace.js CHANGED
@@ -939,7 +939,7 @@ export function normalizeWorkspacePath(input, platform = hostPlatform()) {
939
939
  }
940
940
  return normalized.replace(/\\+$/, '').toLowerCase();
941
941
  }
942
- if (platform !== 'linux') {
942
+ if (platform !== 'linux' && platform !== 'darwin') {
943
943
  throw new Error('WORKSPACE_PLATFORM_UNSUPPORTED');
944
944
  }
945
945
  const normalized = posix.normalize(input);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myagentroam/node",
3
- "version": "0.9.64",
3
+ "version": "0.9.65",
4
4
  "description": "MyAgentRoam Node runtime CLI.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -27,8 +27,8 @@
27
27
  "node-pty": "1.1.0",
28
28
  "ws": "^8.21.3",
29
29
  "zod": "4.4.3",
30
- "@myagentroam/agent": "0.9.64",
31
- "@myagentroam/protocol": "0.9.64"
30
+ "@myagentroam/agent": "0.9.65",
31
+ "@myagentroam/protocol": "0.9.65"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@types/ws": "^8.18.1"
Binary file
Binary file
@@ -14,6 +14,18 @@
14
14
  "executable": "linux-arm64/rg",
15
15
  "executableSha256": "968cabe8efed72fd8fd482cb76b6084fcb695fc5293af7fb62296b02f487fb69"
16
16
  },
17
+ "darwin-x64": {
18
+ "archive": "ripgrep-15.1.0-x86_64-apple-darwin.tar.gz",
19
+ "archiveSha256": "64811cb24e77cac3057d6c40b63ac9becf9082eedd54ca411b475b755d334882",
20
+ "executable": "darwin-x64/rg",
21
+ "executableSha256": "3bafa7e6ee51ba3ac4ed065883484a309be09b26ea6dad561ae4049bfe049c50"
22
+ },
23
+ "darwin-arm64": {
24
+ "archive": "ripgrep-15.1.0-aarch64-apple-darwin.tar.gz",
25
+ "archiveSha256": "378e973289176ca0c6054054ee7f631a065874a352bf43f0fa60ef079b6ba715",
26
+ "executable": "darwin-arm64/rg",
27
+ "executableSha256": "4fdf1d8365af224bc70e3c1490d8461d859c37cc70e739a11e987af0215f3e94"
28
+ },
17
29
  "win32-x64": {
18
30
  "archive": "ripgrep-15.1.0-x86_64-pc-windows-msvc.zip",
19
31
  "archiveSha256": "124510b94b6baa3380d051fdf4650eaa80a302c876d611e9dba0b2e18d87493a",