@myagentroam/node 0.11.42 → 0.11.43
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 +9 -2
- package/dist/hosting/hosted-conversation-node-service.js +1 -2
- package/dist/marctl-guidance.js +3 -1
- package/dist/runner/abstract-runner.js +2 -2
- package/dist/runner/claude/managed-run-controller.js +1 -1
- package/dist/runner/claude/native-transcript.js +1 -1
- package/dist/runner/claude/tool-normalizer.js +21 -12
- package/dist/runner/codex/conversation-parser.js +17 -9
- package/dist/runner/codex/managed-run-controller.js +1 -1
- package/dist/runner/codex/tool-normalizer.js +17 -9
- package/dist/runner/execution-presentation.js +0 -3
- package/dist/runner/mar-agent/agent-network-extension.js +2 -2
- package/dist/runner/mar-agent/conversation-normalizer.js +259 -43
- package/dist/runner/mar-agent/managed-run-controller.js +2 -1
- package/dist/runner/mar-agent/runtime-model-factory.js +2 -4
- package/dist/runner/mar-agent-runner.js +32 -8
- package/dist/runner/normalization.js +8 -0
- package/dist/runner/opencode/tool-normalizer.js +8 -4
- package/dist/runtime-state.js +0 -1
- package/dist/service/agent-network-bindings.js +4 -2
- package/dist/service/agent-network-invoke.js +5 -2
- package/dist/service/agent-network-observations.js +15 -13
- package/dist/service/agent-network-service.js +39 -15
- package/dist/service/goal-continuation-coordinator.js +5 -0
- package/dist/service/runner-service.js +7 -3
- package/dist/session/runtime/conversation-projection.js +3 -1
- package/dist/session/session-lifecycle-service.js +7 -4
- package/dist/session/session-message-service.js +4 -2
- package/package.json +4 -4
|
@@ -141,7 +141,9 @@ export function createNodeAgentNetwork(options) {
|
|
|
141
141
|
options.projection.resolve(record.id, true)));
|
|
142
142
|
return resolved.filter((session) => session !== undefined);
|
|
143
143
|
},
|
|
144
|
-
observe: (actor
|
|
144
|
+
observe: (actor) => {
|
|
145
|
+
options.ensureObservations(actor);
|
|
146
|
+
},
|
|
145
147
|
isUpward: async (actor, session) => !terminalCalls.has(actor) && (await actorSession(actor)).parentSessionId === session.id,
|
|
146
148
|
reportUpward: async (actor, session, input, signal) => {
|
|
147
149
|
const child = await actorSession(actor);
|
|
@@ -210,7 +212,7 @@ export function createNodeAgentNetwork(options) {
|
|
|
210
212
|
throw new Error('SESSION_INVALID');
|
|
211
213
|
const model = input.model ??
|
|
212
214
|
database.getRunnerDefaults().find((entry) => entry.runner === runner)?.model ??
|
|
213
|
-
runnerAdapter.defaultConfiguration(workspace, actor.secretEnvironment ?? {}).model;
|
|
215
|
+
runnerAdapter.defaultConfiguration(workspace, actor.secretEnvironment ?? {}, runnerAdapter.prepareExecutionContext(actor.runnerConfiguration ?? {})).model;
|
|
214
216
|
const request = {
|
|
215
217
|
...executionInput(actor, runner, model, parent !== undefined),
|
|
216
218
|
workspaceId: workspace.id,
|
|
@@ -11,11 +11,14 @@ export function agentNetworkInvoke(input) {
|
|
|
11
11
|
}
|
|
12
12
|
/** Read actor resources from the current Node-owned Execution, not caller arguments. */
|
|
13
13
|
export function executionAgentActor(input) {
|
|
14
|
-
const {
|
|
14
|
+
const { executionId } = input;
|
|
15
|
+
// Warm runtimes and execution credentials may retain the bootstrap Session ID.
|
|
16
|
+
const sessionId = input.runtime.getAgentSessionById(input.sessionId)?.id;
|
|
15
17
|
const execution = input.runtime.executionSnapshot(executionId);
|
|
16
18
|
const prepared = input.coordinator.pending(executionId);
|
|
17
19
|
const run = execution && input.runtime.getRun(execution.runId);
|
|
18
|
-
if (!
|
|
20
|
+
if (!sessionId ||
|
|
21
|
+
!execution ||
|
|
19
22
|
!prepared ||
|
|
20
23
|
!run ||
|
|
21
24
|
execution.sessionId !== sessionId ||
|
|
@@ -32,6 +32,7 @@ export function agentObservationFromRunEvent(input) {
|
|
|
32
32
|
/** Volatile, session-owned delivery of live direct-child observations. */
|
|
33
33
|
export class AgentNetworkObservations {
|
|
34
34
|
#parents = new Map();
|
|
35
|
+
#waiters = new Map();
|
|
35
36
|
attach(parentId) {
|
|
36
37
|
if (this.#parents.has(parentId))
|
|
37
38
|
throw new Error('AGENT_NETWORK_PARENT_ALREADY_ATTACHED');
|
|
@@ -49,11 +50,21 @@ export class AgentNetworkObservations {
|
|
|
49
50
|
publish(input) {
|
|
50
51
|
this.#parents.get(input.parentId)?.publish(input);
|
|
51
52
|
}
|
|
52
|
-
/**
|
|
53
|
+
/** Call-local observations never enter a Session's automatic context or wake channel. */
|
|
54
|
+
watchExecutions(targets) {
|
|
55
|
+
const observations = new ParentObservations(() => this.#waiters.delete(observations));
|
|
56
|
+
this.#waiters.set(observations, targets);
|
|
57
|
+
return observations;
|
|
58
|
+
}
|
|
59
|
+
/** Only direct children are automatic; other targets reach active, execution-scoped waits. */
|
|
53
60
|
publishChild(input) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
if (input.parentId != null)
|
|
62
|
+
this.#parents.get(input.parentId)?.publish(input);
|
|
63
|
+
for (const [waiter, targets] of this.#waiters) {
|
|
64
|
+
if (targets.some((target) => target.agentId === input.childId &&
|
|
65
|
+
target.runId === input.runId &&
|
|
66
|
+
target.executionId === input.executionId))
|
|
67
|
+
waiter.publish(input);
|
|
57
68
|
}
|
|
58
69
|
}
|
|
59
70
|
promote(previousId, nextId) {
|
|
@@ -74,19 +85,11 @@ export class ParentObservations {
|
|
|
74
85
|
#results = new Map();
|
|
75
86
|
#listeners = new Set();
|
|
76
87
|
#wakeListeners = new Set();
|
|
77
|
-
#targets = new Set();
|
|
78
88
|
#revision = 0;
|
|
79
89
|
#closed = false;
|
|
80
90
|
constructor(detach) {
|
|
81
91
|
this.detach = detach;
|
|
82
92
|
}
|
|
83
|
-
observe(childId) {
|
|
84
|
-
if (!this.#closed)
|
|
85
|
-
this.#targets.add(childId);
|
|
86
|
-
}
|
|
87
|
-
observes(childId) {
|
|
88
|
-
return this.#targets.has(childId);
|
|
89
|
-
}
|
|
90
93
|
wake = {
|
|
91
94
|
pending: () => [...this.#items.values()].some((item) => item.kind === 'message' && item.wakes !== false),
|
|
92
95
|
subscribe: (listener) => {
|
|
@@ -302,7 +305,6 @@ export class ParentObservations {
|
|
|
302
305
|
this.#results.clear();
|
|
303
306
|
this.#listeners.clear();
|
|
304
307
|
this.#wakeListeners.clear();
|
|
305
|
-
this.#targets.clear();
|
|
306
308
|
this.detach();
|
|
307
309
|
}
|
|
308
310
|
}
|
|
@@ -41,7 +41,8 @@ export class AgentNetworkService {
|
|
|
41
41
|
goal
|
|
42
42
|
}, signal);
|
|
43
43
|
try {
|
|
44
|
-
|
|
44
|
+
if (created.session.parentSessionId === actor.sessionId)
|
|
45
|
+
this.options.observe(actor, created.session);
|
|
45
46
|
return { agentId: created.session.id, start: created.result };
|
|
46
47
|
}
|
|
47
48
|
catch (error) {
|
|
@@ -106,7 +107,8 @@ export class AgentNetworkService {
|
|
|
106
107
|
return { agentId: session.id, message: { status: 'accepted', result } };
|
|
107
108
|
}
|
|
108
109
|
signal?.throwIfAborted();
|
|
109
|
-
|
|
110
|
+
if (session.parentSessionId === actor.sessionId)
|
|
111
|
+
this.options.observe(actor, session);
|
|
110
112
|
const approvalResult = input.approval === undefined
|
|
111
113
|
? undefined
|
|
112
114
|
: await this.options.approval(actor, session, input.approval, signal);
|
|
@@ -281,22 +283,44 @@ export class AgentNetworkService {
|
|
|
281
283
|
if (!targets.length)
|
|
282
284
|
throw new Error('AGENT_EXECUTION_NOT_FOUND');
|
|
283
285
|
const selected = new Set(targets.map((target) => target.agentId));
|
|
286
|
+
const directChildren = new Set();
|
|
284
287
|
for (const session of sessions)
|
|
285
|
-
if (selected.has(session.id))
|
|
288
|
+
if (selected.has(session.id) && session.parentSessionId === actor.sessionId) {
|
|
286
289
|
this.options.observe(actor, session);
|
|
287
|
-
|
|
288
|
-
|
|
290
|
+
directChildren.add(session.id);
|
|
291
|
+
}
|
|
292
|
+
const parent = this.options.observations.get(actor.observationId ?? actor.sessionId);
|
|
293
|
+
if (directChildren.size && !parent)
|
|
289
294
|
throw new Error('AGENT_OBSERVATION_UNAVAILABLE');
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
observations
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
295
|
+
const otherTargets = targets.filter((target) => !directChildren.has(target.agentId));
|
|
296
|
+
const temporary = otherTargets.length && input.waitMs !== 0
|
|
297
|
+
? this.options.observations.watchExecutions(otherTargets)
|
|
298
|
+
: undefined;
|
|
299
|
+
try {
|
|
300
|
+
return await waitForAgentTargets({
|
|
301
|
+
targets,
|
|
302
|
+
observations: {
|
|
303
|
+
capture: (id, executionId) => (directChildren.has(id) ? parent : temporary)?.capture(id, executionId),
|
|
304
|
+
subscribe: (listener) => {
|
|
305
|
+
const unsubscribeParent = directChildren.size ? parent?.subscribe(listener) : undefined;
|
|
306
|
+
const unsubscribeTemporary = temporary?.subscribe(listener);
|
|
307
|
+
return () => {
|
|
308
|
+
unsubscribeParent?.();
|
|
309
|
+
unsubscribeTemporary?.();
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
single: input.agentIds === undefined,
|
|
314
|
+
waitMs: input.waitMs ?? 30_000,
|
|
315
|
+
...(input.mode === undefined ? {} : { mode: input.mode }),
|
|
316
|
+
...(input.waitFor === undefined ? {} : { waitFor: input.waitFor }),
|
|
317
|
+
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
318
|
+
...(input.interrupt === undefined ? {} : { interrupt: input.interrupt })
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
finally {
|
|
322
|
+
temporary?.close();
|
|
323
|
+
}
|
|
300
324
|
}
|
|
301
325
|
}
|
|
302
326
|
function sameGoal(left, right) {
|
|
@@ -180,6 +180,11 @@ export class GoalContinuationCoordinator {
|
|
|
180
180
|
};
|
|
181
181
|
}
|
|
182
182
|
async start({ session, objective, initiatedByUserId, suppressNotifications, secretEnvironment, personalInstructions, executionContext, usageGrant, preserveActiveRun, messageIntent, messageContent, clientMessageId, messageOrigin, attachments, attachmentIds }) {
|
|
183
|
+
if (session.parentSessionId != null)
|
|
184
|
+
this.options
|
|
185
|
+
.runners()
|
|
186
|
+
.require(session.runner)
|
|
187
|
+
.assertChildModel(session.model, executionContext);
|
|
183
188
|
this.invalidateGoalContinuation(session.id);
|
|
184
189
|
const prepared = this.prepareGoalSession(session);
|
|
185
190
|
const goalSession = prepared.session;
|
|
@@ -44,10 +44,14 @@ export class RunnerService {
|
|
|
44
44
|
async listProfiles(data) {
|
|
45
45
|
const input = data;
|
|
46
46
|
const marAgent = this.runners.optional('mar-agent');
|
|
47
|
+
let marAgentProfile;
|
|
47
48
|
if (marAgent !== undefined &&
|
|
48
49
|
'configureModels' in marAgent &&
|
|
49
50
|
typeof marAgent.configureModels === 'function')
|
|
50
|
-
marAgent.configureModels(input.marAgentModels);
|
|
51
|
+
marAgentProfile = marAgent.configureModels(input.marAgentModels);
|
|
52
|
+
// Capture the request's display catalog before any asynchronous Runner refresh.
|
|
53
|
+
// This cache is not used for model admission.
|
|
54
|
+
const requestProfiles = (profiles) => profiles.map((profile) => profile.runner === 'mar-agent' && marAgentProfile !== undefined ? marAgentProfile : profile);
|
|
51
55
|
const environment = parseSecretEnvironment(input.secretEnvironment);
|
|
52
56
|
const defaults = this.database()
|
|
53
57
|
.getRunnerDefaults()
|
|
@@ -71,12 +75,12 @@ export class RunnerService {
|
|
|
71
75
|
if (cacheOnly) {
|
|
72
76
|
void refresh.catch(() => undefined);
|
|
73
77
|
return {
|
|
74
|
-
profiles: this.profiles(environment),
|
|
78
|
+
profiles: requestProfiles(this.profiles(environment)),
|
|
75
79
|
defaults
|
|
76
80
|
};
|
|
77
81
|
}
|
|
78
82
|
return {
|
|
79
|
-
profiles: await refresh,
|
|
83
|
+
profiles: requestProfiles(await refresh),
|
|
80
84
|
defaults
|
|
81
85
|
};
|
|
82
86
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { permissionStopSchema } from '@myagentroam/protocol';
|
|
1
|
+
import { appendExecutionPresentation, permissionStopSchema } from '@myagentroam/protocol';
|
|
2
2
|
import { projectConversationWorkProcesses } from './work-process.js';
|
|
3
3
|
function isRecord(value) {
|
|
4
4
|
return typeof value === 'object' && value !== null;
|
|
@@ -293,6 +293,8 @@ export function mergeConversationItemPayload(existing, next) {
|
|
|
293
293
|
if (next.append === 'output' &&
|
|
294
294
|
isRecord(next.payload.output) &&
|
|
295
295
|
typeof next.payload.output.text === 'string') {
|
|
296
|
+
if (next.payload.toolPresentation !== undefined)
|
|
297
|
+
value.toolPresentation = appendExecutionPresentation(base.toolPresentation, next.payload.toolPresentation);
|
|
296
298
|
const prior = isRecord(base.output) && typeof base.output.text === 'string' ? base.output : undefined;
|
|
297
299
|
const text = `${prior?.text ?? ''}${next.payload.output.text}`;
|
|
298
300
|
value.output = {
|
|
@@ -168,7 +168,8 @@ export class SessionLifecycleService {
|
|
|
168
168
|
}
|
|
169
169
|
const environment = parseSecretEnvironment(input.secretEnvironment);
|
|
170
170
|
const saved = database.getRunnerDefaults().find((value) => value.runner === runner.name);
|
|
171
|
-
const
|
|
171
|
+
const executionContext = runner.prepareExecutionContext(input);
|
|
172
|
+
const fallback = runner.defaultConfiguration(workspace, environment, executionContext);
|
|
172
173
|
const configuration = {
|
|
173
174
|
runner: runner.name,
|
|
174
175
|
model: typeof input.model === 'string' ? input.model : (saved?.model ?? fallback.model),
|
|
@@ -182,7 +183,7 @@ export class SessionLifecycleService {
|
|
|
182
183
|
if (runner.name === 'mar-agent' && !['auto', 'full-access'].includes(configuration.access))
|
|
183
184
|
throw new Error('SESSION_INVALID');
|
|
184
185
|
if (parentSessionId !== undefined)
|
|
185
|
-
runner.assertChildModel(configuration.model);
|
|
186
|
+
runner.assertChildModel(configuration.model, executionContext);
|
|
186
187
|
const session = this.options.runtime.createAgentSession({
|
|
187
188
|
...(parentSessionId === undefined ? {} : { parentSessionId }),
|
|
188
189
|
workspaceId: input.workspaceId,
|
|
@@ -221,8 +222,10 @@ export class SessionLifecycleService {
|
|
|
221
222
|
input.access !== undefined &&
|
|
222
223
|
!['auto', 'full-access'].includes(input.access))
|
|
223
224
|
throw new Error('SESSION_INVALID');
|
|
224
|
-
if (current.parentSessionId != null && typeof input.model === 'string')
|
|
225
|
-
this.options.runners.require(current.runner)
|
|
225
|
+
if (current.parentSessionId != null && typeof input.model === 'string') {
|
|
226
|
+
const runner = this.options.runners.require(current.runner);
|
|
227
|
+
runner.assertChildModel(input.model, runner.prepareExecutionContext(input));
|
|
228
|
+
}
|
|
226
229
|
const session = this.options.runtime.updateAgentSessionConfiguration({
|
|
227
230
|
sessionId: current.id,
|
|
228
231
|
...(typeof input.model === 'string' ? { model: input.model } : {}),
|
|
@@ -143,10 +143,12 @@ export class SessionMessageService {
|
|
|
143
143
|
idempotent: true,
|
|
144
144
|
auditReceipt: auditReceipt(session, existing.kind === 'queue' ? 'QUEUE' : 'SEND', existing.kind === 'queue' ? existing.item.id : existing.run.id, existing.kind === 'queue' ? existing.item.id : undefined)
|
|
145
145
|
};
|
|
146
|
-
if (session.parentSessionId != null)
|
|
147
|
-
this.options.runners.require(session.runner).assertChildModel(session.model);
|
|
148
146
|
const executionContext = input[RUNNER_EXECUTION_CONTEXT] ??
|
|
149
147
|
this.options.runners.require(session.runner).prepareExecutionContext(input);
|
|
148
|
+
if (session.parentSessionId != null)
|
|
149
|
+
this.options.runners
|
|
150
|
+
.require(session.runner)
|
|
151
|
+
.assertChildModel(session.model, executionContext);
|
|
150
152
|
const sourceContent = withSessionMessageOrigin(content, input.__marctlOrigin, session.parentSessionId);
|
|
151
153
|
const goalMessage = internalGoal || internalSchedule || internalRestore
|
|
152
154
|
? undefined
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myagentroam/node",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.43",
|
|
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.
|
|
41
|
+
"@myagentroam/agent": "0.11.43",
|
|
42
|
+
"@myagentroam/marctl": "0.11.6",
|
|
42
43
|
"@myagentroam/code-navigation": "0.11.1",
|
|
43
|
-
"@myagentroam/
|
|
44
|
-
"@myagentroam/protocol": "0.11.42"
|
|
44
|
+
"@myagentroam/protocol": "0.11.43"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/ws": "^8.18.1"
|