@myagentroam/node 0.9.180 → 0.10.2

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.
package/NOTICE CHANGED
@@ -2,3 +2,10 @@ MyAgentRoam
2
2
  Copyright 2026 MyAgentRoam contributors
3
3
 
4
4
  This product includes software developed by the MyAgentRoam project.
5
+
6
+ Enterprise implementation and product composition:
7
+ Copyright 2026 aCHAOS
8
+ Author and licensing contact: aCHAOS (achaosxyz@gmail.com)
9
+ Licensed under MyAgentRoam Enterprise Source-Available License 1.0; see
10
+ ee/LICENSE and LICENSING.md. Independent core and third-party notices remain
11
+ applicable; this attribution does not transfer any contributor's copyright.
@@ -1 +1 @@
1
- export const computerUseRuntimeVersion = '0.9.96';
1
+ export const computerUseRuntimeVersion = '0.10.1';
@@ -294,9 +294,6 @@ function safeRuntimePath(root, path) {
294
294
  throw new ComputerUseRuntimeError('COMPUTER_RUNTIME_MANIFEST_INVALID');
295
295
  return target;
296
296
  }
297
- function isMissing(error) {
298
- return (error instanceof Error && 'code' in error && error.code === 'ENOENT');
299
- }
300
297
  function isAlreadyExists(error) {
301
298
  return (error instanceof Error && 'code' in error && error.code === 'EEXIST');
302
299
  }
@@ -0,0 +1,43 @@
1
+ export interface ConversationHostingConfig {
2
+ readonly enabled: boolean;
3
+ /** Relative directory inside dataDirectory. */
4
+ readonly storeDirectory?: string;
5
+ readonly inactiveRetentionDays?: number;
6
+ }
7
+ export interface DirectTransferConfig {
8
+ readonly udpPortRangeBegin: number;
9
+ readonly udpPortRangeEnd: number;
10
+ }
11
+ export interface DirectTransferUdpPortRange {
12
+ readonly begin: number;
13
+ readonly end: number;
14
+ }
15
+ export interface ComputerUseConfig {
16
+ readonly enabled: boolean;
17
+ /** Development/validation override; production distributions use the managed runtime path. */
18
+ readonly runtimeExecutable?: string;
19
+ }
20
+ export interface NodeConfig {
21
+ readonly serverUrl: string;
22
+ /** Explicit roots or the platform default resolved while loading the config. */
23
+ readonly allowedRoots: readonly string[];
24
+ /** Absolute or config-relative root for SQLite, upgrades and other private Node data. */
25
+ readonly dataDirectory?: string;
26
+ readonly conversationHosting?: ConversationHostingConfig;
27
+ readonly directTransfer?: DirectTransferConfig;
28
+ readonly computerUse?: ComputerUseConfig;
29
+ readonly nodeId?: string;
30
+ readonly credential?: string;
31
+ readonly registrationToken?: string;
32
+ }
33
+ export declare function nodeConfigPath(): string;
34
+ export declare function loadNodeConfig(path?: string): Promise<NodeConfig>;
35
+ export declare function directTransferUdpPortRange(config: Pick<NodeConfig, 'directTransfer'> | undefined): DirectTransferUdpPortRange;
36
+ /** Uses the Node service account's scope when no Workspace roots are configured. */
37
+ export declare function defaultAllowedRoots(platform?: NodeJS.Platform, homePath?: string, currentDirectory?: string): readonly string[];
38
+ export declare function nodeDatabasePath(config: NodeConfig, configPath?: string): string;
39
+ export declare function nodeDataDirectory(config: NodeConfig, configPath?: string): string;
40
+ export declare function computerUseRuntimeExecutable(config: NodeConfig, configPath?: string, platform?: NodeJS.Platform, architecture?: string): string | undefined;
41
+ export declare function hostedConversationStorePath(config: NodeConfig, configPath?: string): string | undefined;
42
+ /** Credentials are always written with owner-only POSIX permissions where supported. */
43
+ export declare function saveNodeConfig(config: NodeConfig, path?: string): Promise<void>;
package/dist/config.js CHANGED
@@ -1,4 +1,5 @@
1
- import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises';
1
+ import { chmod, mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
2
+ import { randomUUID } from 'node:crypto';
2
3
  import { homedir } from 'node:os';
3
4
  import { dirname, isAbsolute, relative, resolve, sep, win32 } from 'node:path';
4
5
  import { computerUseRuntimeVersion } from './computer-use-runtime-version.js';
@@ -87,9 +88,18 @@ export function hostedConversationStorePath(config, configPath = nodeConfigPath(
87
88
  /** Credentials are always written with owner-only POSIX permissions where supported. */
88
89
  export async function saveNodeConfig(config, path = nodeConfigPath()) {
89
90
  await mkdir(dirname(path), { recursive: true, mode: 0o700 });
90
- await writeFile(path, `${JSON.stringify(config, undefined, 2)}\n`, { mode: 0o600 });
91
- if (process.platform !== 'win32') {
92
- await chmod(path, 0o600);
91
+ const temporary = `${path}.${randomUUID()}.tmp`;
92
+ try {
93
+ await writeFile(temporary, `${JSON.stringify(config, undefined, 2)}\n`, {
94
+ mode: 0o600,
95
+ flag: 'wx'
96
+ });
97
+ if (process.platform !== 'win32')
98
+ await chmod(temporary, 0o600);
99
+ await rename(temporary, path);
100
+ }
101
+ finally {
102
+ await rm(temporary, { force: true });
93
103
  }
94
104
  }
95
105
  function parseConversationHosting(value) {
package/dist/main.js CHANGED
@@ -17,10 +17,18 @@ if (command === 'run') {
17
17
  const { NodeConnector } = await import('./connector.js');
18
18
  configureNodeLog(nodeDataDirectory(await loadNodeConfig(config), config));
19
19
  const connector = new NodeConnector({ configPath: config });
20
- await connector.start();
20
+ const shutdown = () => {
21
+ void connector.stop().finally(() => process.exit(0));
22
+ };
21
23
  for (const signal of ['SIGINT', 'SIGTERM']) {
22
- process.once(signal, () => connector.stop());
24
+ process.once(signal, shutdown);
25
+ }
26
+ if (args.includes('--managed-parent')) {
27
+ if (process.send === undefined || !process.connected)
28
+ throw new Error('NODE_MANAGED_PARENT_UNAVAILABLE');
29
+ process.once('disconnect', shutdown);
23
30
  }
31
+ await connector.start();
24
32
  }
25
33
  else if (command === 'supervise') {
26
34
  if (process.argv[1] === undefined)
@@ -49,7 +49,7 @@ export class CodexRunner extends AbstractRunner {
49
49
  }).find((profile) => profile.runner === this.name);
50
50
  return { ...base, models: this.profileCache?.profile.models ?? [] };
51
51
  }
52
- cachedProfile(capabilities, environment = {}) {
52
+ cachedProfile(capabilities, _environment = {}) {
53
53
  const base = this.profile(capabilities);
54
54
  return this.profileCache === undefined ||
55
55
  this.profileCacheVersion !== capabilities.codex.version
@@ -43,7 +43,7 @@ export class OpenCodeRunner extends AbstractRunner {
43
43
  }).find((profile) => profile.runner === this.name);
44
44
  return { ...base, models: [] };
45
45
  }
46
- cachedProfile(capabilities, environment = {}) {
46
+ cachedProfile(capabilities, _environment = {}) {
47
47
  const cached = this.profileCache;
48
48
  return cached === undefined
49
49
  ? this.profile(capabilities)
@@ -70,10 +70,6 @@ function candidates(path) {
70
70
  ? [path]
71
71
  : [path, ...extensionlessSourceExtensions.map((extension) => `${path}${extension}`)];
72
72
  }
73
- function sourceFileStem(path) {
74
- const name = path.slice(path.lastIndexOf('/') + 1);
75
- return name.replace(/(?:\.d)?\.[^.]+$/u, '');
76
- }
77
73
  function unresolvedSpecifierScore(path, specifier) {
78
74
  const normalizedSpecifier = specifier.startsWith('@/') ? specifier.slice(2) : specifier;
79
75
  return trailingPathCandidateScore(path, unresolvedCandidates(normalizedSpecifier));
@@ -389,7 +389,10 @@ export class DirectTransferService {
389
389
  const complete = (error) => {
390
390
  channel.removeEventListener('bufferedamountlow', available);
391
391
  channel.removeEventListener('close', closed);
392
- error === undefined ? resolve() : reject(error);
392
+ if (error === undefined)
393
+ resolve();
394
+ else
395
+ reject(error);
393
396
  };
394
397
  const available = () => complete();
395
398
  const closed = () => complete(new Error('DIRECT_CHANNEL_CLOSED'));
@@ -1798,18 +1798,6 @@ function publishedTemplateEntry(value) {
1798
1798
  resolvedTarget
1799
1799
  };
1800
1800
  }
1801
- function publishedTemplateFiles(value) {
1802
- if (!Array.isArray(value))
1803
- throw new Error('CONVERSATION_TEMPLATE_VERSION_CORRUPTED');
1804
- const paths = new Set();
1805
- return value.map((candidate) => {
1806
- const file = publishedTemplateFile(candidate);
1807
- if (paths.has(file.relativePath))
1808
- throw new Error('CONVERSATION_TEMPLATE_VERSION_CORRUPTED');
1809
- paths.add(file.relativePath);
1810
- return file;
1811
- });
1812
- }
1813
1801
  function publishedTemplateFile(value, requireKind = false) {
1814
1802
  if (!record(value) ||
1815
1803
  (requireKind && value.kind !== 'FILE') ||
@@ -22,10 +22,6 @@ const MAX_TAGS_BYTES = 512 * 1024 * 1024;
22
22
  const MAX_CANDIDATES = 100;
23
23
  const MAX_RESULTS = 20;
24
24
  const MAX_REFERENCES = 100;
25
- const MAX_TAG_LINE_BYTES = 16 * 1024;
26
- const READ_BLOCK_BYTES = 4096;
27
- const MAX_TARGET_LINE_SCAN_BYTES = MAX_SOURCE_BYTES;
28
- const MAX_TARGET_PREVIEW_CHARACTERS = 512;
29
25
  /**
30
26
  * Builds a demand-driven, standard u-ctags declaration index. It never keeps
31
27
  * a complete symbol table, watcher, or idle child process in memory.
@@ -77,15 +77,15 @@ export class WorkspaceFileService {
77
77
  : readWorkspaceFileContentRange(workspacePath, path, offset, limit);
78
78
  }
79
79
  readDirect(workspace, input, workspacePath = workspace.path) {
80
- const service = this;
80
+ const readContent = this.readContent.bind(this);
81
81
  return (async function* () {
82
- const initial = (await service.readContent(workspace, { path: input.path, offset: input.range?.offset ?? 0, limit: 1 }, workspacePath));
82
+ const initial = (await readContent(workspace, { path: input.path, offset: input.range?.offset ?? 0, limit: 1 }, workspacePath));
83
83
  if (initial.size !== input.size || initial.sourceRevision !== input.revision)
84
84
  throw new Error('DIRECT_FILE_REVISION_CHANGED');
85
85
  let offset = input.range?.offset ?? 0;
86
86
  const endOffset = input.range === undefined ? input.size : input.range.offset + input.range.length;
87
87
  while (offset < endOffset) {
88
- const range = (await service.readContent(workspace, {
88
+ const range = (await readContent(workspace, {
89
89
  path: input.path,
90
90
  offset,
91
91
  limit: Math.min(512 * 1024, endOffset - offset)
@@ -44,8 +44,8 @@ export class WorkspaceQueueWorkbenchService {
44
44
  version: queue.version,
45
45
  paused: queue.paused,
46
46
  items: queue.itemIds.flatMap((itemId) => {
47
- const item = this.options.runtime.getQueueItem(itemId);
48
- if (item === undefined || item.clientMessageId.startsWith('goal:'))
47
+ const item = this.publicQueueItem(itemId);
48
+ if (item === undefined)
49
49
  return [];
50
50
  const session = this.options.runtime.getAgentSession(item.sessionId);
51
51
  return [
@@ -89,7 +89,16 @@ export class WorkspaceQueueWorkbenchService {
89
89
  throw new Error('QUEUE_INVALID');
90
90
  const session = this.requireSession(input);
91
91
  assertSessionControlOwner(this.options.runtime, session.id, input.__requestUserId);
92
- this.options.runtime.reorderSessionQueue(session.id, input.expectedVersion, input.queueItemIds);
92
+ const current = this.options.runtime.sessionQueue(session.id);
93
+ const publicItemIds = new Set(current.itemIds.filter((itemId) => this.publicQueueItem(itemId) !== undefined));
94
+ const reorderedIds = input.queueItemIds;
95
+ if (reorderedIds.length !== publicItemIds.size ||
96
+ new Set(reorderedIds).size !== reorderedIds.length ||
97
+ reorderedIds.some((itemId) => !publicItemIds.has(itemId)))
98
+ throw new Error('QUEUE_VERSION_CONFLICT');
99
+ let index = 0;
100
+ // Reorder only public slots, leaving internal continuations in place.
101
+ this.options.runtime.reorderSessionQueue(session.id, input.expectedVersion, current.itemIds.map((itemId) => (publicItemIds.has(itemId) ? reorderedIds[index++] : itemId)));
93
102
  this.options.emit(session.workspaceId, session.id);
94
103
  return {
95
104
  queue: this.present(session.workspaceId, session.id),
@@ -151,6 +160,10 @@ export class WorkspaceQueueWorkbenchService {
151
160
  throw new Error('SESSION_NOT_FOUND');
152
161
  return session;
153
162
  }
163
+ publicQueueItem(itemId) {
164
+ const item = this.options.runtime.getQueueItem(itemId);
165
+ return item?.clientMessageId.startsWith('goal:') ? undefined : item;
166
+ }
154
167
  requireItem(itemId, workspaceId) {
155
168
  const item = this.options.runtime.getQueueItem(itemId);
156
169
  if (item === undefined)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myagentroam/node",
3
- "version": "0.9.180",
3
+ "version": "0.10.2",
4
4
  "description": "MyAgentRoam Node runtime CLI.",
5
5
  "license": "Apache-2.0 AND GPL-2.0-or-later",
6
6
  "type": "module",
@@ -9,6 +9,7 @@
9
9
  "scripts/install-web-browser.mjs",
10
10
  "vendor/ripgrep/**/*",
11
11
  "vendor/ctags/**/*",
12
+ "dist/config.d.ts",
12
13
  "LICENSE",
13
14
  "NOTICE"
14
15
  ],
@@ -36,14 +37,22 @@
36
37
  "playwright": "1.62.1",
37
38
  "ws": "^8.21.3",
38
39
  "zod": "4.4.3",
39
- "@myagentroam/agent": "0.9.180",
40
- "@myagentroam/protocol": "0.9.180",
41
- "@myagentroam/marctl": "0.9.123",
42
- "@myagentroam/code-navigation": "0.9.129"
40
+ "@myagentroam/agent": "0.10.2",
41
+ "@myagentroam/code-navigation": "0.10.1",
42
+ "@myagentroam/marctl": "0.10.1",
43
+ "@myagentroam/protocol": "0.10.2"
43
44
  },
44
45
  "devDependencies": {
45
46
  "@types/ws": "^8.18.1"
46
47
  },
48
+ "exports": {
49
+ "./config": {
50
+ "types": "./dist/config.d.ts",
51
+ "import": "./dist/config.js"
52
+ },
53
+ "./cli": "./dist/main.js",
54
+ "./package.json": "./package.json"
55
+ },
47
56
  "scripts": {
48
57
  "postinstall": "node scripts/install-web-browser.mjs",
49
58
  "build": "node ../scripts/clean-build-output.mjs dist && tsc -p tsconfig.json",
@@ -51,7 +60,7 @@
51
60
  "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.tests.json --noEmit",
52
61
  "dev": "tsx watch src/main.ts",
53
62
  "start": "node dist/main.js",
54
- "test:unit": "vitest run --config vitest.config.mts",
63
+ "test:unit": "vitest run --config vitest.config.mts && node --test test/unit/*.test.mjs",
55
64
  "test:e2e:real": "vitest run --config vitest.e2e.config.mts"
56
65
  }
57
66
  }