@myagentroam/node 0.9.116 → 0.9.118
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 +223 -224
- package/dist/native-session-history.js +2 -2
- package/dist/runner/abstract-runner.js +3 -3
- package/dist/runner/codex/conversation-parser.js +2 -2
- package/dist/runner/codex/managed-run-controller.js +6 -6
- package/dist/runner/mar-agent/history-projection.js +2 -2
- package/dist/runner/mar-agent-runner.js +5 -5
- package/dist/runner/opencode/conversation-parser.js +3 -3
- package/dist/runner-command-engine.js +1 -1
- package/dist/runner-profiles.js +8 -8
- package/dist/runtime-state.js +1 -1
- package/dist/service/continuous-run-coordinator.js +20 -21
- package/dist/service/{mission-mcp-server.js → goal-mcp-server.js} +28 -28
- package/dist/service/{mission-mcp-stdio.js → goal-mcp-stdio.js} +8 -8
- package/dist/service/goal-runtime.js +250 -0
- package/dist/service/mar-agent-model-transport-test-service.js +2 -19
- package/dist/service/session-command-service.js +4 -4
- package/dist/service/session-identity-service.js +1 -1
- package/dist/service/session-message-service.js +25 -29
- package/dist/service/workspace-queue-workbench-service.js +1 -1
- package/dist/util/runner-native-session-parsers.js +3 -3
- package/package.json +4 -4
- package/dist/service/mission-runtime.js +0 -225
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
export function goalUnrestrictedAccess(runner) {
|
|
3
|
+
if (runner === 'codex' || runner === 'mar-agent')
|
|
4
|
+
return 'full-access';
|
|
5
|
+
if (runner === 'claude-code')
|
|
6
|
+
return 'bypass';
|
|
7
|
+
return 'auto';
|
|
8
|
+
}
|
|
9
|
+
const START_OPEN = '<mar_goal_start>';
|
|
10
|
+
const START_CLOSE = '</mar_goal_start>';
|
|
11
|
+
const CONTINUE_OPEN = '<mar_goal_continue>';
|
|
12
|
+
const CONTINUE_CLOSE = '</mar_goal_continue>';
|
|
13
|
+
const LEGACY_START_OPEN = '<mar_mission_start>';
|
|
14
|
+
const LEGACY_START_CLOSE = '</mar_mission_start>';
|
|
15
|
+
const LEGACY_CONTINUE_OPEN = '<mar_mission_continue>';
|
|
16
|
+
const LEGACY_CONTINUE_CLOSE = '</mar_mission_continue>';
|
|
17
|
+
function goalPromptTags(text) {
|
|
18
|
+
if (text.startsWith(START_OPEN))
|
|
19
|
+
return { open: START_OPEN, close: START_CLOSE, legacy: false, continuation: false };
|
|
20
|
+
if (text.startsWith(CONTINUE_OPEN))
|
|
21
|
+
return { open: CONTINUE_OPEN, close: CONTINUE_CLOSE, legacy: false, continuation: true };
|
|
22
|
+
if (text.startsWith(LEGACY_START_OPEN))
|
|
23
|
+
return {
|
|
24
|
+
open: LEGACY_START_OPEN,
|
|
25
|
+
close: LEGACY_START_CLOSE,
|
|
26
|
+
legacy: true,
|
|
27
|
+
continuation: false
|
|
28
|
+
};
|
|
29
|
+
if (text.startsWith(LEGACY_CONTINUE_OPEN))
|
|
30
|
+
return {
|
|
31
|
+
open: LEGACY_CONTINUE_OPEN,
|
|
32
|
+
close: LEGACY_CONTINUE_CLOSE,
|
|
33
|
+
legacy: true,
|
|
34
|
+
continuation: true
|
|
35
|
+
};
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
export function publicGoalStartText(objective) {
|
|
39
|
+
const normalized = objective.trim();
|
|
40
|
+
return normalized.length === 0 ? 'Goal Start' : `Goal Start\n${normalized}`;
|
|
41
|
+
}
|
|
42
|
+
export function stripGoalStartPrompt(text) {
|
|
43
|
+
const tags = goalPromptTags(text);
|
|
44
|
+
if (tags === undefined)
|
|
45
|
+
return text;
|
|
46
|
+
const close = text.lastIndexOf(tags.close);
|
|
47
|
+
return close === -1 ? '' : text.slice(close + tags.close.length).trimStart();
|
|
48
|
+
}
|
|
49
|
+
export function publicGoalHistoryText(text) {
|
|
50
|
+
const tags = goalPromptTags(text);
|
|
51
|
+
if (tags === undefined)
|
|
52
|
+
return text;
|
|
53
|
+
const stripped = stripGoalStartPrompt(text);
|
|
54
|
+
if (stripped.length > 0)
|
|
55
|
+
return stripped;
|
|
56
|
+
if (tags.continuation)
|
|
57
|
+
return tags.legacy ? 'Mission Continue' : 'Goal Continue';
|
|
58
|
+
const close = text.lastIndexOf(tags.close);
|
|
59
|
+
const prompt = close === -1 ? text : text.slice(0, close);
|
|
60
|
+
const objectiveStart = prompt.indexOf('\nOriginal objective:\n');
|
|
61
|
+
const objectiveEnd = prompt.lastIndexOf(tags.legacy
|
|
62
|
+
? '\n\nContinue executing this Mission across turns:'
|
|
63
|
+
: '\n\nContinue executing this Goal across turns:');
|
|
64
|
+
const objective = objectiveStart === -1 || objectiveEnd === -1
|
|
65
|
+
? ''
|
|
66
|
+
: prompt.slice(objectiveStart + '\nOriginal objective:\n'.length, objectiveEnd);
|
|
67
|
+
return tags.legacy
|
|
68
|
+
? objective.trim().length === 0
|
|
69
|
+
? 'Mission Start'
|
|
70
|
+
: `Mission Start\n${objective.trim()}`
|
|
71
|
+
: publicGoalStartText(objective);
|
|
72
|
+
}
|
|
73
|
+
export class GoalRuntime {
|
|
74
|
+
changed;
|
|
75
|
+
goals = new Map();
|
|
76
|
+
executionFailures = new Map();
|
|
77
|
+
constructor(changed) {
|
|
78
|
+
this.changed = changed;
|
|
79
|
+
}
|
|
80
|
+
get(sessionId) {
|
|
81
|
+
return this.goals.get(sessionId);
|
|
82
|
+
}
|
|
83
|
+
migrateSession(previousId, nextId) {
|
|
84
|
+
if (previousId === nextId)
|
|
85
|
+
return;
|
|
86
|
+
const goal = this.goals.get(previousId);
|
|
87
|
+
if (goal !== undefined) {
|
|
88
|
+
this.goals.delete(previousId);
|
|
89
|
+
this.goals.set(nextId, { ...goal, sessionId: nextId });
|
|
90
|
+
}
|
|
91
|
+
const failures = this.executionFailures.get(previousId);
|
|
92
|
+
if (failures !== undefined) {
|
|
93
|
+
this.executionFailures.delete(previousId);
|
|
94
|
+
this.executionFailures.set(nextId, failures);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
start(sessionId, objective) {
|
|
98
|
+
const normalized = objective.trim();
|
|
99
|
+
if (normalized.length === 0 || normalized.length > 20_000)
|
|
100
|
+
throw new Error('GOAL_OBJECTIVE_INVALID');
|
|
101
|
+
const current = this.goals.get(sessionId);
|
|
102
|
+
const continuing = current?.status === 'active';
|
|
103
|
+
const goal = {
|
|
104
|
+
id: continuing ? current.id : randomUUID(),
|
|
105
|
+
sessionId,
|
|
106
|
+
objective: normalized,
|
|
107
|
+
revision: continuing ? current.revision + 1 : 1,
|
|
108
|
+
status: 'active',
|
|
109
|
+
turns: 0,
|
|
110
|
+
retryRequired: false,
|
|
111
|
+
retryStartedAtTurn: null,
|
|
112
|
+
consecutiveNoProgressTurns: 0,
|
|
113
|
+
continuationPaused: false
|
|
114
|
+
};
|
|
115
|
+
this.goals.set(sessionId, goal);
|
|
116
|
+
this.executionFailures.delete(sessionId);
|
|
117
|
+
this.changed(goal);
|
|
118
|
+
return goal;
|
|
119
|
+
}
|
|
120
|
+
recordTurn(sessionId) {
|
|
121
|
+
const current = this.goals.get(sessionId);
|
|
122
|
+
if (current?.status !== 'active')
|
|
123
|
+
return current;
|
|
124
|
+
const goal = { ...current, turns: current.turns + 1 };
|
|
125
|
+
this.goals.set(sessionId, goal);
|
|
126
|
+
return goal;
|
|
127
|
+
}
|
|
128
|
+
recordExecutionResult(sessionId, input) {
|
|
129
|
+
const current = this.goals.get(sessionId);
|
|
130
|
+
if (current?.status !== 'active')
|
|
131
|
+
return 'continue';
|
|
132
|
+
if (!input.failed && !input.progressed) {
|
|
133
|
+
this.executionFailures.delete(sessionId);
|
|
134
|
+
const consecutiveNoProgressTurns = current.consecutiveNoProgressTurns + 1;
|
|
135
|
+
const paused = consecutiveNoProgressTurns >= 3;
|
|
136
|
+
const goal = {
|
|
137
|
+
...current,
|
|
138
|
+
consecutiveNoProgressTurns,
|
|
139
|
+
continuationPaused: paused
|
|
140
|
+
};
|
|
141
|
+
this.goals.set(sessionId, goal);
|
|
142
|
+
this.changed(goal);
|
|
143
|
+
return paused ? 'paused' : 'continue';
|
|
144
|
+
}
|
|
145
|
+
if (!input.failed) {
|
|
146
|
+
this.executionFailures.delete(sessionId);
|
|
147
|
+
if (current.consecutiveNoProgressTurns > 0 || current.continuationPaused) {
|
|
148
|
+
const goal = {
|
|
149
|
+
...current,
|
|
150
|
+
consecutiveNoProgressTurns: 0,
|
|
151
|
+
continuationPaused: false
|
|
152
|
+
};
|
|
153
|
+
this.goals.set(sessionId, goal);
|
|
154
|
+
this.changed(goal);
|
|
155
|
+
}
|
|
156
|
+
return 'continue';
|
|
157
|
+
}
|
|
158
|
+
if (current.consecutiveNoProgressTurns > 0 || current.continuationPaused) {
|
|
159
|
+
const goal = {
|
|
160
|
+
...current,
|
|
161
|
+
consecutiveNoProgressTurns: 0,
|
|
162
|
+
continuationPaused: false
|
|
163
|
+
};
|
|
164
|
+
this.goals.set(sessionId, goal);
|
|
165
|
+
}
|
|
166
|
+
const failures = (this.executionFailures.get(sessionId) ?? 0) + 1;
|
|
167
|
+
this.executionFailures.set(sessionId, failures);
|
|
168
|
+
if (failures <= 3)
|
|
169
|
+
return 'continue';
|
|
170
|
+
const blocked = {
|
|
171
|
+
...(this.goals.get(sessionId) ?? current),
|
|
172
|
+
status: 'blocked'
|
|
173
|
+
};
|
|
174
|
+
this.goals.set(sessionId, blocked);
|
|
175
|
+
this.changed(blocked);
|
|
176
|
+
return 'blocked';
|
|
177
|
+
}
|
|
178
|
+
resume(sessionId) {
|
|
179
|
+
const current = this.goals.get(sessionId);
|
|
180
|
+
if (current?.status !== 'active')
|
|
181
|
+
return current;
|
|
182
|
+
if (!current.continuationPaused && current.consecutiveNoProgressTurns === 0)
|
|
183
|
+
return current;
|
|
184
|
+
const goal = {
|
|
185
|
+
...current,
|
|
186
|
+
consecutiveNoProgressTurns: 0,
|
|
187
|
+
continuationPaused: false
|
|
188
|
+
};
|
|
189
|
+
this.goals.set(sessionId, goal);
|
|
190
|
+
this.changed(goal);
|
|
191
|
+
return goal;
|
|
192
|
+
}
|
|
193
|
+
blockAfterRuntimeFailure(sessionId, goalId, revision) {
|
|
194
|
+
const current = this.requireCurrent(sessionId, goalId, revision);
|
|
195
|
+
const blocked = { ...current, status: 'blocked' };
|
|
196
|
+
this.goals.set(sessionId, blocked);
|
|
197
|
+
this.executionFailures.delete(sessionId);
|
|
198
|
+
this.changed(blocked);
|
|
199
|
+
return blocked;
|
|
200
|
+
}
|
|
201
|
+
update(sessionId, goalId, revision, status) {
|
|
202
|
+
const current = this.requireCurrent(sessionId, goalId, revision);
|
|
203
|
+
if (status === 'blocked') {
|
|
204
|
+
if (current.turns < 3)
|
|
205
|
+
throw new Error('GOAL_BLOCKED_TOO_EARLY');
|
|
206
|
+
if (!current.retryRequired) {
|
|
207
|
+
const retry = {
|
|
208
|
+
...current,
|
|
209
|
+
retryRequired: true,
|
|
210
|
+
retryStartedAtTurn: current.turns
|
|
211
|
+
};
|
|
212
|
+
this.goals.set(sessionId, retry);
|
|
213
|
+
this.changed(retry);
|
|
214
|
+
return retry;
|
|
215
|
+
}
|
|
216
|
+
if (current.retryStartedAtTurn === null || current.turns <= current.retryStartedAtTurn)
|
|
217
|
+
throw new Error('GOAL_BLOCKED_RETRY_REQUIRED');
|
|
218
|
+
}
|
|
219
|
+
const goal = { ...current, status };
|
|
220
|
+
this.goals.set(sessionId, goal);
|
|
221
|
+
this.changed(goal);
|
|
222
|
+
return goal;
|
|
223
|
+
}
|
|
224
|
+
clear(sessionId) {
|
|
225
|
+
const removed = this.goals.delete(sessionId);
|
|
226
|
+
this.executionFailures.delete(sessionId);
|
|
227
|
+
if (removed)
|
|
228
|
+
this.changed(undefined);
|
|
229
|
+
return removed;
|
|
230
|
+
}
|
|
231
|
+
prompt(sessionId, kind) {
|
|
232
|
+
const goal = this.goals.get(sessionId);
|
|
233
|
+
if (goal?.status !== 'active')
|
|
234
|
+
throw new Error('GOAL_NOT_ACTIVE');
|
|
235
|
+
const heading = kind === 'start' ? 'A Goal has started or changed.' : 'Continue the active Goal.';
|
|
236
|
+
const open = kind === 'start' ? START_OPEN : CONTINUE_OPEN;
|
|
237
|
+
const close = kind === 'start' ? START_CLOSE : CONTINUE_CLOSE;
|
|
238
|
+
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${close}`;
|
|
239
|
+
}
|
|
240
|
+
requireCurrent(sessionId, goalId, revision) {
|
|
241
|
+
const current = this.goals.get(sessionId);
|
|
242
|
+
if (current === undefined || current.id !== goalId)
|
|
243
|
+
throw new Error('GOAL_NOT_FOUND');
|
|
244
|
+
if (current.revision !== revision)
|
|
245
|
+
throw new Error('GOAL_REVISION_STALE');
|
|
246
|
+
if (current.status !== 'active')
|
|
247
|
+
throw new Error('GOAL_NOT_ACTIVE');
|
|
248
|
+
return current;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { testMarAgentModelTransport } from '@myagentroam/agent';
|
|
2
2
|
import { marAgentModelTransportTestInputSchema, marAgentModelTransportTestResultSchema } from '@myagentroam/protocol';
|
|
3
3
|
import { runnerErrorProjection } from '../util/runner-error.js';
|
|
4
4
|
export class MarAgentModelTransportTestService {
|
|
5
5
|
options;
|
|
6
|
-
#adapterFactory;
|
|
7
6
|
#timeoutMs;
|
|
8
7
|
constructor(options) {
|
|
9
8
|
this.options = options;
|
|
10
|
-
this.#adapterFactory = options.adapterFactory ?? defaultAdapter;
|
|
11
9
|
this.#timeoutMs = options.timeoutMs ?? 30_000;
|
|
12
10
|
}
|
|
13
11
|
operations() {
|
|
@@ -26,17 +24,7 @@ export class MarAgentModelTransportTestService {
|
|
|
26
24
|
if (configuration === undefined)
|
|
27
25
|
throw new Error('MAR_AGENT_MODEL_TEST_INPUT_INVALID');
|
|
28
26
|
try {
|
|
29
|
-
const
|
|
30
|
-
let completed = false;
|
|
31
|
-
for await (const event of adapter.start({
|
|
32
|
-
system: 'You are performing a model transport connectivity test.',
|
|
33
|
-
messages: [{ role: 'user', content: 'Reply with OK.' }],
|
|
34
|
-
tools: [],
|
|
35
|
-
allowTools: false
|
|
36
|
-
}, AbortSignal.timeout(this.#timeoutMs))) {
|
|
37
|
-
if (event.type === 'completed')
|
|
38
|
-
completed = true;
|
|
39
|
-
}
|
|
27
|
+
const completed = await (this.options.testTransport ?? testMarAgentModelTransport)(configuration, AbortSignal.timeout(this.#timeoutMs));
|
|
40
28
|
return marAgentModelTransportTestResultSchema.parse(completed
|
|
41
29
|
? { success: true, code: null, message: null, httpStatus: null }
|
|
42
30
|
: {
|
|
@@ -66,11 +54,6 @@ function withoutNodeRequestMetadata(raw) {
|
|
|
66
54
|
delete payload.__workspaceWatchSessionHash;
|
|
67
55
|
return payload;
|
|
68
56
|
}
|
|
69
|
-
function defaultAdapter(configuration) {
|
|
70
|
-
return configuration.protocol === 'OPENAI_RESPONSES'
|
|
71
|
-
? new OpenAiResponsesAdapter(configuration)
|
|
72
|
-
: new AnthropicMessagesAdapter(configuration);
|
|
73
|
-
}
|
|
74
57
|
function modelTestErrorProjection(error) {
|
|
75
58
|
if (error === null || typeof error !== 'object')
|
|
76
59
|
return runnerErrorProjection(error, 'MAR_AGENT_MODEL_CONNECTION_FAILED');
|
|
@@ -58,12 +58,12 @@ export class SessionCommandService {
|
|
|
58
58
|
throw new Error('RUNNER_COMMAND_UNAVAILABLE');
|
|
59
59
|
const invocation = parseCommandInvocation({ descriptor: command }, input.input);
|
|
60
60
|
const secretEnvironment = parseSecretEnvironment(input.secretEnvironment);
|
|
61
|
-
if (command.id === '
|
|
61
|
+
if (command.id === 'goal') {
|
|
62
62
|
if (invocation.argument === '--clear')
|
|
63
|
-
return this.options.
|
|
63
|
+
return this.options.clearGoal(session);
|
|
64
64
|
if (invocation.argument.length === 0)
|
|
65
|
-
return this.options.
|
|
66
|
-
return this.options.
|
|
65
|
+
return this.options.beginGoal(session);
|
|
66
|
+
return this.options.goal({
|
|
67
67
|
session,
|
|
68
68
|
objective: invocation.argument,
|
|
69
69
|
...(Number.isSafeInteger(input.__requestUserId)
|
|
@@ -13,7 +13,7 @@ export class SessionIdentityService {
|
|
|
13
13
|
this.options.runtime.promoteSessionIdentity(sessionId, nativeSessionId);
|
|
14
14
|
if (current !== undefined)
|
|
15
15
|
this.options.persist(current, nativeSessionId);
|
|
16
|
-
this.options.
|
|
16
|
+
this.options.migrateGoal(sessionId, nativeSessionId);
|
|
17
17
|
this.options.migrateCommands(sessionId, nativeSessionId);
|
|
18
18
|
this.options.migrateQueue(sessionId, nativeSessionId);
|
|
19
19
|
this.options.migrateRunnerState(sessionId, nativeSessionId);
|
|
@@ -3,8 +3,8 @@ import { isImageAttachment, isRunnerImageAttachment, parseComposerAttachmentIds,
|
|
|
3
3
|
import { parseSecretEnvironment } from '../util/secret-environment.js';
|
|
4
4
|
import { personalInstructionsForRunner } from '../util/personal-instructions.js';
|
|
5
5
|
import { safeErrorCode } from '../util/safe-error.js';
|
|
6
|
-
import {
|
|
7
|
-
const
|
|
6
|
+
import { publicGoalStartText } from './goal-runtime.js';
|
|
7
|
+
const INTERNAL_GOAL = Symbol('internalGoal');
|
|
8
8
|
export class SessionMessageService {
|
|
9
9
|
options;
|
|
10
10
|
pendingMessages = new Map();
|
|
@@ -18,14 +18,14 @@ export class SessionMessageService {
|
|
|
18
18
|
'session.channel.token': (data) => this.channelToken(record(data))
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
submitGoal(input) {
|
|
22
22
|
return this.message({
|
|
23
|
-
[
|
|
23
|
+
[INTERNAL_GOAL]: true,
|
|
24
24
|
sessionId: input.sessionId,
|
|
25
|
-
clientMessageId: `
|
|
26
|
-
content: input.kind === 'start' ?
|
|
25
|
+
clientMessageId: `goal:${randomUUID()}`,
|
|
26
|
+
content: input.kind === 'start' ? publicGoalStartText(input.objective ?? '') : 'Goal Continue',
|
|
27
27
|
__runnerContent: input.content,
|
|
28
|
-
|
|
28
|
+
__goalRef: input.goal,
|
|
29
29
|
...(input.initiatedByUserId === undefined
|
|
30
30
|
? {}
|
|
31
31
|
: { __requestUserId: input.initiatedByUserId }),
|
|
@@ -46,10 +46,8 @@ export class SessionMessageService {
|
|
|
46
46
|
throw new Error('MESSAGE_INVALID');
|
|
47
47
|
const clientMessageId = input.clientMessageId;
|
|
48
48
|
const content = input.content;
|
|
49
|
-
const
|
|
50
|
-
const internalRunnerContent =
|
|
51
|
-
? input.__runnerContent
|
|
52
|
-
: content;
|
|
49
|
+
const internalGoal = input[INTERNAL_GOAL] === true;
|
|
50
|
+
const internalRunnerContent = internalGoal && typeof input.__runnerContent === 'string' ? input.__runnerContent : content;
|
|
53
51
|
const inlineAttachments = parseMessageAttachments(input.attachments);
|
|
54
52
|
const secretEnvironment = parseSecretEnvironment(input.secretEnvironment);
|
|
55
53
|
const attachmentIds = parseComposerAttachmentIds(input.attachmentIds);
|
|
@@ -57,7 +55,7 @@ export class SessionMessageService {
|
|
|
57
55
|
throw new Error('MESSAGE_ATTACHMENTS_INVALID');
|
|
58
56
|
const accepted = await this.options.resolve(input.sessionId);
|
|
59
57
|
const session = accepted.session;
|
|
60
|
-
const personalInstructions =
|
|
58
|
+
const personalInstructions = internalGoal && typeof input.personalInstructions === 'string'
|
|
61
59
|
? input.personalInstructions
|
|
62
60
|
: personalInstructionsForRunner(input.personalInstructions, session.runner);
|
|
63
61
|
const requestedIntent = input.deliveryIntent ?? 'SEND';
|
|
@@ -82,12 +80,10 @@ export class SessionMessageService {
|
|
|
82
80
|
idempotent: true,
|
|
83
81
|
auditReceipt: auditReceipt(session, existing.kind === 'queue' ? 'QUEUE' : 'SEND', existing.run.id, existing.kind === 'queue' ? existing.item.id : undefined)
|
|
84
82
|
};
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
const publicContent = missionMessage?.activated === true ? publicMissionStartText(content) : content;
|
|
90
|
-
const intent = missionMessage === undefined ? requestedIntent : 'REPLACE_CURRENT';
|
|
83
|
+
const goalMessage = internalGoal ? undefined : this.options.goalMessage(session, content);
|
|
84
|
+
const runnerContent = goalMessage?.runnerContent ?? internalRunnerContent;
|
|
85
|
+
const publicContent = goalMessage?.activated === true ? publicGoalStartText(content) : content;
|
|
86
|
+
const intent = goalMessage === undefined ? requestedIntent : 'REPLACE_CURRENT';
|
|
91
87
|
const operation = (async () => {
|
|
92
88
|
const acceptedSession = accepted.session;
|
|
93
89
|
const session = this.options.runtime.getAgentSession(acceptedSession.id) ?? acceptedSession;
|
|
@@ -106,7 +102,7 @@ export class SessionMessageService {
|
|
|
106
102
|
...(inlineAttachments.length === 0 ? {} : { attachments: inlineAttachments })
|
|
107
103
|
}, secretEnvironment);
|
|
108
104
|
const submissionId = created.queueItem?.id ?? created.run.id;
|
|
109
|
-
const sessionForPresentation = input.
|
|
105
|
+
const sessionForPresentation = input.__goal === true
|
|
110
106
|
? session
|
|
111
107
|
: this.options.runtime.setTemporaryTitleIfMissing(session.id, sessionTitleFromFirstMessage(content));
|
|
112
108
|
this.options.emitSession(sessionForPresentation);
|
|
@@ -158,17 +154,17 @@ export class SessionMessageService {
|
|
|
158
154
|
? {}
|
|
159
155
|
: { marAgentRuntimeScopeId: input.marAgentRuntimeScopeId }),
|
|
160
156
|
...(input.computerUse === undefined ? {} : { computerUse: input.computerUse }),
|
|
161
|
-
...(
|
|
162
|
-
? {
|
|
163
|
-
:
|
|
164
|
-
? {
|
|
157
|
+
...(goalMessage !== undefined
|
|
158
|
+
? { goal: goalMessage.goal }
|
|
159
|
+
: isGoalRef(input.__goalRef)
|
|
160
|
+
? { goal: input.__goalRef }
|
|
165
161
|
: {}),
|
|
166
162
|
...(runner.serviceTier() === 'fast' ? { serviceTier: 'fast' } : {})
|
|
167
163
|
});
|
|
168
164
|
this.options.attachments.cache(submissionId, imageAttachments);
|
|
169
|
-
if (
|
|
170
|
-
!this.options.
|
|
171
|
-
throw new Error('
|
|
165
|
+
if (goalMessage !== undefined &&
|
|
166
|
+
!this.options.prepareGoalInsertion(session.id, submissionId, goalMessage.goal))
|
|
167
|
+
throw new Error('GOAL_REVISION_STALE');
|
|
172
168
|
const delivery = this.options.coordinator.settle({
|
|
173
169
|
submissionId,
|
|
174
170
|
intent,
|
|
@@ -179,8 +175,8 @@ export class SessionMessageService {
|
|
|
179
175
|
return delivery;
|
|
180
176
|
}
|
|
181
177
|
catch (error) {
|
|
182
|
-
if (
|
|
183
|
-
this.options.
|
|
178
|
+
if (goalMessage !== undefined)
|
|
179
|
+
this.options.goalPreparationFailed(session, goalMessage.goal, goalMessage.activated);
|
|
184
180
|
this.options.coordinator.failPreparation(submissionId, safeErrorCode(error, 'MESSAGE_PREPARATION_FAILED'));
|
|
185
181
|
this.options.attachments.clear(submissionId);
|
|
186
182
|
this.options.attachments.cleanup(submissionId);
|
|
@@ -252,7 +248,7 @@ function record(value) {
|
|
|
252
248
|
return {};
|
|
253
249
|
return value;
|
|
254
250
|
}
|
|
255
|
-
function
|
|
251
|
+
function isGoalRef(value) {
|
|
256
252
|
return (value !== null &&
|
|
257
253
|
typeof value === 'object' &&
|
|
258
254
|
typeof value.id === 'string' &&
|
|
@@ -45,7 +45,7 @@ export class WorkspaceQueueWorkbenchService {
|
|
|
45
45
|
paused: queue.paused,
|
|
46
46
|
items: queue.itemIds.flatMap((itemId) => {
|
|
47
47
|
const item = this.options.runtime.getQueueItem(itemId);
|
|
48
|
-
if (item === undefined || item.clientMessageId.startsWith('
|
|
48
|
+
if (item === undefined || item.clientMessageId.startsWith('goal:'))
|
|
49
49
|
return [];
|
|
50
50
|
const session = this.options.runtime.getAgentSession(item.sessionId);
|
|
51
51
|
return [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
3
|
import { stripClaudePlanTag } from '../runner-command-engine.js';
|
|
4
|
-
import {
|
|
4
|
+
import { stripGoalStartPrompt } from '../service/goal-runtime.js';
|
|
5
5
|
import { parseCodexComposerImageMarkers } from '../runner/codex/composer-image-markers.js';
|
|
6
6
|
import { normalizeCodexTool } from '../runner/codex/tool-normalizer.js';
|
|
7
7
|
import { normalizeClaudeTool } from '../runner/claude/tool-normalizer.js';
|
|
@@ -435,8 +435,8 @@ function runtimeUserMessagePayload(clientMessageId, runtimeTurns) {
|
|
|
435
435
|
return undefined;
|
|
436
436
|
}
|
|
437
437
|
function nativeUserMessageText(runner, text) {
|
|
438
|
-
const
|
|
439
|
-
const normalized = runner === 'claude-code' ? stripClaudePlanTag(
|
|
438
|
+
const goalFiltered = stripGoalStartPrompt(text);
|
|
439
|
+
const normalized = runner === 'claude-code' ? stripClaudePlanTag(goalFiltered) : goalFiltered;
|
|
440
440
|
if (runner !== 'codex')
|
|
441
441
|
return normalized;
|
|
442
442
|
return parseCodexComposerImageMarkers(normalized).text;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myagentroam/node",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.118",
|
|
4
4
|
"description": "MyAgentRoam Node runtime CLI.",
|
|
5
5
|
"license": "Apache-2.0 AND GPL-2.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
"npm": "11.12.1",
|
|
31
31
|
"ws": "^8.21.3",
|
|
32
32
|
"zod": "4.4.3",
|
|
33
|
-
"@myagentroam/
|
|
34
|
-
"@myagentroam/
|
|
35
|
-
"@myagentroam/
|
|
33
|
+
"@myagentroam/agent": "0.9.118",
|
|
34
|
+
"@myagentroam/code-navigation": "0.9.118",
|
|
35
|
+
"@myagentroam/protocol": "0.9.118"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/ws": "^8.18.1"
|