@myagentroam/node 0.11.38 → 0.11.39

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.
@@ -286,12 +286,18 @@ export class MarAgentConversationNormalizer {
286
286
  !state.active ||
287
287
  state.toolName !== toolName ||
288
288
  state.executionId !== executionId ||
289
- (state.turnId !== undefined && turnId !== undefined && state.turnId !== turnId) ||
290
- state.commandOrigin === undefined)
289
+ (state.turnId !== undefined && turnId !== undefined && state.turnId !== turnId))
291
290
  return [];
292
291
  const input = record(state.input);
293
292
  if (typeof input?.processId === 'string' && input.processId !== output.processId)
294
293
  return [];
294
+ if (state.commandOrigin === undefined) {
295
+ if (toolName !== 'exec_wait')
296
+ return [];
297
+ return [
298
+ genericToolItem(state.itemId, toolName, 'IN_PROGRESS', state.input, snapshot.outputPreview, null, snapshot.truncated)
299
+ ];
300
+ }
295
301
  const command = this.#commands.get(state.commandOrigin);
296
302
  if (command === undefined || command.status !== 'IN_PROGRESS')
297
303
  return [];
@@ -864,7 +870,7 @@ function genericToolItem(id, toolName, status, input, outputSummary = null, erro
864
870
  truncated: truncated || source.length > 10_000 || output.length > 10_000
865
871
  }, status, 'Code execution');
866
872
  }
867
- if (toolName === 'code_exec_wait') {
873
+ if (toolName === 'code_exec_wait' || toolName === 'exec_wait') {
868
874
  const inputRecord = record(input);
869
875
  const action = typeof inputRecord?.action === 'string' ? inputRecord.action : 'poll';
870
876
  const inputSummary = compactRunnerValue(input, 10_000);
@@ -890,7 +896,7 @@ function genericToolItem(id, toolName, status, input, outputSummary = null, erro
890
896
  inputSummary.truncated ||
891
897
  result?.truncated === true ||
892
898
  resultSummary.length > 10_000
893
- }, status, 'Code execution wait');
899
+ }, status, toolName === 'code_exec_wait' ? 'Code execution wait' : 'Command wait');
894
900
  }
895
901
  const subagent = marAgentSubagentProjection(toolName, input, output, subagentTitle, knownSubagentDetails);
896
902
  const toolCategory = isImageGenerationTool(toolName) ? 'IMAGE_GENERATION' : undefined;
@@ -1,6 +1,6 @@
1
1
  import { marAgentEnvelopeInput, resolveMarAgentExecutionInput } from './execution-input.js';
2
2
  export { resolveRunModels } from './execution-input.js';
3
- import { NODE_MCP } from '../../mcp/naming.js';
3
+ import { NODE_MCP, NODE_COMPUTER_WAIT_TOOL_NAME } from '../../mcp/naming.js';
4
4
  import { computerUseHostSkill } from './computer-use-skill.js';
5
5
  import { marctlExecutionEnvironment, marctlHostSkill } from './marctl-skill.js';
6
6
  import { createHash, randomUUID } from 'node:crypto';
@@ -291,6 +291,7 @@ export class MarAgentManagedRunController {
291
291
  sessionId: runtime.session.id,
292
292
  mode: input.mode,
293
293
  enabled: input.computerUseEnabled === true,
294
+ signal: controller.signal,
294
295
  modelSupportsImages: input.model.inputCapabilities.includes('IMAGE')
295
296
  });
296
297
  use.assertUsable();
@@ -344,7 +345,9 @@ export class MarAgentManagedRunController {
344
345
  const computer = nodeTools.map((definition) => ({
345
346
  definition,
346
347
  serverId: NODE_MCP.computer.name,
347
- rawName: NODE_MCP.computer.tools.exec,
348
+ rawName: definition.name === NODE_COMPUTER_WAIT_TOOL_NAME
349
+ ? NODE_MCP.computer.tools.wait
350
+ : NODE_MCP.computer.tools.exec,
348
351
  sourceIdentity: `node:${input.runId}:computer`,
349
352
  definitionRevision: createHash('sha256')
350
353
  .update(JSON.stringify(definition))
@@ -540,6 +543,9 @@ export class MarAgentManagedRunController {
540
543
  finally {
541
544
  titleController.abort();
542
545
  const cleanup = [
546
+ async () => {
547
+ await computerUseBinding?.close();
548
+ },
543
549
  async () => {
544
550
  await titleTask;
545
551
  },
@@ -549,9 +555,6 @@ export class MarAgentManagedRunController {
549
555
  async () => {
550
556
  await closeImageCredentialProviders(executionModels);
551
557
  },
552
- async () => {
553
- await computerUseBinding?.close();
554
- },
555
558
  async () => {
556
559
  runtime?.host.unbindExecutionMcp(executionMcpBinding);
557
560
  },
@@ -1,5 +1,7 @@
1
1
  import { computerUseDisableInputSchema, computerUseEnableInputSchema, computerUseEnableResultSchema } from '@myagentroam/protocol';
2
2
  import { computerUseRuntimeExecutable, saveNodeConfig } from '../config.js';
3
+ import { ComputerUseRuntimeError } from '../computer-use-runtime.js';
4
+ import { ComputerUseError } from '../computer-use/contracts.js';
3
5
  import { nodeOperationData } from '../connection/node-operation-data.js';
4
6
  /** Persists Computer Use authorization and owns its asynchronous capability probe. */
5
7
  export class ComputerUseEnablementService {
@@ -17,8 +19,8 @@ export class ComputerUseEnablementService {
17
19
  }
18
20
  operations() {
19
21
  return {
20
- 'computer.use.enable': (data) => this.enable(data),
21
- 'computer.use.disable': (data) => this.disable(data)
22
+ 'computer.use.enable': (data) => this.options.mutations.run(() => this.enable(data)),
23
+ 'computer.use.disable': (data) => this.options.mutations.run(() => this.disable(data))
22
24
  };
23
25
  }
24
26
  initialize() {
@@ -107,9 +109,13 @@ export class ComputerUseEnablementService {
107
109
  });
108
110
  void this.options.provider
109
111
  .reset()
110
- .then(() => this.options.prepareRuntime())
111
- .then(() => this.options.provider.support())
112
- .then((support) => {
112
+ .then(async () => {
113
+ if (generation !== this.#probeGeneration)
114
+ return;
115
+ await this.options.prepareRuntime();
116
+ if (generation !== this.#probeGeneration)
117
+ return;
118
+ const support = await this.options.provider.support();
113
119
  if (generation !== this.#probeGeneration)
114
120
  return;
115
121
  this.#set(this.#fromSupport(support));
@@ -117,8 +123,8 @@ export class ComputerUseEnablementService {
117
123
  .catch((error) => {
118
124
  if (generation !== this.#probeGeneration)
119
125
  return;
120
- this.#set(this.#unavailable(error instanceof Error && /^[A-Z][A-Z0-9_]{0,79}$/u.test(error.message)
121
- ? error.message
126
+ this.#set(this.#unavailable(error instanceof ComputerUseError || error instanceof ComputerUseRuntimeError
127
+ ? error.code
122
128
  : 'COMPUTER_PROBE_FAILED'));
123
129
  });
124
130
  }
@@ -9,8 +9,8 @@ export class ConversationHostingEnablementService {
9
9
  }
10
10
  operations() {
11
11
  return {
12
- 'conversation.hosting.enable': (data) => this.enable(data),
13
- 'conversation.hosting.disable': (data) => this.disable(data)
12
+ 'conversation.hosting.enable': (data) => this.options.mutations.run(() => this.enable(data)),
13
+ 'conversation.hosting.disable': (data) => this.options.mutations.run(() => this.disable(data))
14
14
  };
15
15
  }
16
16
  async disable(data) {
@@ -0,0 +1,27 @@
1
+ /** Serializes runtime configuration writes, including transient state and rollback. */
2
+ export class NodeConfigMutations {
3
+ #pending;
4
+ run(operation) {
5
+ const previous = this.#pending;
6
+ let release;
7
+ const pending = new Promise((resolve) => {
8
+ release = resolve;
9
+ });
10
+ this.#pending = pending;
11
+ const finish = () => {
12
+ if (this.#pending === pending)
13
+ this.#pending = undefined;
14
+ release();
15
+ };
16
+ let result;
17
+ try {
18
+ // Start an uncontended mutation synchronously so disable closes admission before yielding.
19
+ result = previous === undefined ? operation() : previous.then(operation);
20
+ }
21
+ catch (error) {
22
+ result = Promise.reject(error);
23
+ }
24
+ void result.then(finish, finish);
25
+ return result;
26
+ }
27
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myagentroam/node",
3
- "version": "0.11.38",
3
+ "version": "0.11.39",
4
4
  "description": "MyAgentRoam Node runtime CLI.",
5
5
  "license": "Apache-2.0 AND GPL-2.0-or-later",
6
6
  "type": "module",
@@ -38,10 +38,10 @@
38
38
  "sharp": "0.35.5",
39
39
  "ws": "^8.21.3",
40
40
  "zod": "4.4.3",
41
- "@myagentroam/agent": "0.11.38",
41
+ "@myagentroam/agent": "0.11.39",
42
42
  "@myagentroam/code-navigation": "0.11.1",
43
- "@myagentroam/marctl": "0.11.3",
44
- "@myagentroam/protocol": "0.11.38"
43
+ "@myagentroam/marctl": "0.11.4",
44
+ "@myagentroam/protocol": "0.11.39"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@types/ws": "^8.18.1"
@@ -62,6 +62,7 @@
62
62
  "dev": "tsx watch src/main.ts",
63
63
  "start": "node dist/main.js",
64
64
  "test:unit": "vitest run --config vitest.config.mts && node --test test/unit/*.test.mjs",
65
- "test:e2e:real": "vitest run --config vitest.e2e.config.mts"
65
+ "test:e2e:real": "vitest run --config vitest.e2e.config.mts",
66
+ "test:e2e:computer-use:windows": "node --test test/e2e/computer-use-windows.test.mjs"
66
67
  }
67
68
  }