@myagentroam/node 0.10.49 → 0.10.50

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/dist/connector.js CHANGED
@@ -856,37 +856,8 @@ export class NodeConnector {
856
856
  retainEnvironment: (environment) => this.gitExecution().retain(environment),
857
857
  goalCurrent: (input) => input.goal === undefined || this.goalGenerationCurrent(input.sessionId, input.goal),
858
858
  goalActive: (sessionId) => this.goalRuntime.get(sessionId)?.status === 'active',
859
- afterExecutionStarted: async (input) => {
860
- if (input.goal === undefined)
861
- return;
862
- if (!this.goalGenerationCurrent(input.sessionId, input.goal))
863
- return;
864
- const updated = this.goalRuntime.recordTurn(input.sessionId);
865
- const session = this.runtime.getAgentSession(input.sessionId);
866
- const run = this.runtime.getRun(input.runId);
867
- await this.enqueueGoalContinuation({
868
- sessionId: input.sessionId,
869
- goal: { id: input.goal.id, revision: input.goal.revision },
870
- ...(run?.initiatedByUserId === undefined
871
- ? {}
872
- : { initiatedByUserId: run.initiatedByUserId }),
873
- ...(input.usageGrant === undefined ? {} : { usageGrant: input.usageGrant }),
874
- secretEnvironment: input.secretEnvironment,
875
- ...(input.personalInstructions === undefined
876
- ? {}
877
- : { personalInstructions: input.personalInstructions }),
878
- ...(input.marAgentModel === undefined ? {} : { marAgentModel: input.marAgentModel }),
879
- ...(input.marAgentModels === undefined ? {} : { marAgentModels: input.marAgentModels }),
880
- ...(input.marAgentCompact === undefined
881
- ? {}
882
- : { marAgentCompact: input.marAgentCompact }),
883
- ...(input.marAgentRuntimeScopeId === undefined
884
- ? {}
885
- : { marAgentRuntimeScopeId: input.marAgentRuntimeScopeId })
886
- });
887
- if (updated !== undefined && session !== undefined)
888
- this.publishGoalState(session, updated);
889
- },
859
+ afterExecutionStarted: (input) => this.maintainGoalContinuation(input, true),
860
+ afterExecutionSteered: (input) => this.maintainGoalContinuation(input, false),
890
861
  afterExecutionStartFailed: (input, error) => {
891
862
  nodeLog('goal.execution-start.failed', {
892
863
  sessionId: input.sessionId,
@@ -1963,6 +1934,34 @@ export class NodeConnector {
1963
1934
  current.id === goal.id &&
1964
1935
  current.revision === goal.revision);
1965
1936
  }
1937
+ async maintainGoalContinuation(input, started) {
1938
+ if (this.stopped || input.goal === undefined)
1939
+ return;
1940
+ if (!this.goalGenerationCurrent(input.sessionId, input.goal))
1941
+ return;
1942
+ const updated = started ? this.goalRuntime.recordTurn(input.sessionId) : undefined;
1943
+ const session = this.runtime.getAgentSession(input.sessionId);
1944
+ const run = this.runtime.getRun(input.runId);
1945
+ await this.enqueueGoalContinuation({
1946
+ sessionId: input.sessionId,
1947
+ goal: { id: input.goal.id, revision: input.goal.revision },
1948
+ continuationEpoch: input.goal.epoch,
1949
+ ...(run?.initiatedByUserId === undefined ? {} : { initiatedByUserId: run.initiatedByUserId }),
1950
+ ...(input.usageGrant === undefined ? {} : { usageGrant: input.usageGrant }),
1951
+ secretEnvironment: input.secretEnvironment,
1952
+ ...(input.personalInstructions === undefined
1953
+ ? {}
1954
+ : { personalInstructions: input.personalInstructions }),
1955
+ ...(input.marAgentModel === undefined ? {} : { marAgentModel: input.marAgentModel }),
1956
+ ...(input.marAgentModels === undefined ? {} : { marAgentModels: input.marAgentModels }),
1957
+ ...(input.marAgentCompact === undefined ? {} : { marAgentCompact: input.marAgentCompact }),
1958
+ ...(input.marAgentRuntimeScopeId === undefined
1959
+ ? {}
1960
+ : { marAgentRuntimeScopeId: input.marAgentRuntimeScopeId })
1961
+ });
1962
+ if (updated !== undefined && session !== undefined)
1963
+ this.publishGoalState(session, updated);
1964
+ }
1966
1965
  handleNativeGoalUpdate(runId, nativeGoal) {
1967
1966
  const pending = this.continuousRunCoordinator.pending(runId);
1968
1967
  if (pending?.goal === undefined || !this.goalGenerationCurrent(pending.sessionId, pending.goal))
@@ -247,15 +247,31 @@ export class ContinuousRunCoordinator {
247
247
  return undefined;
248
248
  }
249
249
  const task = attempt
250
- .then((result) => {
250
+ .then(async (result) => {
251
251
  if (result.status === 'notAccepted')
252
252
  return false;
253
253
  onAccepted?.();
254
254
  this.options.runtime.consumeSteeredQueueItem(itemId, active.id);
255
- this.remove(itemId);
256
255
  this.immediateQueueItems.delete(itemId);
257
256
  this.options.runtime.resumeSessionQueue(item.sessionId);
258
257
  this.options.clearImages(itemId);
258
+ if (prepared.goal !== undefined && this.goalCurrent(prepared)) {
259
+ const current = this.preparedInputs.get(executionId);
260
+ if (current !== undefined)
261
+ this.preparedInputs.set(executionId, { ...current, goal: prepared.goal });
262
+ }
263
+ try {
264
+ await this.options.afterExecutionSteered?.({ ...prepared, runId: executionId });
265
+ }
266
+ catch (error) {
267
+ nodeLog('queue.native_steer.continuation_failed', {
268
+ level: 'warn',
269
+ sessionId: item.sessionId,
270
+ executionId,
271
+ code: safeErrorCode(error, 'NATIVE_STEER_CONTINUATION_FAILED')
272
+ });
273
+ }
274
+ this.remove(itemId);
259
275
  // Publication is best effort after ownership transfers; it cannot undo SDK acceptance.
260
276
  for (const notify of [
261
277
  () => {
@@ -591,6 +607,9 @@ export class ContinuousRunCoordinator {
591
607
  for (const [id, pending] of this.preparedInputs) {
592
608
  if (id === preservedSubmissionId)
593
609
  continue;
610
+ // Native admission owns receiving items until its receipt settles.
611
+ if (this.steerInFlight.has(id))
612
+ continue;
594
613
  if (pending.sessionId !== sessionId || pending.goal === undefined)
595
614
  continue;
596
615
  if (pending.goal.id === preservedGoal?.id && pending.goal.revision === preservedGoal.revision)
@@ -1,5 +1,5 @@
1
1
  import { createHash, randomUUID } from 'node:crypto';
2
- import { link, lstat, mkdir, open, readFile, rename, rm, stat } from 'node:fs/promises';
2
+ import { link, lstat, mkdir, open, readFile, rename, rm } from 'node:fs/promises';
3
3
  import { dirname, join, posix, resolve } from 'node:path';
4
4
  import { parseComposerAttachmentUpload, validComposerAttachmentName } from '../util/node-operation-parsers.js';
5
5
  import { preflightWorkspaceUpload, workspaceUploadTemporaryName } from '../workspace.js';
@@ -61,9 +61,7 @@ export class WorkspaceUploadService {
61
61
  throw new Error('UPLOAD_TARGET_BUSY');
62
62
  const id = randomUUID();
63
63
  const temporaryPath = resolve(dirname(target.absolutePath), workspaceUploadTemporaryName(id));
64
- const parentIdentity = await stat(dirname(target.absolutePath));
65
64
  const handle = await open(temporaryPath, 'wx+');
66
- const stagingIdentity = await handle.stat();
67
65
  const timer = setTimeout(() => {
68
66
  const upload = this.state.uploads.get(id);
69
67
  if (upload !== undefined)
@@ -73,8 +71,6 @@ export class WorkspaceUploadService {
73
71
  id,
74
72
  workspaceId: workspace.id,
75
73
  workspacePath: workspace.path,
76
- parentIdentity,
77
- stagingIdentity,
78
74
  path: target.path,
79
75
  targetPath: target.absolutePath,
80
76
  temporaryPath,
@@ -361,15 +357,10 @@ export class WorkspaceUploadService {
361
357
  throw new Error('UPLOAD_TARGET_EXISTS');
362
358
  }
363
359
  const parent = await lstat(dirname(upload.targetPath));
364
- if (!parent.isDirectory() ||
365
- parent.isSymbolicLink() ||
366
- !sameIdentity(parent, upload.parentIdentity))
360
+ if (!parent.isDirectory() || parent.isSymbolicLink())
367
361
  throw new Error('UPLOAD_TARGET_INVALID');
368
362
  const staging = await lstat(upload.temporaryPath);
369
- if (!staging.isFile() ||
370
- staging.isSymbolicLink() ||
371
- !sameIdentity(staging, upload.stagingIdentity) ||
372
- staging.size !== upload.size)
363
+ if (!staging.isFile() || staging.isSymbolicLink() || staging.size !== upload.size)
373
364
  throw new Error('UPLOAD_STAGING_INVALID');
374
365
  }
375
366
  async remove(upload) {
@@ -382,9 +373,9 @@ export class WorkspaceUploadService {
382
373
  return undefined;
383
374
  throw error;
384
375
  });
385
- if (!sameIdentity(parent, upload.parentIdentity) ||
376
+ if (!parent.isDirectory() ||
386
377
  parent.isSymbolicLink() ||
387
- (staging !== undefined && !sameIdentity(staging, upload.stagingIdentity)))
378
+ (staging !== undefined && (!staging.isFile() || staging.isSymbolicLink())))
388
379
  throw new Error('UPLOAD_CLEANUP_FAILED');
389
380
  if (staging !== undefined)
390
381
  await rm(upload.temporaryPath, { force: true });
@@ -427,9 +418,6 @@ export class WorkspaceUploadService {
427
418
  };
428
419
  }
429
420
  }
430
- function sameIdentity(actual, expected) {
431
- return actual.dev === expected.dev && actual.ino === expected.ino;
432
- }
433
421
  async function safeDirectory(path) {
434
422
  const value = await lstat(path);
435
423
  if (!value.isDirectory() || value.isSymbolicLink())
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myagentroam/node",
3
- "version": "0.10.49",
3
+ "version": "0.10.50",
4
4
  "description": "MyAgentRoam Node runtime CLI.",
5
5
  "license": "Apache-2.0 AND GPL-2.0-or-later",
6
6
  "type": "module",
@@ -37,10 +37,10 @@
37
37
  "playwright": "1.62.1",
38
38
  "ws": "^8.21.3",
39
39
  "zod": "4.4.3",
40
- "@myagentroam/agent": "0.10.49",
41
- "@myagentroam/code-navigation": "0.10.1",
40
+ "@myagentroam/agent": "0.10.50",
41
+ "@myagentroam/protocol": "0.10.50",
42
42
  "@myagentroam/marctl": "0.10.10",
43
- "@myagentroam/protocol": "0.10.49"
43
+ "@myagentroam/code-navigation": "0.10.1"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@types/ws": "^8.18.1"