@myagentroam/node 0.10.22 → 0.10.24

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.
@@ -209,14 +209,17 @@ function resolvedMcpServers(raw, secrets) {
209
209
  lifecycle: 'EXECUTION',
210
210
  origin: 'BUILTIN',
211
211
  allowedToolCallers: record['__marGoal'] === true
212
- ? { mar_get_goal: ['direct', 'programmatic'], mar_update_goal: ['direct'] }
212
+ ? {
213
+ mar_get_goal: ['direct', 'programmatic'],
214
+ mar_update_goal: ['direct', 'programmatic']
215
+ }
213
216
  : record['__marScheduled'] === true
214
217
  ? {
215
218
  mar_get_scheduled_task: ['direct', 'programmatic'],
216
- mar_create_scheduled_task: ['direct'],
217
- mar_update_scheduled_task: ['direct']
219
+ mar_create_scheduled_task: ['direct', 'programmatic'],
220
+ mar_update_scheduled_task: ['direct', 'programmatic']
218
221
  }
219
- : { mar_send_email_notification: ['direct'] },
222
+ : { mar_send_email_notification: ['direct', 'programmatic'] },
220
223
  transport: 'STDIO',
221
224
  command: record['command'],
222
225
  args: record['args'],
@@ -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. Write as the user composing a message addressed to the agent in the conversation composer. Your output will become the user's editable draft, which the user may send as their own next message. The user is directing the work; the agent is the recipient who carries it out.",
44
- 'Express the user\'s request, question, or change of emphasis in their own concise voice. For example, during execution: "Focus on API compatibility first." After completion: "Check whether the result meets the acceptance criteria." With a draft: turn its intent into a clear request addressed to the agent. Statements about intended work belong to the agent\'s replies; this scene calls for the user\'s instruction to that agent.',
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
- 'If the final input has kind="review", validate its candidate instead of generating: submit {"accept":true} or {"accept":false} through submit_prompt_review. Reject revived historical problems, unsupported facts or current execution status, broadened constraints, invented user commitments, conflated independent checks, and invented permission for an external action. For NEXT accept only a distinct useful next instruction, not an action already underway or completed. In COMPLETED, a check explicitly reported as not run is unresolved work, not a duplicate merely because it was mentioned before. Accept a bounded next step to resolve that known verification gap, including necessary test-environment setup when current constraints permit it; reject only actual conflicts, unsupported scope, or commitments. A suggested future check does not assert that it has already been performed. For REWRITE accept a concise faithful expression of the current draft intent, even if its explicit constraints overlap history; reject additional replayed commands or task steps that the draft did not request. Reject answers written as the agent, model commentary, and unrelated prose. No explanation is needed.',
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 = Math.max(countModelTokens(JSON.stringify(predictionTool)), countModelTokens(JSON.stringify(REVIEW_TOOL)));
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: 12,
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
- let suggestion = strictSuggestion ?? (generated?.toolCalls?.length ? null : parseSuggestion(output, true));
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
- : (reviewIssue ??
258
- (qualityAccepted === false
259
- ? 'quality_rejected'
260
- : abstained
261
- ? input.trigger === 'MANUAL'
262
- ? 'manual_result_missing'
263
- : 'abstained'
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() + 60_000,
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() + 60_000;
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() + 60_000,
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() + 60_000;
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.22",
3
+ "version": "0.10.24",
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.22",
40
+ "@myagentroam/agent": "0.10.24",
41
41
  "@myagentroam/code-navigation": "0.10.1",
42
- "@myagentroam/marctl": "0.10.2",
43
- "@myagentroam/protocol": "0.10.22"
42
+ "@myagentroam/marctl": "0.10.3",
43
+ "@myagentroam/protocol": "0.10.24"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@types/ws": "^8.18.1"