@myagentroam/node 0.11.15 → 0.11.16

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.
Files changed (51) hide show
  1. package/dist/connector.js +13 -20
  2. package/dist/native-session-history.js +35 -832
  3. package/dist/native-transcript-adapters.js +9 -0
  4. package/dist/native-transcript-model.js +1 -0
  5. package/dist/runner/abstract-runner.js +12 -0
  6. package/dist/runner/claude/conversation-parser.js +80 -1
  7. package/dist/runner/claude/managed-run-controller.js +4 -2
  8. package/dist/runner/claude/message-parsers.js +37 -0
  9. package/dist/runner/claude/native-context-usage.js +90 -0
  10. package/dist/runner/claude/native-transcript.js +347 -0
  11. package/dist/runner/claude/tool-normalizer.js +12 -2
  12. package/dist/runner/claude-code-runner.js +13 -2
  13. package/dist/runner/codex/conversation-parser.js +67 -3
  14. package/dist/runner/codex/managed-run-controller.js +3 -2
  15. package/dist/runner/codex/native-context-usage.js +42 -0
  16. package/dist/runner/codex/native-transcript.js +575 -0
  17. package/dist/runner/codex-runner.js +18 -3
  18. package/dist/runner/mar-agent/managed-run-controller.js +1 -1
  19. package/dist/runner/mar-agent-runner.js +6 -0
  20. package/dist/runner/opencode/conversation-parser.js +1 -1
  21. package/dist/runner/opencode/managed-run-controller.js +1 -1
  22. package/dist/runner/opencode-runner.js +7 -1
  23. package/dist/runner/runner-registry.js +4 -0
  24. package/dist/runtime-state.js +1 -0
  25. package/dist/service/continuous-run-coordinator.js +1 -0
  26. package/dist/service/conversation-template-manifest.js +179 -0
  27. package/dist/service/conversation-template-node-service.js +10 -132
  28. package/dist/service/external-session-resume-service.js +15 -0
  29. package/dist/service/fake-managed-run-service.js +1 -1
  30. package/dist/service/goal-continuation-coordinator.js +4 -3
  31. package/dist/service/goal-runtime.js +0 -9
  32. package/dist/service/hosted-conversation-node-service.js +16 -179
  33. package/dist/service/native-session-projection-service.js +7 -24
  34. package/dist/service/node-control-channel.js +1 -1
  35. package/dist/service/node-request-service.js +1 -1
  36. package/dist/service/node-run-event-bridge.js +0 -24
  37. package/dist/service/node-terminal-channel.js +1 -1
  38. package/dist/service/recent-run-projection-service.js +2 -1
  39. package/dist/service/run-workbench-service.js +1 -1
  40. package/dist/service/runner-interaction-service.js +2 -1
  41. package/dist/service/runner-service.js +6 -4
  42. package/dist/service/session-identity-service.js +1 -0
  43. package/dist/service/session-message-service.js +1 -0
  44. package/dist/service/session-query-service.js +1 -1
  45. package/dist/service/workbench-event-projection.js +1 -1
  46. package/dist/service/workbench-event-service.js +1 -1
  47. package/dist/service/workspace-file-service.js +0 -2
  48. package/dist/service/workspace-queue-workbench-service.js +2 -2
  49. package/dist/util/node-operation-parsers.js +0 -45
  50. package/dist/util/runner-native-session-parsers.js +17 -194
  51. package/package.json +4 -4
@@ -1,22 +1,6 @@
1
+ import { nativeTranscriptAdapter } from '../native-transcript-adapters.js';
1
2
  import { createHash } from 'node:crypto';
2
- import { fileURLToPath } from 'node:url';
3
- import { stripClaudePlanTag } from '../runner-command-engine.js';
4
- import { publicGoalHistoryText } from '../service/goal-runtime.js';
5
- import { parseCodexComposerImageMarkers } from '../runner/codex/composer-image-markers.js';
6
- import { normalizeCodexTool } from '../runner/codex/tool-normalizer.js';
7
- import { normalizeClaudeTool, restoreClaudeSubagentTitles } from '../runner/claude/tool-normalizer.js';
8
3
  import { compactRunnerText, isPlainRecord, nativePageEnd } from './node-operation-parsers.js';
9
- export function extractId(result, key) {
10
- if (typeof result === 'object' &&
11
- result !== null &&
12
- key in result &&
13
- typeof result[key] === 'object' &&
14
- result[key] !== null &&
15
- typeof result[key]['id'] === 'string') {
16
- return result[key]['id'];
17
- }
18
- throw new Error(`CODEX_${key.toUpperCase()}_ID_MISSING`);
19
- }
20
4
  export async function settleWithin(promise, milliseconds) {
21
5
  let timer;
22
6
  try {
@@ -33,51 +17,6 @@ export async function settleWithin(promise, milliseconds) {
33
17
  clearTimeout(timer);
34
18
  }
35
19
  }
36
- export function extractCodexThreads(result) {
37
- if (typeof result !== 'object' || result === null || !('data' in result))
38
- return [];
39
- const data = result.data;
40
- if (!Array.isArray(data))
41
- return [];
42
- return data.flatMap((entry) => {
43
- if (typeof entry !== 'object' || entry === null)
44
- return [];
45
- const value = entry;
46
- if (typeof value.id !== 'string')
47
- return [];
48
- const source = typeof value.sourceKind === 'string'
49
- ? value.sourceKind
50
- : typeof value.source === 'string'
51
- ? value.source
52
- : typeof value.source === 'object' &&
53
- value.source !== null &&
54
- typeof value.source.kind === 'string'
55
- ? value.source.kind
56
- : undefined;
57
- const sourceRecord = isPlainRecord(value.source) ? value.source : undefined;
58
- const derived = source === 'subagent' ||
59
- sourceRecord?.kind === 'subagent' ||
60
- isPlainRecord(sourceRecord?.subagent) ||
61
- isPlainRecord(sourceRecord?.subAgent);
62
- const name = typeof value.name === 'string' ? value.name.trim() : '';
63
- const preview = typeof value.preview === 'string' ? value.preview.trim() : '';
64
- const title = name || preview || undefined;
65
- const titleOrigin = name ? 'OFFICIAL' : preview ? 'PREVIEW' : undefined;
66
- return [{ id: value.id, source, derived, cwd: value.cwd, title, titleOrigin }];
67
- });
68
- }
69
- export function codexThreadCwd(value) {
70
- if (typeof value !== 'string' || value.length === 0)
71
- throw new Error('CODEX_THREAD_CWD_INVALID');
72
- if (!value.startsWith('file:'))
73
- return value;
74
- try {
75
- return fileURLToPath(value);
76
- }
77
- catch {
78
- throw new Error('CODEX_THREAD_CWD_INVALID');
79
- }
80
- }
81
20
  export function isWithinWorkspace(cwd, workspacePath) {
82
21
  const normalize = (value) => {
83
22
  const compact = value.replace(/[\\/]+/g, '/').replace(/\/$/, '');
@@ -89,36 +28,6 @@ export function isWithinWorkspace(cwd, workspacePath) {
89
28
  return true;
90
29
  return normalizedCwd.startsWith(`${normalizedWorkspace}/`);
91
30
  }
92
- export function claudeDiscoveredSession(value, fallbackCwd) {
93
- if (typeof value !== 'object' || value === null)
94
- return undefined;
95
- const record = value;
96
- if (record.isSidechain === true)
97
- return undefined;
98
- const externalSessionId = typeof record.sessionId === 'string'
99
- ? record.sessionId
100
- : typeof record.id === 'string'
101
- ? record.id
102
- : undefined;
103
- if (externalSessionId === undefined || externalSessionId.length === 0)
104
- return undefined;
105
- const officialTitle = [record.customTitle, record.firstPrompt, record.title].find((candidate) => typeof candidate === 'string' && candidate.trim().length > 0);
106
- const previewTitle = typeof record.summary === 'string' && record.summary.trim().length > 0
107
- ? record.summary
108
- : undefined;
109
- const title = officialTitle ?? previewTitle;
110
- const cwd = typeof record.cwd === 'string' && record.cwd.length > 0 ? record.cwd : fallbackCwd;
111
- return {
112
- externalSessionId,
113
- cwd,
114
- ...(title === undefined
115
- ? {}
116
- : {
117
- title: title.slice(0, 80),
118
- titleOrigin: officialTitle === undefined ? 'PREVIEW' : 'OFFICIAL'
119
- })
120
- };
121
- }
122
31
  export function latestNativeActivity(history) {
123
32
  return history.lastActivityAt;
124
33
  }
@@ -148,17 +57,13 @@ export function nativeConversationPage(session, history, input, runtimeTurns = [
148
57
  const nativeTurnIds = nativeTranscriptTurnIds(session.id, nativeTurns);
149
58
  const end = nativePageEnd(effectiveCursor, session.id, nativeTurns.length);
150
59
  const start = Math.max(0, end - limit);
151
- const knownClaudeSubagents = restoreClaudeSubagentTitles(session.runner === 'claude-code'
152
- ? history.items
153
- .slice(0, nativeTurns[start]?.[0]?.index ?? 0)
154
- .filter((entry) => entry.kind === 'tool_call')
155
- : []);
60
+ const projection = nativeTranscriptAdapter(session.runner).createProjection(history.items.slice(0, nativeTurns[start]?.[0]?.index ?? 0));
156
61
  const nativePageTurns = nativeTurns
157
62
  .slice(start, end)
158
63
  .map((entries, relativeIndex) => {
159
64
  const nativeUser = entries.find(({ entry }) => entry.kind === 'message' && entry.role === 'USER')?.entry;
160
65
  const matchedClientMessageId = nativeUser?.kind === 'message'
161
- ? nativeUserClientMessageId(session.runner, nativeUser, nativeUser.createdAt, runtimeTurns)
66
+ ? nativeUserClientMessageId(projection.userText(nativeUser.text), nativeUser.createdAt, runtimeTurns)
162
67
  : null;
163
68
  const runtimeTurn = typeof matchedClientMessageId === 'string'
164
69
  ? runtimeTurns.find((turn) => runtimeTurnClientMessageId(turn) === matchedClientMessageId)
@@ -166,7 +71,7 @@ export function nativeConversationPage(session, history, input, runtimeTurns = [
166
71
  const turnId = runtimeTurn?.id ?? nativeTurnIds[start + relativeIndex];
167
72
  const itemIdentities = nativeTranscriptItemIdentities(entries);
168
73
  const nativeItems = entries.map(({ entry, index }, entryIndex) => ({
169
- ...nativeTranscriptConversationItem(session, entry, index, itemIdentities[entryIndex], turnId, runtimeTurns, registerImages, knownClaudeSubagents),
74
+ ...nativeTranscriptConversationItem(session, entry, index, itemIdentities[entryIndex], turnId, runtimeTurns, registerImages, projection),
170
75
  runId: runtimeTurn?.runId ?? null
171
76
  }));
172
77
  const runtimeErrors = (runtimeTurn?.items ?? [])
@@ -201,7 +106,7 @@ export function nativeConversationPage(session, history, input, runtimeTurns = [
201
106
  model: null,
202
107
  effort: null,
203
108
  access: null,
204
- ...(after === undefined || session.runner !== 'claude-code'
109
+ ...(after === undefined
205
110
  ? {}
206
111
  : {
207
112
  rewind: {
@@ -256,7 +161,7 @@ function runtimeTurnClientMessageId(turn) {
256
161
  : undefined;
257
162
  }
258
163
  function lastNativeItemId(entries) {
259
- return entries.findLast(({ entry }) => entry.nativeId !== undefined)?.entry.nativeId;
164
+ return entries.findLast(({ entry }) => entry.rewindAfter !== undefined)?.entry.rewindAfter;
260
165
  }
261
166
  function nativeTranscriptTurnIds(sessionId, turns) {
262
167
  const occurrences = new Map();
@@ -312,41 +217,21 @@ function nativeTranscriptTurns(items) {
312
217
  turns.push(current);
313
218
  return turns;
314
219
  }
315
- function nativeTranscriptConversationItem(session, entry, index, itemIdentity, turnId, runtimeTurns, registerImages, knownClaudeSubagents) {
220
+ function nativeTranscriptConversationItem(session, entry, index, itemIdentity, turnId, runtimeTurns, registerImages, projection) {
316
221
  const time = entry.createdAt;
317
222
  const isToolCall = entry.kind === 'tool_call';
318
223
  const isUnknown = entry.kind === 'unknown';
319
224
  const isReasoning = entry.kind === 'reasoning_summary';
320
225
  const isContextCompaction = entry.kind === 'context_compaction';
321
- const normalizedClaudeTool = session.runner === 'claude-code' && isToolCall
322
- ? normalizeClaudeTool(entry.toolName, entry.input, entry.outputSummary, entry.failed, entry.inputTruncated || entry.outputTruncated, knownClaudeSubagents, entry.claudeResult)
323
- : undefined;
324
- const normalizedCodexTool = session.runner === 'codex' && isToolCall
325
- ? normalizeCodexTool({
326
- name: entry.toolName,
327
- namespace: 'codex',
328
- rawInput: entry.input,
329
- inputSummary: entry.inputSummary,
330
- outputSummary: entry.outputSummary,
331
- truncated: entry.inputTruncated || entry.outputTruncated,
332
- ...(entry.imageAttachments === undefined ? {} : { attachments: entry.imageAttachments })
333
- })
334
- : undefined;
335
- const userInputQuestions = session.runner === 'claude-code' &&
336
- isToolCall &&
337
- entry.toolName === 'AskUserQuestion' &&
338
- isPlainRecord(entry.input)
339
- ? claudeUserInputQuestions(entry.input)
340
- : [];
226
+ const normalizedTool = isToolCall ? projection.normalizeTool(entry) : undefined;
227
+ const userInputQuestions = isToolCall ? projection.userInputQuestions(entry) : [];
341
228
  const isUserInputRequest = userInputQuestions.length > 0;
342
229
  const clientMessageId = entry.kind === 'message' && entry.role === 'USER'
343
- ? nativeUserClientMessageId(session.runner, entry, time, runtimeTurns)
230
+ ? nativeUserClientMessageId(projection.userText(entry.text), time, runtimeTurns)
344
231
  : null;
345
- // Claude tagged Plan Mode strips the injected planning instruction label from user content
346
- // and normalizes a complete <proposed_plan> Agent response into a plan card.
347
232
  const entryText = entry.kind === 'message'
348
233
  ? entry.role === 'USER'
349
- ? nativeUserMessageText(session.runner, entry.text)
234
+ ? projection.userText(entry.text)
350
235
  : entry.text
351
236
  : '';
352
237
  const runtimeUserPayload = clientMessageId === null ? undefined : runtimeUserMessagePayload(clientMessageId, runtimeTurns);
@@ -355,7 +240,7 @@ function nativeTranscriptConversationItem(session, entry, index, itemIdentity, t
355
240
  : entry.kind === 'message' && entry.role === 'USER' && entry.imageAttachments !== undefined
356
241
  ? registerImages(entry.imageAttachments)
357
242
  : [];
358
- const planText = entry.kind === 'message' && entry.role !== 'USER' ? claudePlanText(entryText) : undefined;
243
+ const planText = entry.kind === 'message' && entry.role !== 'USER' ? projection.planText(entryText) : undefined;
359
244
  const item = {
360
245
  id: `${turnId}:item:${itemIdentity}`,
361
246
  ...(entry.sourceItemId === undefined ? {} : { sourceItemId: entry.sourceItemId }),
@@ -372,7 +257,7 @@ function nativeTranscriptConversationItem(session, entry, index, itemIdentity, t
372
257
  : isContextCompaction
373
258
  ? 'context_compaction'
374
259
  : isToolCall
375
- ? (normalizedClaudeTool?.kind ?? normalizedCodexTool?.kind ?? 'tool_call')
260
+ ? (normalizedTool?.kind ?? 'tool_call')
376
261
  : isUnknown
377
262
  ? 'unknown'
378
263
  : entry.kind === 'message' && entry.role === 'USER'
@@ -392,8 +277,7 @@ function nativeTranscriptConversationItem(session, entry, index, itemIdentity, t
392
277
  ? { phase: entry.phase, summary: entry.summary }
393
278
  : isToolCall
394
279
  ? {
395
- ...(normalizedClaudeTool?.payload ??
396
- normalizedCodexTool?.payload ?? {
280
+ ...(normalizedTool?.payload ?? {
397
281
  namespace: session.runner,
398
282
  toolName: entry.toolName,
399
283
  title: entry.toolName,
@@ -427,10 +311,10 @@ function nativeTranscriptConversationItem(session, entry, index, itemIdentity, t
427
311
  return item;
428
312
  }
429
313
  /**
430
- * Claude JSONL does not retain browser request IDs. While the Node process is alive, match current
314
+ * Native history may not retain browser request IDs. While the Node process is alive, match current
431
315
  * runtime user messages by content and creation time so native history replaces the optimistic Turn.
432
316
  */
433
- export function nativeUserClientMessageId(runner, entry, createdAt, runtimeTurns) {
317
+ export function nativeUserClientMessageId(text, createdAt, runtimeTurns) {
434
318
  const candidates = [];
435
319
  for (const turn of runtimeTurns) {
436
320
  const user = turn.items.find((item) => item.kind === 'user_message');
@@ -438,8 +322,7 @@ export function nativeUserClientMessageId(runner, entry, createdAt, runtimeTurns
438
322
  continue;
439
323
  const payload = user.payload;
440
324
  const clientMessageId = typeof payload.clientMessageId === 'string' ? payload.clientMessageId : null;
441
- // Tagged Plan Mode instruction labels exist only in native transcripts; runtime bubbles retain the original content.
442
- if (clientMessageId === null || payload.text !== nativeUserMessageText(runner, entry.text))
325
+ if (clientMessageId === null || payload.text !== text)
443
326
  continue;
444
327
  const runtimeCreatedAt = user.startedAt ?? turn.startedAt;
445
328
  candidates.push({ clientMessageId, createdAt: runtimeCreatedAt ?? null });
@@ -465,63 +348,3 @@ function runtimeUserMessagePayload(clientMessageId, runtimeTurns) {
465
348
  }
466
349
  return undefined;
467
350
  }
468
- function nativeUserMessageText(runner, text) {
469
- const withoutPlan = runner === 'claude-code' ? stripClaudePlanTag(text) : text;
470
- const normalized = publicGoalHistoryText(withoutPlan);
471
- if (runner !== 'codex')
472
- return normalized;
473
- return parseCodexComposerImageMarkers(normalized).text;
474
- }
475
- /**
476
- * Normalize the documented App Server `thread/read(includeTurns: true)`
477
- * result. Only items with a user-visible Workbench representation are kept;
478
- * raw protocol envelopes are deliberately never exposed to Web.
479
- */
480
- export function claudePlanText(text) {
481
- const trimmed = text.trim();
482
- if (!trimmed.startsWith('<proposed_plan>') || !/<\/proposed_plan>\s*$/.test(trimmed))
483
- return undefined;
484
- const plan = trimmed
485
- .slice('<proposed_plan>'.length)
486
- .replace(/<\/proposed_plan>\s*$/, '')
487
- .trim();
488
- return plan.length > 0 ? plan : undefined;
489
- }
490
- export function claudeUserInputQuestions(value) {
491
- if (!Array.isArray(value.questions) || value.questions.length === 0 || value.questions.length > 4)
492
- return [];
493
- const questions = value.questions.map((raw, index) => {
494
- if (!isPlainRecord(raw) || typeof raw.question !== 'string')
495
- return undefined;
496
- const options = Array.isArray(raw.options)
497
- ? raw.options.flatMap((option) => {
498
- if (!isPlainRecord(option) || typeof option.label !== 'string')
499
- return [];
500
- const label = compactRunnerText(option.label, 500);
501
- return label.length === 0
502
- ? []
503
- : [
504
- {
505
- value: label,
506
- label,
507
- description: typeof option.description === 'string'
508
- ? compactRunnerText(option.description, 1_000)
509
- : null
510
- }
511
- ];
512
- })
513
- : [];
514
- const multiSelect = raw.multiSelect === true;
515
- return {
516
- id: `claude-question-${index}`,
517
- prompt: compactRunnerText(raw.question, 5_000),
518
- input: options.length === 0 ? 'SHORT_TEXT' : multiSelect ? 'MULTI_SELECT' : 'SINGLE_SELECT',
519
- options,
520
- allowOther: true,
521
- multiSelect
522
- };
523
- });
524
- return questions.some((question) => question === undefined)
525
- ? []
526
- : questions;
527
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myagentroam/node",
3
- "version": "0.11.15",
3
+ "version": "0.11.16",
4
4
  "description": "MyAgentRoam Node runtime CLI.",
5
5
  "license": "Apache-2.0 AND GPL-2.0-or-later",
6
6
  "type": "module",
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "@anthropic-ai/claude-agent-sdk": "0.3.233",
31
- "@modelcontextprotocol/sdk": "1.30.0",
31
+ "@modelcontextprotocol/sdk": "1.32.0",
32
32
  "@opencode-ai/sdk": "1.18.20",
33
33
  "minimatch": "^10.2.6",
34
34
  "node-datachannel": "0.33.4",
@@ -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.11.15",
40
+ "@myagentroam/agent": "0.11.16",
41
41
  "@myagentroam/code-navigation": "0.11.0",
42
42
  "@myagentroam/marctl": "0.11.0",
43
- "@myagentroam/protocol": "0.11.15"
43
+ "@myagentroam/protocol": "0.11.16"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@types/ws": "^8.18.1"