@myagentroam/node 0.9.129 → 0.9.131
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
|
@@ -263,6 +263,7 @@ export class NodeConnector {
|
|
|
263
263
|
goalSubmissionAttempts = new Map();
|
|
264
264
|
goalContinuationEpochs = new Map();
|
|
265
265
|
goalExecutionProgress = new Set();
|
|
266
|
+
nativeGoalBindings = new Map();
|
|
266
267
|
sessionScheduleService;
|
|
267
268
|
goalMcpServer = new GoalMcpServer(this.goalRuntime, (sessionId) => {
|
|
268
269
|
const goal = this.goalRuntime.get(sessionId);
|
|
@@ -270,6 +271,7 @@ export class NodeConnector {
|
|
|
270
271
|
if (goal === undefined || session === undefined)
|
|
271
272
|
return;
|
|
272
273
|
if (goal.status !== 'active') {
|
|
274
|
+
this.nativeGoalBindings.delete(goal.id);
|
|
273
275
|
this.retireGoalContinuation(sessionId);
|
|
274
276
|
this.continuousRunCoordinator.removeGoalQueue(sessionId);
|
|
275
277
|
}
|
|
@@ -384,11 +386,9 @@ export class NodeConnector {
|
|
|
384
386
|
failed: status === 'FAILED',
|
|
385
387
|
progressed: status !== 'SUCCEEDED' || progressed
|
|
386
388
|
});
|
|
387
|
-
if (disposition === 'blocked' || disposition === '
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
else
|
|
391
|
-
this.invalidateGoalContinuation(pending.sessionId);
|
|
389
|
+
if (disposition === 'blocked' || disposition === 'completed') {
|
|
390
|
+
this.nativeGoalBindings.delete(pending.goal.id);
|
|
391
|
+
this.retireGoalContinuation(pending.sessionId);
|
|
392
392
|
this.continuousRunCoordinator.removeGoalQueue(pending.sessionId);
|
|
393
393
|
const terminalGoal = this.goalRuntime.get(pending.sessionId);
|
|
394
394
|
const session = this.runtime.getAgentSession(pending.sessionId);
|
|
@@ -528,6 +528,7 @@ export class NodeConnector {
|
|
|
528
528
|
promoteSession: (sessionId, nativeSessionId) => this.sessionIdentityService.promote(sessionId, nativeSessionId),
|
|
529
529
|
send: (type, payload) => this.send(type, payload),
|
|
530
530
|
emit: (runId, eventType, payload, status) => this.runEventBridge.emitRun(runId, eventType, payload, status),
|
|
531
|
+
nativeGoalUpdated: (runId, goal) => this.handleNativeGoalUpdate(runId, goal),
|
|
531
532
|
cancel: (runId, threadId, turnId, cwd, status) => this.runnerInteractionService.cancelCodexTurn(runId, threadId, turnId, cwd, status),
|
|
532
533
|
createApproval: (input) => this.runtime.createApproval(input),
|
|
533
534
|
publishApproval: (input) => this.publishApprovalForRun(input),
|
|
@@ -985,6 +986,9 @@ export class NodeConnector {
|
|
|
985
986
|
goalAlreadyActive: true
|
|
986
987
|
};
|
|
987
988
|
if (existing !== undefined) {
|
|
989
|
+
const previousGoal = this.goalRuntime.get(session.id);
|
|
990
|
+
if (previousGoal !== undefined)
|
|
991
|
+
this.nativeGoalBindings.delete(previousGoal.id);
|
|
988
992
|
this.goalRuntime.clear(session.id);
|
|
989
993
|
this.commandStates.clear(session.id, 'goal');
|
|
990
994
|
}
|
|
@@ -1720,10 +1724,46 @@ export class NodeConnector {
|
|
|
1720
1724
|
const current = this.goalRuntime.get(sessionId);
|
|
1721
1725
|
return ((this.goalContinuationEpochs.get(sessionId) ?? 0) === goal.epoch &&
|
|
1722
1726
|
current?.status === 'active' &&
|
|
1723
|
-
!current.continuationPaused &&
|
|
1724
1727
|
current.id === goal.id &&
|
|
1725
1728
|
current.revision === goal.revision);
|
|
1726
1729
|
}
|
|
1730
|
+
handleNativeGoalUpdate(runId, nativeGoal) {
|
|
1731
|
+
const pending = this.continuousRunCoordinator.pending(runId);
|
|
1732
|
+
if (pending?.goal === undefined || !this.goalGenerationCurrent(pending.sessionId, pending.goal))
|
|
1733
|
+
return;
|
|
1734
|
+
const goal = this.goalRuntime.get(pending.sessionId);
|
|
1735
|
+
if (nativeGoal.status === 'active') {
|
|
1736
|
+
if ((nativeGoal.createdAt + 1) * 1_000 < goal.revisionStartedAt)
|
|
1737
|
+
return;
|
|
1738
|
+
const previous = this.nativeGoalBindings.get(goal.id);
|
|
1739
|
+
if (previous !== undefined &&
|
|
1740
|
+
previous.revision !== goal.revision &&
|
|
1741
|
+
previous.threadId === nativeGoal.threadId &&
|
|
1742
|
+
previous.createdAt === nativeGoal.createdAt &&
|
|
1743
|
+
previous.objective === nativeGoal.objective)
|
|
1744
|
+
return;
|
|
1745
|
+
this.nativeGoalBindings.set(goal.id, {
|
|
1746
|
+
revision: goal.revision,
|
|
1747
|
+
threadId: nativeGoal.threadId,
|
|
1748
|
+
createdAt: nativeGoal.createdAt,
|
|
1749
|
+
objective: nativeGoal.objective
|
|
1750
|
+
});
|
|
1751
|
+
return;
|
|
1752
|
+
}
|
|
1753
|
+
const bound = this.nativeGoalBindings.get(goal.id);
|
|
1754
|
+
if (bound?.revision !== goal.revision ||
|
|
1755
|
+
bound.threadId !== nativeGoal.threadId ||
|
|
1756
|
+
bound.createdAt !== nativeGoal.createdAt ||
|
|
1757
|
+
bound.objective !== nativeGoal.objective)
|
|
1758
|
+
return;
|
|
1759
|
+
this.nativeGoalBindings.delete(goal.id);
|
|
1760
|
+
const completed = this.goalRuntime.update(pending.sessionId, goal.id, goal.revision, 'completed');
|
|
1761
|
+
this.retireGoalContinuation(pending.sessionId);
|
|
1762
|
+
this.continuousRunCoordinator.removeGoalQueue(pending.sessionId);
|
|
1763
|
+
const session = this.runtime.getAgentSession(pending.sessionId);
|
|
1764
|
+
if (session !== undefined)
|
|
1765
|
+
this.publishGoalState(session, completed);
|
|
1766
|
+
}
|
|
1727
1767
|
beginGoalSubmission(sessionId, continuationEpoch = this.goalContinuationEpochs.get(sessionId) ?? 0) {
|
|
1728
1768
|
const attempt = { sessionId, epoch: continuationEpoch };
|
|
1729
1769
|
const attempts = this.goalSubmissionAttempts.get(sessionId) ?? new Set();
|
|
@@ -1814,6 +1854,7 @@ export class NodeConnector {
|
|
|
1814
1854
|
this.clearGoalRetry(attempt.sessionId);
|
|
1815
1855
|
if (failedAttempts > 3) {
|
|
1816
1856
|
const blocked = this.goalRuntime.blockAfterRuntimeFailure(attempt.sessionId, input.goal.id, input.goal.revision);
|
|
1857
|
+
this.nativeGoalBindings.delete(input.goal.id);
|
|
1817
1858
|
this.continuousRunCoordinator.removeGoalQueue(attempt.sessionId);
|
|
1818
1859
|
this.goalContinuationEpochs.delete(attempt.sessionId);
|
|
1819
1860
|
this.finishIdleGoalRun(attempt.sessionId, 'FAILED');
|
|
@@ -1861,6 +1902,9 @@ export class NodeConnector {
|
|
|
1861
1902
|
}
|
|
1862
1903
|
clearGoalState(sessionId, status) {
|
|
1863
1904
|
const goalExit = this.goalRuntime.exitSummary(sessionId, status);
|
|
1905
|
+
const goal = this.goalRuntime.get(sessionId);
|
|
1906
|
+
if (goal !== undefined)
|
|
1907
|
+
this.nativeGoalBindings.delete(goal.id);
|
|
1864
1908
|
this.retireGoalContinuation(sessionId);
|
|
1865
1909
|
const removed = this.goalRuntime.clear(sessionId);
|
|
1866
1910
|
this.continuousRunCoordinator.removeGoalQueue(sessionId);
|
|
@@ -142,6 +142,27 @@ export class CodexManagedRunController {
|
|
|
142
142
|
this.host.emit(runId, 'run.running', { threadId, turnId }, 'RUNNING');
|
|
143
143
|
return;
|
|
144
144
|
}
|
|
145
|
+
if (notification.method === 'thread/goal/updated' &&
|
|
146
|
+
activeRun.goalMcp === true &&
|
|
147
|
+
turnId !== undefined &&
|
|
148
|
+
threadId !== undefined &&
|
|
149
|
+
isPlainRecord(params.goal) &&
|
|
150
|
+
params.goal.threadId === threadId &&
|
|
151
|
+
Number.isSafeInteger(params.goal.createdAt) &&
|
|
152
|
+
params.goal.createdAt > 0 &&
|
|
153
|
+
typeof params.goal.objective === 'string' &&
|
|
154
|
+
params.goal.objective.length <= 20_000 &&
|
|
155
|
+
(params.goal.status !== 'active' ||
|
|
156
|
+
(params.goal.tokensUsed === 0 && params.goal.timeUsedSeconds === 0)) &&
|
|
157
|
+
(params.goal.status === 'active' || params.goal.status === 'complete')) {
|
|
158
|
+
this.host.nativeGoalUpdated(runId, {
|
|
159
|
+
threadId,
|
|
160
|
+
createdAt: params.goal.createdAt,
|
|
161
|
+
objective: params.goal.objective,
|
|
162
|
+
status: params.goal.status === 'complete' ? 'completed' : 'active'
|
|
163
|
+
});
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
145
166
|
if (notification.requestId !== undefined &&
|
|
146
167
|
(notification.method === 'item/commandExecution/requestApproval' ||
|
|
147
168
|
notification.method === 'item/fileChange/requestApproval')) {
|
|
@@ -102,18 +102,19 @@ export class GoalRuntime {
|
|
|
102
102
|
throw new Error('GOAL_OBJECTIVE_INVALID');
|
|
103
103
|
const current = this.goals.get(sessionId);
|
|
104
104
|
const continuing = current?.status === 'active';
|
|
105
|
+
const now = this.now();
|
|
105
106
|
const goal = {
|
|
106
107
|
id: continuing ? current.id : randomUUID(),
|
|
107
108
|
sessionId,
|
|
108
109
|
objective: normalized,
|
|
109
|
-
startedAt: continuing ? current.startedAt :
|
|
110
|
+
startedAt: continuing ? current.startedAt : now,
|
|
111
|
+
revisionStartedAt: now,
|
|
110
112
|
revision: continuing ? current.revision + 1 : 1,
|
|
111
113
|
status: 'active',
|
|
112
114
|
turns: 0,
|
|
113
115
|
retryRequired: false,
|
|
114
116
|
retryStartedAtTurn: null,
|
|
115
|
-
consecutiveNoProgressTurns: 0
|
|
116
|
-
continuationPaused: false
|
|
117
|
+
consecutiveNoProgressTurns: 0
|
|
117
118
|
};
|
|
118
119
|
this.goals.set(sessionId, goal);
|
|
119
120
|
this.executionFailures.delete(sessionId);
|
|
@@ -144,34 +145,32 @@ export class GoalRuntime {
|
|
|
144
145
|
if (!input.failed && !input.progressed) {
|
|
145
146
|
this.executionFailures.delete(sessionId);
|
|
146
147
|
const consecutiveNoProgressTurns = current.consecutiveNoProgressTurns + 1;
|
|
147
|
-
const
|
|
148
|
+
const completed = consecutiveNoProgressTurns >= 3;
|
|
148
149
|
const goal = {
|
|
149
150
|
...current,
|
|
150
151
|
consecutiveNoProgressTurns,
|
|
151
|
-
|
|
152
|
+
...(completed ? { status: 'completed' } : {})
|
|
152
153
|
};
|
|
153
154
|
this.goals.set(sessionId, goal);
|
|
154
155
|
this.changed(goal);
|
|
155
|
-
return
|
|
156
|
+
return completed ? 'completed' : 'continue';
|
|
156
157
|
}
|
|
157
158
|
if (!input.failed) {
|
|
158
159
|
this.executionFailures.delete(sessionId);
|
|
159
|
-
if (current.consecutiveNoProgressTurns > 0
|
|
160
|
+
if (current.consecutiveNoProgressTurns > 0) {
|
|
160
161
|
const goal = {
|
|
161
162
|
...current,
|
|
162
|
-
consecutiveNoProgressTurns: 0
|
|
163
|
-
continuationPaused: false
|
|
163
|
+
consecutiveNoProgressTurns: 0
|
|
164
164
|
};
|
|
165
165
|
this.goals.set(sessionId, goal);
|
|
166
166
|
this.changed(goal);
|
|
167
167
|
}
|
|
168
168
|
return 'continue';
|
|
169
169
|
}
|
|
170
|
-
if (current.consecutiveNoProgressTurns > 0
|
|
170
|
+
if (current.consecutiveNoProgressTurns > 0) {
|
|
171
171
|
const goal = {
|
|
172
172
|
...current,
|
|
173
|
-
consecutiveNoProgressTurns: 0
|
|
174
|
-
continuationPaused: false
|
|
173
|
+
consecutiveNoProgressTurns: 0
|
|
175
174
|
};
|
|
176
175
|
this.goals.set(sessionId, goal);
|
|
177
176
|
}
|
|
@@ -191,12 +190,11 @@ export class GoalRuntime {
|
|
|
191
190
|
const current = this.goals.get(sessionId);
|
|
192
191
|
if (current?.status !== 'active')
|
|
193
192
|
return current;
|
|
194
|
-
if (
|
|
193
|
+
if (current.consecutiveNoProgressTurns === 0)
|
|
195
194
|
return current;
|
|
196
195
|
const goal = {
|
|
197
196
|
...current,
|
|
198
|
-
consecutiveNoProgressTurns: 0
|
|
199
|
-
continuationPaused: false
|
|
197
|
+
consecutiveNoProgressTurns: 0
|
|
200
198
|
};
|
|
201
199
|
this.goals.set(sessionId, goal);
|
|
202
200
|
this.changed(goal);
|
|
@@ -247,7 +245,7 @@ export class GoalRuntime {
|
|
|
247
245
|
const heading = kind === 'start' ? 'A Goal has started or changed.' : 'Continue the active Goal.';
|
|
248
246
|
const open = kind === 'start' ? START_OPEN : CONTINUE_OPEN;
|
|
249
247
|
const close = kind === 'start' ? START_CLOSE : CONTINUE_CLOSE;
|
|
250
|
-
return `${open}\n${heading}\n\nOriginal objective:\n${goal.objective}\n\nContinue executing this Goal across turns:\n- Work on the objective now. If it is incomplete, use tools to finish a coherent unit or obtain decisive evidence; do not stop at an acknowledgement, status, plan, or promise.\n- Preserve the original scope. Before completion, review the full objective and verify it with real evidence, then call mar_update_goal with status=completed.\n- Adapt and retry after individual failures. Request blocked only after the same blocker persists for three turns and the required additional retry.\n- Use mar_get_goal only when you need to reread the authoritative objective or status.\n- After mar_update_goal confirms completed or finally blocked, summarize the completed work, verification evidence, remaining issues, and the tool-reported elapsedWallMs converted from milliseconds into a concise readable duration in your final user-facing response. Name whether the Goal completed or is finally blocked.
|
|
248
|
+
return `${open}\n${heading}\n\nOriginal objective:\n${goal.objective}\n\nContinue executing this Goal across turns:\n- This Goal is owned by the Node's myagentroam_goal MCP server. Prefer myagentroam_goal.mar_update_goal to complete it. In Codex, a runner-native Goal created during this Goal may also complete it when Codex reports that native Goal complete; native Goal state from another task or turn does not count. Do not claim completion based only on a final message or an unrelated Goal.\n- Work on the objective now. If it is incomplete, use tools to finish a coherent unit or obtain decisive evidence; do not stop at an acknowledgement, status, plan, or promise.\n- Preserve the original scope. Before completion, review the full objective and verify it with real evidence, then call mar_update_goal with status=completed when available.\n- Adapt and retry after individual failures. Request blocked only after the same blocker persists for three turns and the required additional retry.\n- Use mar_get_goal only when you need to reread the authoritative objective or status.\n- After mar_update_goal confirms completed or finally blocked, summarize the completed work, verification evidence, remaining issues, and the tool-reported elapsedWallMs converted from milliseconds into a concise readable duration in your final user-facing response. If Codex instead confirms completion with its native Goal, summarize the work without claiming a MAR elapsedWallMs value. Name whether the Goal completed or is finally blocked. MAR elapsedWallMs includes waiting and retries through the status update, not tool execution time or the final response. If blocked returns active for the required retry, continue work instead of claiming a final summary.\n${close}`;
|
|
251
249
|
}
|
|
252
250
|
requireCurrent(sessionId, goalId, revision) {
|
|
253
251
|
const current = this.goals.get(sessionId);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myagentroam/node",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.131",
|
|
4
4
|
"description": "MyAgentRoam Node runtime CLI.",
|
|
5
5
|
"license": "Apache-2.0 AND GPL-2.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"npm": "11.12.1",
|
|
31
31
|
"ws": "^8.21.3",
|
|
32
32
|
"zod": "4.4.3",
|
|
33
|
-
"@myagentroam/agent": "0.9.
|
|
34
|
-
"@myagentroam/protocol": "0.9.
|
|
33
|
+
"@myagentroam/agent": "0.9.131",
|
|
34
|
+
"@myagentroam/protocol": "0.9.131",
|
|
35
35
|
"@myagentroam/code-navigation": "0.9.129"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|