@myagentroam/node 0.10.22 → 0.10.23
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.
|
@@ -27,21 +27,12 @@ const MANUAL_PREDICTION_TOOL = {
|
|
|
27
27
|
additionalProperties: false
|
|
28
28
|
}
|
|
29
29
|
};
|
|
30
|
-
const REVIEW_TOOL = {
|
|
31
|
-
name: 'submit_prompt_review',
|
|
32
|
-
description: 'Return whether the candidate is a faithful, justified user instruction. This only returns data and performs no action.',
|
|
33
|
-
inputSchema: {
|
|
34
|
-
type: 'object',
|
|
35
|
-
properties: { accept: { type: 'boolean' } },
|
|
36
|
-
required: ['accept'],
|
|
37
|
-
additionalProperties: false
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
30
|
function predictionSystemPrompt(trigger) {
|
|
41
31
|
const manual = trigger === 'MANUAL';
|
|
42
32
|
return [
|
|
43
|
-
"You are Composer Prediction for Prompt Tab
|
|
44
|
-
|
|
33
|
+
"You are Composer Prediction for Prompt Tab: the user composing a message addressed to the agent. The user has read the conversation and is now typing in the composer. Your suggestion becomes the user's editable next message to that same agent.",
|
|
34
|
+
"Speaker: the user. Recipient: the agent. The agent carries out the requested work; the user states what they want the agent to do, check, explain or change. Read the latest agent reply as context the user is responding to, and continue the user's side of that exchange.",
|
|
35
|
+
'Use the user\'s own language and concise voice, with a direct request or question. During execution, a user message might be "Focus on API compatibility first." After an explanation, it might be "Check which request produced this error and explain the cause." After completed work, it might be "Verify the remaining acceptance criteria." A draft such as "compatibility first" can become "Check API compatibility before changing the UI."',
|
|
45
36
|
...(manual
|
|
46
37
|
? [
|
|
47
38
|
'Manual invocation: the user has explicitly asked for help composing a message now. Return one useful nonempty candidate even with an empty draft or a completed task. Use a grounded intervention while work is running and a grounded next step after completion. When no distinct task remains, choose the smallest relevant read-only follow-up or clarification; with no conversation history, ask the agent to establish the current workspace state.'
|
|
@@ -71,13 +62,7 @@ function predictionSystemPrompt(trigger) {
|
|
|
71
62
|
'Reference messages from other sessions are style examples ONLY, not current tasks, facts or constraints. Never import their file names, goals, prohibitions or workflow into this conversation. Prefer the latest explicit user request and the most recent public agent update.',
|
|
72
63
|
'Keep the message concise and actionable, usually one to three sentences. Do not add generic checklists or invent a requirement to review-only, not modify, commit, deploy or stop. RUNNING interventions must resolve an identifiable risk or express the draft intent, not repeat work the agent is already doing. After COMPLETED, either address a stated remaining item or propose the smallest useful verification/continuation justified by the result.',
|
|
73
64
|
'For COMPLETE, return only the text to insert at the UTF-16 cursor position. Do not repeat the draft prefix or suffix, and leave text outside the cursor unchanged.',
|
|
74
|
-
|
|
75
|
-
...(manual
|
|
76
|
-
? [
|
|
77
|
-
'For manual review, judge the candidate as a user message addressed to the agent, with the agent as the actor for requested work. Accept a conservative read-only follow-up or clarification when no concrete pending task remains, including after COMPLETED. Completion alone is not grounds for rejection; distinctness, factual grounding and existing authorization boundaries still apply.'
|
|
78
|
-
]
|
|
79
|
-
: []),
|
|
80
|
-
`Submit the result exactly once through the available result tool: submit_prompt_prediction with {"suggestion":${manual ? 'nonempty string' : 'string|null'}}, or submit_prompt_review with {"accept":boolean} for review input. These tools only return data and perform no action. Do not write the result as prose, use Markdown fences, call other tools, or add commentary.`
|
|
65
|
+
`Submit the user's message exactly once through submit_prompt_prediction with {"suggestion":${manual ? 'nonempty string' : 'string|null'}}. This tool only returns data and performs no action. Do not write the result as prose, use Markdown fences, call other tools, or add commentary.`
|
|
81
66
|
].join(' ');
|
|
82
67
|
}
|
|
83
68
|
/** Generate structured result data without executing tools or creating a Session. */
|
|
@@ -88,7 +73,7 @@ export async function generatePromptCompletion(input) {
|
|
|
88
73
|
return { suggestion: null };
|
|
89
74
|
const system = predictionSystemPrompt(input.trigger);
|
|
90
75
|
const predictionTool = input.trigger === 'MANUAL' ? MANUAL_PREDICTION_TOOL : PREDICTION_TOOL;
|
|
91
|
-
const toolInputTokens =
|
|
76
|
+
const toolInputTokens = countModelTokens(JSON.stringify(predictionTool));
|
|
92
77
|
const outputLimit = Math.min(MAX_OUTPUT_TOKENS, input.model.maxOutputTokens, Math.max(1, Math.floor(input.model.contextWindowTokens / 4)));
|
|
93
78
|
const inputTokenBudget = Math.min(MAX_INPUT_TOKENS, input.model.contextWindowTokens - outputLimit - INPUT_CONTEXT_RESERVE_TOKENS) - toolInputTokens;
|
|
94
79
|
if (inputTokenBudget <= 0)
|
|
@@ -161,7 +146,7 @@ export async function generatePromptCompletion(input) {
|
|
|
161
146
|
messages = [...references.messages, ...history.messages, currentMessage];
|
|
162
147
|
}
|
|
163
148
|
input.onPreparedInput?.({
|
|
164
|
-
templateVersion:
|
|
149
|
+
templateVersion: 13,
|
|
165
150
|
system,
|
|
166
151
|
messages,
|
|
167
152
|
tools: [predictionTool],
|
|
@@ -191,54 +176,8 @@ export async function generatePromptCompletion(input) {
|
|
|
191
176
|
const generated = await generateModelText(invocation);
|
|
192
177
|
const output = resultPayload(generated, PREDICTION_TOOL.name);
|
|
193
178
|
const strictSuggestion = parseSuggestion(output);
|
|
194
|
-
|
|
179
|
+
const suggestion = strictSuggestion ?? (generated?.toolCalls?.length ? null : parseSuggestion(output, true));
|
|
195
180
|
const plainText = strictSuggestion === null && suggestion !== null;
|
|
196
|
-
let review;
|
|
197
|
-
let qualityAccepted;
|
|
198
|
-
let reviewIssue;
|
|
199
|
-
if (suggestion !== null) {
|
|
200
|
-
const reviewMessages = [
|
|
201
|
-
...messages,
|
|
202
|
-
{
|
|
203
|
-
role: 'user',
|
|
204
|
-
content: JSON.stringify({
|
|
205
|
-
kind: 'review',
|
|
206
|
-
candidate: suggestion,
|
|
207
|
-
completionMode: input.completionMode
|
|
208
|
-
})
|
|
209
|
-
}
|
|
210
|
-
];
|
|
211
|
-
if (countRequestInputTokens(system, reviewMessages) > inputTokenBudget) {
|
|
212
|
-
qualityAccepted = false;
|
|
213
|
-
reviewIssue = 'review_budget_exceeded';
|
|
214
|
-
}
|
|
215
|
-
else {
|
|
216
|
-
const checked = await generateModelText({
|
|
217
|
-
...invocation,
|
|
218
|
-
messages: reviewMessages,
|
|
219
|
-
tools: [REVIEW_TOOL],
|
|
220
|
-
outputLimit: Math.min(outputLimit, 1_024),
|
|
221
|
-
cachePrefixMessages: messages.length
|
|
222
|
-
});
|
|
223
|
-
review = resultPayload(checked, REVIEW_TOOL.name);
|
|
224
|
-
try {
|
|
225
|
-
const value = JSON.parse(review ?? '');
|
|
226
|
-
if (typeof value !== 'object' ||
|
|
227
|
-
value === null ||
|
|
228
|
-
Array.isArray(value) ||
|
|
229
|
-
Object.keys(value).length !== 1 ||
|
|
230
|
-
typeof value.accept !== 'boolean')
|
|
231
|
-
throw new Error('Invalid review output');
|
|
232
|
-
qualityAccepted = value.accept;
|
|
233
|
-
}
|
|
234
|
-
catch {
|
|
235
|
-
qualityAccepted = false;
|
|
236
|
-
reviewIssue = checked === undefined ? 'review_incomplete' : 'review_invalid_output';
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
if (!qualityAccepted)
|
|
240
|
-
suggestion = null;
|
|
241
|
-
}
|
|
242
181
|
let abstained = false;
|
|
243
182
|
try {
|
|
244
183
|
const value = JSON.parse(output ?? '');
|
|
@@ -254,23 +193,19 @@ export async function generatePromptCompletion(input) {
|
|
|
254
193
|
}
|
|
255
194
|
const outcome = generated === undefined
|
|
256
195
|
? 'generation_incomplete'
|
|
257
|
-
:
|
|
258
|
-
|
|
259
|
-
? '
|
|
260
|
-
: abstained
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
: suggestion === null
|
|
265
|
-
? 'invalid_output'
|
|
266
|
-
: 'accepted'));
|
|
196
|
+
: abstained
|
|
197
|
+
? input.trigger === 'MANUAL'
|
|
198
|
+
? 'manual_result_missing'
|
|
199
|
+
: 'abstained'
|
|
200
|
+
: suggestion === null
|
|
201
|
+
? 'invalid_output'
|
|
202
|
+
: 'accepted';
|
|
267
203
|
input.onPredictionOutput?.({
|
|
268
204
|
text: generated?.text?.slice(0, 8192) ?? null,
|
|
269
205
|
outputSource: generated?.toolCalls?.length ? 'tool' : 'text',
|
|
270
206
|
...(generated?.toolCalls?.length ? { toolOutput: output?.slice(0, 8192) ?? null } : {}),
|
|
271
207
|
parsed: strictSuggestion !== null || plainText || abstained,
|
|
272
208
|
plainText,
|
|
273
|
-
...(qualityAccepted === undefined ? {} : { qualityAccepted, review: review?.slice(0, 1024) }),
|
|
274
209
|
abstained,
|
|
275
210
|
outcome
|
|
276
211
|
});
|
|
@@ -112,8 +112,6 @@ export class PromptCompletionNodeService {
|
|
|
112
112
|
const { runtime: rawRuntime, ...publicInput } = data;
|
|
113
113
|
const input = promptCompletionGenerateInputSchema.parse(publicInput);
|
|
114
114
|
const runtime = promptCompletionRuntimeSchema.parse(rawRuntime);
|
|
115
|
-
if (runtime.expiresAt > this.now() + 30_000)
|
|
116
|
-
throw new Error('PROMPT_COMPLETION_AUTHORIZATION_INVALID');
|
|
117
115
|
if (input.target.kind === 'WORKSPACE' && input.target.workspaceId !== runtime.workspaceId)
|
|
118
116
|
throw new Error('PROMPT_COMPLETION_AUTHORIZATION_INVALID');
|
|
119
117
|
const descriptor = {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { createHash, randomUUID } from 'node:crypto';
|
|
2
2
|
import { generatePromptCompletion } from './prompt-completion-generator.js';
|
|
3
3
|
import { promptCompletionRequestSchema, promptCompletionCancelSchema } from '@myagentroam/protocol';
|
|
4
|
+
// Keep cancellation watermarks longer than the five-minute runtime authorization.
|
|
5
|
+
const PAGE_INTENT_TTL_MS = 6 * 60_000;
|
|
4
6
|
/** One manual auxiliary request; it never mutates a Session or enqueues a Run. */
|
|
5
7
|
export class PromptCompletionService {
|
|
6
8
|
options;
|
|
@@ -90,7 +92,7 @@ export class PromptCompletionService {
|
|
|
90
92
|
userId: authorization.userId,
|
|
91
93
|
requestId: request.requestId,
|
|
92
94
|
sequence: request.intentSequence,
|
|
93
|
-
expiresAt: this.now() +
|
|
95
|
+
expiresAt: this.now() + PAGE_INTENT_TTL_MS,
|
|
94
96
|
closed: false,
|
|
95
97
|
active: { controller, workspaceId: authorization.scope.workspaceId }
|
|
96
98
|
};
|
|
@@ -220,14 +222,14 @@ export class PromptCompletionService {
|
|
|
220
222
|
if (page) {
|
|
221
223
|
page.sequence = request.intentSequence;
|
|
222
224
|
page.requestId = request.requestId;
|
|
223
|
-
page.expiresAt = this.now() +
|
|
225
|
+
page.expiresAt = this.now() + PAGE_INTENT_TTL_MS;
|
|
224
226
|
}
|
|
225
227
|
else
|
|
226
228
|
this.pages.set(key, {
|
|
227
229
|
userId,
|
|
228
230
|
requestId: request.requestId,
|
|
229
231
|
sequence: request.intentSequence,
|
|
230
|
-
expiresAt: this.now() +
|
|
232
|
+
expiresAt: this.now() + PAGE_INTENT_TTL_MS,
|
|
231
233
|
closed: false
|
|
232
234
|
});
|
|
233
235
|
}
|
|
@@ -248,7 +250,7 @@ export class PromptCompletionService {
|
|
|
248
250
|
if (!page)
|
|
249
251
|
return;
|
|
250
252
|
page.closed = true;
|
|
251
|
-
page.expiresAt = this.now() +
|
|
253
|
+
page.expiresAt = this.now() + PAGE_INTENT_TTL_MS;
|
|
252
254
|
page.active?.controller.abort();
|
|
253
255
|
}
|
|
254
256
|
disconnect() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myagentroam/node",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.23",
|
|
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.
|
|
40
|
+
"@myagentroam/agent": "0.10.23",
|
|
41
41
|
"@myagentroam/code-navigation": "0.10.1",
|
|
42
42
|
"@myagentroam/marctl": "0.10.2",
|
|
43
|
-
"@myagentroam/protocol": "0.10.
|
|
43
|
+
"@myagentroam/protocol": "0.10.23"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/ws": "^8.18.1"
|