@myagentroam/node 0.9.3 → 0.9.5

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 (66) hide show
  1. package/dist/claude-agent-sdk.d.ts +1 -0
  2. package/dist/claude-agent-sdk.js +9 -0
  3. package/dist/codex-app-server.d.ts +25 -0
  4. package/dist/codex-app-server.js +104 -7
  5. package/dist/connector.d.ts +1 -0
  6. package/dist/connector.js +21 -12
  7. package/dist/database.d.ts +2 -0
  8. package/dist/native-session-history.d.ts +3 -2
  9. package/dist/native-session-history.js +199 -30
  10. package/dist/opencode-server.d.ts +1 -0
  11. package/dist/opencode-server.js +1 -0
  12. package/dist/runner/abstract-runner.d.ts +11 -2
  13. package/dist/runner/abstract-runner.js +4 -0
  14. package/dist/runner/claude/managed-run-controller.js +3 -0
  15. package/dist/runner/claude-code-runner.d.ts +2 -1
  16. package/dist/runner/claude-code-runner.js +4 -0
  17. package/dist/runner/codex/managed-run-controller.d.ts +9 -0
  18. package/dist/runner/codex/managed-run-controller.js +63 -17
  19. package/dist/runner/codex-runner.d.ts +3 -1
  20. package/dist/runner/codex-runner.js +23 -2
  21. package/dist/runner/opencode/managed-run-controller.js +4 -0
  22. package/dist/runner/opencode-runner.d.ts +10 -3
  23. package/dist/runner/opencode-runner.js +87 -14
  24. package/dist/runner/runner-registry.js +16 -1
  25. package/dist/runtime-command-detector.js +1 -6
  26. package/dist/runtime-state.d.ts +2 -0
  27. package/dist/runtime-state.js +12 -7
  28. package/dist/service/conversation-history-service.d.ts +10 -1
  29. package/dist/service/conversation-history-service.js +272 -42
  30. package/dist/service/conversation-segment-service.js +7 -1
  31. package/dist/service/external-session-resume-service.d.ts +2 -0
  32. package/dist/service/external-session-resume-service.js +45 -34
  33. package/dist/service/native-session-projection-service.d.ts +1 -0
  34. package/dist/service/native-session-projection-service.js +4 -0
  35. package/dist/service/native-session-watch-service.d.ts +26 -2
  36. package/dist/service/native-session-watch-service.js +258 -42
  37. package/dist/service/node-request-service.js +2 -1
  38. package/dist/service/run-event-service.js +16 -5
  39. package/dist/service/run-workbench-service.d.ts +2 -4
  40. package/dist/service/run-workbench-service.js +2 -7
  41. package/dist/service/session-command-service.js +1 -1
  42. package/dist/service/session-identity-service.d.ts +1 -1
  43. package/dist/service/session-identity-service.js +1 -1
  44. package/dist/service/session-lifecycle-service.js +7 -12
  45. package/dist/service/session-message-service.d.ts +1 -1
  46. package/dist/service/session-message-service.js +104 -83
  47. package/dist/service/skill-directory-service.d.ts +1 -0
  48. package/dist/service/skill-directory-service.js +40 -6
  49. package/dist/service/workspace-change-service.js +1 -1
  50. package/dist/service/workspace-domain-state.d.ts +3 -0
  51. package/dist/service/workspace-domain-state.js +1 -0
  52. package/dist/service/workspace-file-service.d.ts +1 -0
  53. package/dist/service/workspace-file-service.js +14 -1
  54. package/dist/service/workspace-queue-workbench-service.d.ts +29 -2
  55. package/dist/service/workspace-queue-workbench-service.js +73 -8
  56. package/dist/service/workspace-watch-service.d.ts +7 -2
  57. package/dist/service/workspace-watch-service.js +32 -6
  58. package/dist/service/workspace-workbench-service.d.ts +14 -0
  59. package/dist/service/workspace-workbench-service.js +215 -16
  60. package/dist/util/personal-instructions.d.ts +2 -0
  61. package/dist/util/personal-instructions.js +31 -0
  62. package/dist/util/runner-native-session-parsers.d.ts +3 -1
  63. package/dist/util/runner-native-session-parsers.js +35 -17
  64. package/dist/workspace.d.ts +14 -8
  65. package/dist/workspace.js +98 -50
  66. package/package.json +2 -2
@@ -23,6 +23,7 @@ export interface ClaudeQueryInput {
23
23
  readonly onChannelReply?: (content: string) => void;
24
24
  readonly environment?: Readonly<Record<string, string>>;
25
25
  readonly mcpServers?: NonNullable<Options['mcpServers']>;
26
+ readonly personalInstructions?: string;
26
27
  }
27
28
  /** Image blocks accepted by the Claude Agent SDK message input. */
28
29
  export interface ClaudeImageAttachment {
@@ -64,6 +64,15 @@ export class ClaudeAgentSdkAdapter {
64
64
  // This is the SDK's documented API-side public summary mode. We never
65
65
  // enable or forward raw thinking deltas to the Workbench.
66
66
  settings: { showThinkingSummaries: true },
67
+ ...(input.personalInstructions === undefined
68
+ ? {}
69
+ : {
70
+ systemPrompt: {
71
+ type: 'preset',
72
+ preset: 'claude_code',
73
+ append: input.personalInstructions
74
+ }
75
+ }),
67
76
  abortController,
68
77
  canUseTool: input.onPermission,
69
78
  ...(input.mcpServers !== undefined || channelEnabled
@@ -50,7 +50,20 @@ export interface CodexRunConfiguration {
50
50
  readonly serviceTier?: 'fast';
51
51
  readonly collaborationMode?: 'default' | 'plan';
52
52
  readonly mcpServers?: unknown;
53
+ readonly developerInstructions?: string;
53
54
  }
55
+ interface CodexRpcErrorPayload {
56
+ readonly code?: unknown;
57
+ readonly message?: unknown;
58
+ readonly data?: unknown;
59
+ }
60
+ export declare class CodexAppServerRpcError extends Error {
61
+ readonly code: unknown;
62
+ readonly rpcMessage: string;
63
+ readonly data: unknown;
64
+ constructor(payload: CodexRpcErrorPayload);
65
+ }
66
+ export declare function isCodexRolloutMissingError(error: unknown): boolean;
54
67
  /** Public App Server turn inputs supported by the Workbench Composer. */
55
68
  export type CodexComposerInput = {
56
69
  readonly type: 'text';
@@ -71,15 +84,26 @@ export declare class CodexAppServerClient {
71
84
  private socketPath;
72
85
  private nextId;
73
86
  private readonly pending;
87
+ private readonly pendingDrainWaiters;
74
88
  private readonly notifications;
75
89
  private environment;
90
+ private starting;
91
+ private restarting;
92
+ private lifecycleRevision;
76
93
  constructor(options?: CodexAppServerOptions);
77
94
  configureEnvironment(environment: Readonly<Record<string, string>>): void;
78
95
  clearEnvironment(): void;
79
96
  start(): Promise<void>;
97
+ restart(): Promise<void>;
98
+ private startManaged;
99
+ private restartManaged;
80
100
  stop(): void;
101
+ private stopManaged;
81
102
  onNotification(listener: (notification: JsonRpcNotification) => void): () => void;
82
103
  request(method: string, params: unknown): Promise<unknown>;
104
+ private requestDirect;
105
+ private waitForPendingRequests;
106
+ private resolvePendingDrain;
83
107
  notify(method: string, params: unknown): void;
84
108
  respond(requestId: string | number, result: unknown): void;
85
109
  startThread(cwd: string, configuration?: CodexRunConfiguration): Promise<unknown>;
@@ -106,3 +130,4 @@ export declare class CodexAppServerClient {
106
130
  export declare function probeCodex(command?: string): CodexProbe;
107
131
  export declare function probeCodexAsync(command?: string): Promise<CodexProbe>;
108
132
  export declare function isSupportedCodexVersion(version: string): boolean;
133
+ export {};
@@ -36,6 +36,25 @@ export function codexSessionControl(input) {
36
36
  capabilities: ['history.read', 'turn.start']
37
37
  };
38
38
  }
39
+ export class CodexAppServerRpcError extends Error {
40
+ code;
41
+ rpcMessage;
42
+ data;
43
+ constructor(payload) {
44
+ const rpcMessage = typeof payload.message === 'string' ? payload.message : 'Codex App Server request failed';
45
+ super(`CODEX_APP_SERVER_RPC_ERROR:${JSON.stringify(payload)}`);
46
+ this.name = 'CodexAppServerRpcError';
47
+ this.code = payload.code;
48
+ this.rpcMessage = rpcMessage;
49
+ this.data = payload.data;
50
+ }
51
+ }
52
+ export function isCodexRolloutMissingError(error) {
53
+ return (error instanceof CodexAppServerRpcError &&
54
+ error.code === -32600 &&
55
+ (/^no rollout found for thread id\b/i.test(error.rpcMessage) ||
56
+ /^thread not loaded:\s*/i.test(error.rpcMessage)));
57
+ }
39
58
  /**
40
59
  * Local JSON-RPC client for a Node-supervised Codex App Server. Linux uses a
41
60
  * private Unix socket by default; Windows uses stdio. Neither is exposed to
@@ -48,8 +67,12 @@ export class CodexAppServerClient {
48
67
  socketPath;
49
68
  nextId = 1;
50
69
  pending = new Map();
70
+ pendingDrainWaiters = new Set();
51
71
  notifications = new Set();
52
72
  environment = {};
73
+ starting;
74
+ restarting;
75
+ lifecycleRevision = 0;
53
76
  constructor(options = {}) {
54
77
  this.options = options;
55
78
  }
@@ -63,9 +86,35 @@ export class CodexAppServerClient {
63
86
  throw new Error('CODEX_APP_SERVER_ALREADY_STARTED');
64
87
  this.environment = {};
65
88
  }
66
- async start() {
89
+ start() {
90
+ if (this.restarting !== undefined)
91
+ return this.restarting;
92
+ if (this.starting !== undefined)
93
+ return this.starting;
67
94
  if (this.child !== undefined)
68
- return;
95
+ return Promise.resolve();
96
+ const starting = this.startManaged();
97
+ this.starting = starting;
98
+ const clearStarting = () => {
99
+ if (this.starting === starting)
100
+ this.starting = undefined;
101
+ };
102
+ void starting.then(clearStarting, clearStarting);
103
+ return starting;
104
+ }
105
+ restart() {
106
+ if (this.restarting !== undefined)
107
+ return this.restarting;
108
+ const restarting = this.restartManaged(this.lifecycleRevision);
109
+ this.restarting = restarting;
110
+ const clearRestarting = () => {
111
+ if (this.restarting === restarting)
112
+ this.restarting = undefined;
113
+ };
114
+ void restarting.then(clearRestarting, clearRestarting);
115
+ return restarting;
116
+ }
117
+ async startManaged() {
69
118
  const command = this.options.command ?? 'codex';
70
119
  const mode = this.transportMode();
71
120
  this.socketPath =
@@ -105,18 +154,39 @@ export class CodexAppServerClient {
105
154
  this.transport = socket ?? stdioTransport(child);
106
155
  const lines = createInterface({ input: socket ?? child.stdout });
107
156
  lines.on('line', (line) => this.handleLine(line));
108
- child.once('error', (error) => this.failAll(new Error(`CODEX_APP_SERVER_START_FAILED:${error.message}`)));
157
+ const managedChild = child;
158
+ child.once('error', (error) => {
159
+ if (this.child !== managedChild)
160
+ return;
161
+ this.failAll(new Error(`CODEX_APP_SERVER_START_FAILED:${error.message}`));
162
+ });
109
163
  child.once('exit', () => {
164
+ if (this.child !== managedChild)
165
+ return;
110
166
  this.child = undefined;
111
167
  this.failAll(new Error('CODEX_APP_SERVER_EXITED'));
112
168
  });
113
- await this.request('initialize', {
169
+ await this.requestDirect('initialize', {
114
170
  clientInfo: { name: 'codex_vscode', title: 'MyAgentRoam', version: '0.1.4' },
115
171
  capabilities: { experimentalApi: true }
116
172
  });
117
173
  this.notify('initialized', {});
118
174
  }
175
+ async restartManaged(lifecycleRevision) {
176
+ await Promise.resolve();
177
+ if (this.starting !== undefined)
178
+ await this.starting;
179
+ await this.waitForPendingRequests();
180
+ if (this.lifecycleRevision !== lifecycleRevision)
181
+ throw new Error('CODEX_APP_SERVER_STOPPED');
182
+ this.stopManaged();
183
+ await this.startManaged();
184
+ }
119
185
  stop() {
186
+ this.lifecycleRevision += 1;
187
+ this.stopManaged();
188
+ }
189
+ stopManaged() {
120
190
  this.transport?.destroy();
121
191
  this.transport = undefined;
122
192
  this.child?.kill();
@@ -131,6 +201,13 @@ export class CodexAppServerClient {
131
201
  return () => this.notifications.delete(listener);
132
202
  }
133
203
  async request(method, params) {
204
+ if (this.restarting !== undefined)
205
+ await this.restarting;
206
+ else if (this.starting !== undefined)
207
+ await this.starting;
208
+ return this.requestDirect(method, params);
209
+ }
210
+ requestDirect(method, params) {
134
211
  const transport = this.transport;
135
212
  if (transport === undefined || !transport.writable)
136
213
  throw new Error('CODEX_APP_SERVER_UNAVAILABLE');
@@ -139,6 +216,7 @@ export class CodexAppServerClient {
139
216
  const result = new Promise((resolve, reject) => {
140
217
  const timer = setTimeout(() => {
141
218
  this.pending.delete(id);
219
+ this.resolvePendingDrain();
142
220
  reject(new Error('CODEX_APP_SERVER_TIMEOUT'));
143
221
  }, timeoutMs);
144
222
  this.pending.set(id, { resolve, reject, timer });
@@ -146,6 +224,18 @@ export class CodexAppServerClient {
146
224
  transport.write(`${JSON.stringify({ method, id, params })}\n`);
147
225
  return result;
148
226
  }
227
+ waitForPendingRequests() {
228
+ if (this.pending.size === 0)
229
+ return Promise.resolve();
230
+ return new Promise((resolve) => this.pendingDrainWaiters.add(resolve));
231
+ }
232
+ resolvePendingDrain() {
233
+ if (this.pending.size !== 0)
234
+ return;
235
+ for (const resolve of this.pendingDrainWaiters)
236
+ resolve();
237
+ this.pendingDrainWaiters.clear();
238
+ }
149
239
  notify(method, params) {
150
240
  const transport = this.transport;
151
241
  if (transport === undefined || !transport.writable)
@@ -233,8 +323,9 @@ export class CodexAppServerClient {
233
323
  return;
234
324
  clearTimeout(pending.timer);
235
325
  this.pending.delete(message.id);
326
+ this.resolvePendingDrain();
236
327
  if (message.error !== undefined) {
237
- pending.reject(new Error(`CODEX_APP_SERVER_RPC_ERROR:${JSON.stringify(message.error)}`));
328
+ pending.reject(new CodexAppServerRpcError(isRecord(message.error) ? message.error : { message: String(message.error) }));
238
329
  }
239
330
  else {
240
331
  pending.resolve(message.result);
@@ -252,6 +343,7 @@ export class CodexAppServerClient {
252
343
  pending.reject(error);
253
344
  this.pending.delete(id);
254
345
  }
346
+ this.resolvePendingDrain();
255
347
  }
256
348
  transportMode() {
257
349
  const requested = this.options.transport ?? 'auto';
@@ -266,6 +358,9 @@ export class CodexAppServerClient {
266
358
  function codexThreadConfiguration(cwd, configuration) {
267
359
  return {
268
360
  ...modelOption(configuration.model),
361
+ ...(configuration.developerInstructions === undefined
362
+ ? {}
363
+ : { developerInstructions: configuration.developerInstructions }),
269
364
  ...(configuration.mcpServers === undefined
270
365
  ? {}
271
366
  : { config: { mcp_servers: configuration.mcpServers } }),
@@ -284,8 +379,7 @@ function codexTurnConfiguration(cwd, configuration) {
284
379
  mode: configuration.collaborationMode,
285
380
  settings: {
286
381
  model: configuration.model ?? 'gpt-5.6-sol',
287
- reasoningEffort: configuration.effort ?? null,
288
- developerInstructions: null
382
+ reasoningEffort: configuration.effort ?? null
289
383
  }
290
384
  }
291
385
  }),
@@ -371,6 +465,9 @@ function defaultSpawn(command, args, options) {
371
465
  ...(options.env === undefined ? {} : { env: options.env })
372
466
  });
373
467
  }
468
+ function isRecord(value) {
469
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
470
+ }
374
471
  function stdioTransport(child) {
375
472
  return {
376
473
  get writable() {
@@ -3,6 +3,7 @@ export type { NodeConnectorOptions } from './connector/node-connector-options.js
3
3
  export { nodeConnectEndpoint, validatedCapabilities } from './runner/codex/conversation-parser.js';
4
4
  export declare function nextReconnectDelay(attempt: number): number;
5
5
  export declare class NodeConnector {
6
+ private readonly nodeGeneration;
6
7
  private readonly controlChannel;
7
8
  private readonly controlMessages;
8
9
  private readonly nodeRequests;
package/dist/connector.js CHANGED
@@ -43,7 +43,7 @@ import { SessionQueryService } from './service/session-query-service.js';
43
43
  import { WorkspaceQueueWorkbenchService } from './service/workspace-queue-workbench-service.js';
44
44
  import { SessionIdentityService } from './service/session-identity-service.js';
45
45
  import { NativeSessionProjectionService } from './service/native-session-projection-service.js';
46
- import { ConversationHistoryService, hasManagedActiveRun } from './service/conversation-history-service.js';
46
+ import { ConversationHistoryService, convergeConversationWatchPage, hasManagedActiveRun } from './service/conversation-history-service.js';
47
47
  import { ConversationSegmentService, conversationSegmentIdentityForItem, conversationSegments } from './service/conversation-segment-service.js';
48
48
  import { RunnerInteractionService } from './service/runner-interaction-service.js';
49
49
  import { SessionLifecycleService } from './service/session-lifecycle-service.js';
@@ -86,6 +86,7 @@ function upgradeMetadata(metadata, status) {
86
86
  return next;
87
87
  }
88
88
  export class NodeConnector {
89
+ nodeGeneration = crypto.randomUUID().replace(/-/g, '');
89
90
  controlChannel;
90
91
  controlMessages;
91
92
  nodeRequests;
@@ -153,7 +154,7 @@ export class NodeConnector {
153
154
  discover: (workspaceId) => this.discoverWorkspaceSessions(workspaceId),
154
155
  listPage: (workspaceId) => this.executeNodeOperation('session.list', { workspaceId, limit: 20 }),
155
156
  active: (workspaceId) => this.workspaceWatchService.topicActive(workspaceId, 'sessions'),
156
- emitRevision: (workspaceId, revision) => this.emitWorkbenchEvent('workspace', { workspaceId, topic: 'sessions', revision }),
157
+ emitRevision: (workspaceId) => void this.workspaceWorkbenchService?.refreshTopic(workspaceId, 'sessions'),
157
158
  onPending: (workspaceId, waitMs) => nodeLog('native.session.discovery.pending', {
158
159
  nodeId: this.config?.nodeId,
159
160
  workspaceId,
@@ -192,14 +193,22 @@ export class NodeConnector {
192
193
  });
193
194
  nativeSessionWatchService = new NativeSessionWatchService({
194
195
  resolve: async (sessionId) => this.runtime.getAgentSession(sessionId) ??
195
- this.nativeSessionProjectionService.resolve(sessionId),
196
+ this.nativeSessionProjectionService.resolveCurrent(sessionId),
196
197
  managedActive: (session) => hasManagedActiveRun(this.runtime, session),
198
+ suspended: (sessionId) => this.externalSessionResumeService.transitioning(sessionId),
197
199
  refreshActivity: (session) => this.conversationHistoryService.refreshExternalActivity(session),
198
200
  present: (session) => this.sessionPresentationService.present(session),
199
201
  readPage: (session, limit) => this.conversationHistoryService.read(session, { limit }),
202
+ convergePage: convergeConversationWatchPage,
200
203
  projectInitialPage: (session, page, _unit, limit) => this.conversationSegmentService.projectInitial(session, page, limit),
201
204
  emitSession: (session) => this.emitWorkbenchEvent('session', { session }),
202
- emitTurn: (turn) => this.emitConversationTurn(turn)
205
+ emitPage: (session, page) => this.emitWorkbenchEvent('conversation', {
206
+ sessionId: session.id,
207
+ snapshot: this.conversationSegmentService.projectInitial(session, page, 10)
208
+ }),
209
+ nodeId: () => this.config?.nodeId ?? 'runtime-node',
210
+ nodeGeneration: () => this.nodeGeneration,
211
+ emitWatchEvent: (payload) => this.send('watch.event', payload)
203
212
  });
204
213
  constructor(options = {}) {
205
214
  this.config = options.config;
@@ -392,10 +401,8 @@ export class NodeConnector {
392
401
  readImage: async (runId, imageIndex) => this.runAttachmentService.read(runId, imageIndex) ??
393
402
  (await this.runAttachmentService.readNative(runId, imageIndex)),
394
403
  respondUserInput: (runId, requestId, answers) => this.runnerInteractionService.respondUserInput(runId, requestId, answers),
395
- deleteQueuedStart: (runId) => this.workspaceQueueWorkbenchService.remove(runId),
396
- clearImages: (runId) => this.runAttachmentService.clear(runId),
397
- cleanupAttachments: (runId) => this.runAttachmentService.cleanup(runId),
398
- emitQueue: (workspaceId, sessionId) => this.runEventBridge.emitQueue(workspaceId, sessionId),
404
+ cancelQueued: (runId) => this.workspaceQueueWorkbenchService.cancelQueued(runId),
405
+ pauseQueue: (sessionId) => this.workspaceQueueWorkbenchService.pauseForInterrupt(sessionId),
399
406
  emitRun: (runId, eventType, payload, status) => this.runEventBridge.emitRun(runId, eventType, payload, status),
400
407
  control: (operation, payload) => this.controlMessages.handle(JSON.stringify(createEnvelope(operation, payload))),
401
408
  markInterrupted: (runId) => this.runState.interruptRequested.add(runId)
@@ -443,7 +450,7 @@ export class NodeConnector {
443
450
  migrateRunnerState: (previousId, nextId) => this.runEventBridge.migrateRunnerSessionIdentity(previousId, nextId),
444
451
  emitSession: (session) => this.emitWorkbenchEvent('session', { session }),
445
452
  emitRun: (run) => this.emitWorkbenchEvent('run', { run }),
446
- emitQueue: (workspaceId, sessionId) => this.runEventBridge.emitQueue(workspaceId, sessionId),
453
+ emitQueue: (sessionId) => this.workspaceQueueWorkbenchService.publish(sessionId),
447
454
  emitTurn: (turn) => this.emitConversationTurn(turn)
448
455
  });
449
456
  this.sessionLifecycleService = new SessionLifecycleService({
@@ -497,7 +504,6 @@ export class NodeConnector {
497
504
  emitSession: (session) => this.emitWorkbenchEvent('session', {
498
505
  session: this.sessionPresentationService.present(session)
499
506
  }),
500
- emitQueue: (workspaceId, sessionId) => this.runEventBridge.emitQueue(workspaceId, sessionId),
501
507
  channelToken: (sessionId) => {
502
508
  const session = this.runtime.getAgentSession(sessionId);
503
509
  return session === undefined
@@ -646,7 +652,7 @@ export class NodeConnector {
646
652
  watches: this.workspaceWatchService,
647
653
  sessions: this.workspaceSessionService,
648
654
  changes: this.workspaceChangeService,
649
- emit: (workspaceId, topic, revision) => this.emitWorkbenchEvent('workspace', { workspaceId, topic, revision }),
655
+ emit: (workspaceId, topic) => void this.workspaceWorkbenchService?.refreshTopic(workspaceId, topic),
650
656
  send: (type, payload, replyTo) => this.send(type, payload, replyTo)
651
657
  });
652
658
  this.runEventBridge = new NodeRunEventBridge({
@@ -707,7 +713,10 @@ export class NodeConnector {
707
713
  uploads: this.workspaceUploadService,
708
714
  changes: this.workspaceChangeService,
709
715
  listSessions: (workspaceId) => this.executeNodeOperation('session.list', { workspaceId, limit: 20 }),
710
- invalidate: (workspaceId) => this.workspaceCoordinator.invalidate(workspaceId)
716
+ invalidate: (workspaceId) => this.workspaceCoordinator.invalidate(workspaceId),
717
+ nodeId: () => this.config?.nodeId ?? 'runtime-node',
718
+ nodeGeneration: () => this.nodeGeneration,
719
+ emitWatchEvent: (payload) => this.send('watch.event', payload)
711
720
  });
712
721
  this.operationRouter.registerAll(this.runnerService.operations());
713
722
  this.operationRouter.registerAll(this.terminalService.operations());
@@ -67,6 +67,8 @@ export interface NodeAgentRun {
67
67
  readonly recoveryState: RunRecoveryState;
68
68
  readonly version: number;
69
69
  readonly clientMessageId: string;
70
+ /** Server-authenticated user that submitted this Run. Internal lifecycle metadata only. */
71
+ readonly initiatedByUserId?: number;
70
72
  readonly createdAt: number;
71
73
  readonly updatedAt: number;
72
74
  }
@@ -78,8 +78,9 @@ export interface NativeClaudeContextUsage {
78
78
  export declare function discoverNativeSessions(runner: RunnerName, workspacePath: string): Promise<readonly NativeSessionHistory[]>;
79
79
  /**
80
80
  * Reads every supported transcript header before applying a Workspace filter.
81
- * The caller owns in-process caching; a fixed file-count cutoff would silently
82
- * hide older sessions from a project with a large global history.
81
+ * A short Runner-level snapshot is shared across Workspaces and refreshes only
82
+ * files whose size or modification time changed. A fixed file-count cutoff
83
+ * would silently hide older sessions from a project with a large global history.
83
84
  */
84
85
  export declare function discoverAllNativeSessions(runner: RunnerName): Promise<readonly NativeSessionHistory[]>;
85
86
  /** Reads one already-discovered external session again to follow appended JSONL records. */