@myagentroam/node 0.9.96 → 0.9.98

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 (35) hide show
  1. package/dist/codex-app-server.js +4 -15
  2. package/dist/connector.js +0 -18
  3. package/dist/ctags-binary.js +10 -0
  4. package/dist/runner/claude/managed-run-controller.js +1 -1
  5. package/dist/runner/claude-code-runner.js +14 -48
  6. package/dist/runner/codex/managed-run-controller.js +1 -1
  7. package/dist/runner/codex-runner.js +6 -13
  8. package/dist/runner/mar-agent-runner.js +3 -10
  9. package/dist/runner/opencode-runner.js +7 -19
  10. package/dist/service/code-navigation/c-family-path-specifier-resolver.js +40 -0
  11. package/dist/service/code-navigation/csharp-path-specifier-resolver.js +32 -0
  12. package/dist/service/code-navigation/ctags-index-storage.js +290 -0
  13. package/dist/service/code-navigation/ctags-query.js +140 -0
  14. package/dist/service/code-navigation/ecmascript-path-specifier-resolver.js +85 -0
  15. package/dist/service/code-navigation/file-reference-parser.js +28 -0
  16. package/dist/service/code-navigation/go-path-specifier-resolver.js +31 -0
  17. package/dist/service/code-navigation/jvm-path-specifier-resolver.js +28 -0
  18. package/dist/service/code-navigation/markdown-path-specifier-resolver.js +80 -0
  19. package/dist/service/code-navigation/navigation-resolution-definition.js +1 -0
  20. package/dist/service/code-navigation/navigation-resolution-registry.js +36 -0
  21. package/dist/service/code-navigation/navigation-target-validator.js +121 -0
  22. package/dist/service/code-navigation/path-specifier-resolver.js +6 -0
  23. package/dist/service/code-navigation/python-path-specifier-resolver.js +41 -0
  24. package/dist/service/code-navigation/rust-path-specifier-resolver.js +31 -0
  25. package/dist/service/code-navigation/stylesheet-path-specifier-resolver.js +55 -0
  26. package/dist/service/conversation-history-service.js +1 -1
  27. package/dist/service/external-session-resume-service.js +5 -22
  28. package/dist/service/node-control-message-service.js +1 -1
  29. package/dist/service/node-upgrade-coordinator.js +0 -1
  30. package/dist/service/session-catalog-service.js +2 -27
  31. package/dist/service/session-command-service.js +3 -3
  32. package/dist/service/session-message-service.js +3 -15
  33. package/dist/service/session-presentation-service.js +0 -1
  34. package/dist/service/workspace-code-navigation-service.js +80 -694
  35. package/package.json +4 -3
@@ -9,22 +9,11 @@ import { createInterface } from 'node:readline';
9
9
  import { minimalRunnerEnvironment, platformCliInvocation, runRunnerProbe } from './operational.js';
10
10
  const REQUEST_TIMEOUT_MS = 15_000;
11
11
  /**
12
- * Maps the facts that the Node can actually establish to user-visible
13
- * controls. In particular, seeing an external thread never implies that it
14
- * is safe to write to its active turn.
12
+ * Maps the facts that the Node can establish to the unified session controls.
13
+ * Native-session activation is validated atomically with the first message.
15
14
  */
16
15
  export function codexSessionControl(input) {
17
- if (!input.available)
18
- return { level: 'UNAVAILABLE', capabilities: [] };
19
- if (input.sharedControl) {
20
- return {
21
- level: 'SHARED_CONTROL',
22
- capabilities: ['history.read', 'events.live', 'turn.start', 'turn.steer', 'turn.interrupt']
23
- };
24
- }
25
- if (input.nativeThreadId !== null && input.nativeControl === 'EXTERNAL') {
26
- return { level: 'OBSERVE_ONLY', capabilities: ['history.read'] };
27
- }
16
+ void [input.available, input.nativeThreadId, input.nativeControl];
28
17
  if (input.activeTurn) {
29
18
  return {
30
19
  level: 'MANAGED',
@@ -32,7 +21,7 @@ export function codexSessionControl(input) {
32
21
  };
33
22
  }
34
23
  return {
35
- level: 'RESUMABLE',
24
+ level: 'MANAGED',
36
25
  capabilities: ['history.read', 'turn.start']
37
26
  };
38
27
  }
package/dist/connector.js CHANGED
@@ -635,7 +635,6 @@ export class NodeConnector {
635
635
  runners: this.runners,
636
636
  capabilities: () => this.capabilities,
637
637
  hasManagedActiveRun: (session) => hasManagedActiveRun(this.runtime, session),
638
- externalActivity: (sessionId) => this.sessionState.externalActivity.get(sessionId),
639
638
  projectionForNative: (session) => this.nativeSessionProjectionService.projectionForNative(session)
640
639
  });
641
640
  this.nativeSessionProjectionService = new NativeSessionProjectionService({
@@ -851,28 +850,12 @@ export class NodeConnector {
851
850
  configuration: (session) => this.nativeSessionProjectionService.resumedConfiguration(session),
852
851
  workspacePath: (workspaceId) => this.database?.getWorkspace(workspaceId)?.path,
853
852
  rememberNative: (nativeSessionId, sessionId) => this.managedRunnerSessions.remember(nativeSessionId, sessionId),
854
- stage: (session) => {
855
- const configuration = this.nativeSessionProjectionService.resumedConfiguration(session);
856
- return this.runtime.createAgentSession({
857
- workspaceId: session.workspaceId,
858
- runner: session.runner,
859
- externalSessionId: session.externalSessionId ?? session.id,
860
- nativeControl: 'EXTERNAL',
861
- cwd: session.cwd,
862
- model: configuration.model,
863
- effort: configuration.effort,
864
- access: configuration.access,
865
- ...(session.runnerTitle === null ? {} : { title: session.runnerTitle }),
866
- ...(session.customTitle === null ? {} : { customTitle: session.customTitle })
867
- });
868
- },
869
853
  resolve: (sessionId) => this.nativeSessionProjectionService.resolve(sessionId)
870
854
  });
871
855
  this.sessionCommandService = new SessionCommandService({
872
856
  runtime: this.runtime,
873
857
  runners: this.runners,
874
858
  projection: this.nativeSessionProjectionService,
875
- resume: this.externalSessionResumeService,
876
859
  profiles: () => this.runnerService.profiles(),
877
860
  present: (session) => this.sessionPresentationService.present(session),
878
861
  resumeQueueAfterCommandRun: (sessionId) => this.workspaceQueueWorkbenchService.resumeAfterCommandRun(sessionId),
@@ -1018,7 +1001,6 @@ export class NodeConnector {
1018
1001
  runtime: this.runtime,
1019
1002
  runners: this.runners,
1020
1003
  projection: this.nativeSessionProjectionService,
1021
- resume: this.externalSessionResumeService,
1022
1004
  cachedNative: () => [...this.sessionState.directNative.values()],
1023
1005
  cachedWorkspace: (workspaceId) => this.workspaceCoordinator.cachedSessions(workspaceId),
1024
1006
  discoverWorkspace: (workspaceId) => this.nativeSessionProjectionService.discoverWorkspace(workspaceId),
@@ -1,3 +1,4 @@
1
+ import { chmod } from 'node:fs/promises';
1
2
  import { dirname, resolve } from 'node:path';
2
3
  import { fileURLToPath } from 'node:url';
3
4
  export const BUNDLED_CTAGS_VERSION = '6.2.1';
@@ -16,3 +17,12 @@ export function bundledCtagsPath(platform = process.platform, architecture = pro
16
17
  throw new Error('CTAGS_PLATFORM_UNSUPPORTED');
17
18
  return resolve(bundledCtagsDirectory(packageRoot), ...target);
18
19
  }
20
+ /**
21
+ * Restores the execute bit when an installation mechanism lost the bundled
22
+ * Linux binary's archive mode. Explicit Ctags overrides are never modified.
23
+ */
24
+ export async function repairBundledCtagsExecutable(platform = process.platform, architecture = process.arch, packageRoot) {
25
+ if (platform !== 'linux')
26
+ return;
27
+ await chmod(bundledCtagsPath(platform, architecture, packageRoot), 0o755);
28
+ }
@@ -115,7 +115,7 @@ export class ClaudeManagedRunController {
115
115
  return;
116
116
  if (typeof payload.externalSessionId === 'string' &&
117
117
  !this.runner.execution.managedNativeIds.has(payload.externalSessionId)) {
118
- this.host.emit(runId, 'run.rejected', { code: 'EXTERNAL_SESSION_OBSERVE_ONLY' }, 'FAILED');
118
+ this.host.emit(runId, 'run.rejected', { code: 'SESSION_ACTIVATION_REQUIRED' }, 'FAILED');
119
119
  return;
120
120
  }
121
121
  this.host.active.add(runId);
@@ -147,62 +147,28 @@ export class ClaudeCodeRunner extends AbstractRunner {
147
147
  : this.client.forkSession(session.externalSessionId, session.cwd, boundary, title);
148
148
  }
149
149
  presentSession(session, capabilities, context) {
150
- if (capabilities.claudeCode.available && session.nativeControl === 'MAR_MANAGED') {
151
- const runtimeCapabilities = [
152
- 'history.read',
153
- 'events.live',
154
- 'turn.start',
155
- 'turn.queue',
156
- 'turn.interrupt',
157
- 'run.cancel',
158
- 'approval.respond',
159
- 'session.rename',
160
- 'session.remove',
161
- 'session.pin',
162
- ...(session.externalSessionId === null ? [] : ['session.rewind'])
163
- ];
164
- return {
165
- activity: context.managedActive ? 'MANAGED_ACTIVE' : 'IDLE',
166
- control: {
167
- level: 'MANAGED',
168
- capabilities: ['history.read', 'events.live', 'turn.start', 'turn.interrupt']
169
- },
170
- commandStates: context.commandStates,
171
- runtime: { level: 'MANAGED', capabilities: runtimeCapabilities, reasonCode: null }
172
- };
173
- }
174
- if (capabilities.claudeCode.available && session.externalSessionId !== null) {
175
- const runtimeCapabilities = [
176
- 'history.read',
177
- 'turn.start',
178
- 'session.rename',
179
- 'session.remove',
180
- 'session.pin',
181
- 'session.rewind'
182
- ];
183
- return {
184
- activity: 'IDLE',
185
- control: { level: 'RESUMABLE', capabilities: ['history.read', 'turn.start'] },
186
- commandStates: context.commandStates,
187
- runtime: { level: 'RESUMABLE', capabilities: runtimeCapabilities, reasonCode: null }
188
- };
189
- }
150
+ void capabilities;
190
151
  const runtimeCapabilities = [
191
152
  'history.read',
192
153
  'events.live',
154
+ 'turn.start',
155
+ 'turn.queue',
156
+ 'turn.interrupt',
157
+ 'run.cancel',
158
+ 'approval.respond',
193
159
  'session.rename',
194
160
  'session.remove',
195
- 'session.pin'
161
+ 'session.pin',
162
+ ...(session.externalSessionId === null ? [] : ['session.rewind'])
196
163
  ];
197
164
  return {
198
- activity: 'UNAVAILABLE',
199
- control: { level: 'OBSERVE_ONLY', capabilities: ['history.read', 'events.live'] },
165
+ activity: context.managedActive ? 'MANAGED_ACTIVE' : 'IDLE',
166
+ control: {
167
+ level: 'MANAGED',
168
+ capabilities: ['history.read', 'events.live', 'turn.start', 'turn.interrupt']
169
+ },
200
170
  commandStates: context.commandStates,
201
- runtime: {
202
- level: 'OBSERVE_ONLY',
203
- capabilities: runtimeCapabilities,
204
- reasonCode: 'EXTERNAL_SESSION_OBSERVE_ONLY'
205
- }
171
+ runtime: { level: 'MANAGED', capabilities: runtimeCapabilities, reasonCode: null }
206
172
  };
207
173
  }
208
174
  prepareMessageInput(input, collaborationMode) {
@@ -357,7 +357,7 @@ export class CodexManagedRunController {
357
357
  }
358
358
  if (typeof payload.externalSessionId === 'string' &&
359
359
  (session === undefined || session.nativeControl !== 'MAR_MANAGED')) {
360
- this.host.emit(runId, 'run.rejected', { code: 'EXTERNAL_THREAD_OBSERVE_ONLY' }, 'FAILED');
360
+ this.host.emit(runId, 'run.rejected', { code: 'SESSION_ACTIVATION_REQUIRED' }, 'FAILED');
361
361
  return;
362
362
  }
363
363
  try {
@@ -309,10 +309,7 @@ export class CodexRunner extends AbstractRunner {
309
309
  return { activity: 'IDLE', session: context.create(external) };
310
310
  }
311
311
  catch {
312
- return {
313
- activity: 'UNAVAILABLE',
314
- failureCode: 'RUNNER_RESUME_FAILED'
315
- };
312
+ return { failureCode: 'RUNNER_RESUME_FAILED' };
316
313
  }
317
314
  }
318
315
  async discoverSessions(context, workspace) {
@@ -391,13 +388,7 @@ export class CodexRunner extends AbstractRunner {
391
388
  nativeControl: session.nativeControl,
392
389
  activeTurn
393
390
  });
394
- const activity = !capabilities.codex.available
395
- ? 'UNAVAILABLE'
396
- : context.managedActive
397
- ? 'MANAGED_ACTIVE'
398
- : session.nativeControl === 'EXTERNAL'
399
- ? (context.externalActivity ?? 'IDLE')
400
- : 'IDLE';
391
+ const activity = context.managedActive ? 'MANAGED_ACTIVE' : 'IDLE';
401
392
  return {
402
393
  control,
403
394
  activity,
@@ -406,13 +397,15 @@ export class CodexRunner extends AbstractRunner {
406
397
  level: control.level,
407
398
  capabilities: [
408
399
  ...control.capabilities,
409
- ...(control.level === 'MANAGED' ? ['turn.queue', 'run.cancel', 'approval.respond'] : []),
400
+ 'turn.queue',
401
+ 'run.cancel',
402
+ 'approval.respond',
410
403
  'session.rename',
411
404
  'session.remove',
412
405
  'session.pin',
413
406
  ...(session.externalSessionId === null ? [] : ['session.rewind'])
414
407
  ],
415
- reasonCode: control.level === 'UNAVAILABLE' ? 'RUNNER_UNAVAILABLE' : null
408
+ reasonCode: null
416
409
  }
417
410
  };
418
411
  }
@@ -170,14 +170,7 @@ export class MarAgentRunner extends AbstractRunner {
170
170
  };
171
171
  }
172
172
  presentSession(session, capabilities, context) {
173
- if (!this.available(capabilities))
174
- return {
175
- activity: 'UNAVAILABLE',
176
- control: { level: 'UNAVAILABLE', capabilities: [] },
177
- runtime: { level: 'UNAVAILABLE', capabilities: [], reasonCode: 'RUNNER_UNAVAILABLE' },
178
- commandStates: context.commandStates
179
- };
180
- const managed = session.nativeControl === 'MAR_MANAGED';
173
+ void capabilities;
181
174
  const activity = context.managedActive ? 'MANAGED_ACTIVE' : 'IDLE';
182
175
  const runtimeCapabilities = [
183
176
  'history.read',
@@ -195,11 +188,11 @@ export class MarAgentRunner extends AbstractRunner {
195
188
  return {
196
189
  activity,
197
190
  control: {
198
- level: managed ? 'MANAGED' : 'RESUMABLE',
191
+ level: 'MANAGED',
199
192
  capabilities: ['history.read', 'events.live', 'turn.start', 'turn.interrupt']
200
193
  },
201
194
  runtime: {
202
- level: managed ? 'MANAGED' : 'RESUMABLE',
195
+ level: 'MANAGED',
203
196
  capabilities: runtimeCapabilities,
204
197
  reasonCode: null
205
198
  },
@@ -206,7 +206,7 @@ export class OpenCodeRunner extends AbstractRunner {
206
206
  const projection = context.projectionFor(external);
207
207
  const session = projection === undefined ? context.create(external) : context.promote(projection.id);
208
208
  return session === undefined
209
- ? { activity: 'UNAVAILABLE', failureCode: 'RUNNER_RESUME_FAILED' }
209
+ ? { failureCode: 'RUNNER_RESUME_FAILED' }
210
210
  : { activity: 'IDLE', session: context.ensureConfiguration(session) };
211
211
  }
212
212
  async readOfficialConversation(session, input, managedTurn) {
@@ -227,18 +227,8 @@ export class OpenCodeRunner extends AbstractRunner {
227
227
  return this.managedTurns.get(nativeTurnId);
228
228
  }
229
229
  presentSession(session, capabilities, context) {
230
- const available = capabilities.openCode?.available === true;
231
- const managed = session.nativeControl === 'MAR_MANAGED';
232
- const activity = context.managedActive
233
- ? 'MANAGED_ACTIVE'
234
- : (context.externalActivity ?? (available ? 'IDLE' : 'UNAVAILABLE'));
235
- if (!available)
236
- return {
237
- activity: 'UNAVAILABLE',
238
- control: { level: 'UNAVAILABLE', capabilities: [] },
239
- runtime: { level: 'UNAVAILABLE', capabilities: [], reasonCode: 'RUNNER_UNAVAILABLE' },
240
- commandStates: context.commandStates
241
- };
230
+ void capabilities;
231
+ const activity = context.managedActive ? 'MANAGED_ACTIVE' : 'IDLE';
242
232
  const runtimeCapabilities = [
243
233
  'history.read',
244
234
  'events.live',
@@ -256,15 +246,13 @@ export class OpenCodeRunner extends AbstractRunner {
256
246
  return {
257
247
  activity,
258
248
  control: {
259
- level: managed ? 'MANAGED' : activity === 'IDLE' ? 'RESUMABLE' : 'OBSERVE_ONLY',
260
- capabilities: managed || activity === 'IDLE'
261
- ? ['history.read', 'events.live', 'turn.start', 'turn.interrupt']
262
- : ['history.read', 'events.live']
249
+ level: 'MANAGED',
250
+ capabilities: ['history.read', 'events.live', 'turn.start', 'turn.interrupt']
263
251
  },
264
252
  runtime: {
265
- level: managed ? 'MANAGED' : activity === 'IDLE' ? 'RESUMABLE' : 'OBSERVE_ONLY',
253
+ level: 'MANAGED',
266
254
  capabilities: runtimeCapabilities,
267
- reasonCode: activity === 'EXTERNAL_ACTIVE' ? 'EXTERNAL_SESSION_OBSERVE_ONLY' : null
255
+ reasonCode: null
268
256
  },
269
257
  commandStates: context.commandStates
270
258
  };
@@ -0,0 +1,40 @@
1
+ import { posix } from 'node:path';
2
+ import { matchesPathSuffix } from './path-specifier-resolver.js';
3
+ function accepts(value) {
4
+ return /^(?:\.\.?\/)?(?:[A-Za-z0-9_$+.-]+\/)*[A-Za-z0-9_$+.-]+$/u.test(value);
5
+ }
6
+ function matches(path, currentPath, specifier) {
7
+ return candidates(currentPath, specifier).some((candidate) => path === candidate || matchesPathSuffix(path, candidate));
8
+ }
9
+ function score(path, currentPath, specifier) {
10
+ const resolvedCandidates = candidates(currentPath, specifier);
11
+ const exact = resolvedCandidates.indexOf(path);
12
+ if (exact >= 0)
13
+ return exact;
14
+ const suffix = resolvedCandidates.findIndex((candidate) => matchesPathSuffix(path, candidate));
15
+ return suffix >= 0 ? resolvedCandidates.length + suffix + path.length : Number.MAX_SAFE_INTEGER;
16
+ }
17
+ function candidates(currentPath, specifier) {
18
+ const relative = posix.normalize(posix.join(posix.dirname(currentPath), specifier));
19
+ if (relative.startsWith('../') || relative === '..' || relative === specifier)
20
+ return [specifier];
21
+ return [relative.replace(/^\.\//u, ''), specifier];
22
+ }
23
+ export const cFamilyPathSpecifierResolver = {
24
+ id: 'c-family.path-specifier',
25
+ accepts,
26
+ directCandidates: candidates,
27
+ matches,
28
+ score
29
+ };
30
+ function createCFamilyNavigationResolutionDefinition(languageId) {
31
+ return {
32
+ languageId,
33
+ resolver: { ...cFamilyPathSpecifierResolver, id: `${languageId}.path-specifier` }
34
+ };
35
+ }
36
+ export const cNavigationResolutionDefinition = createCFamilyNavigationResolutionDefinition('c');
37
+ export const cppNavigationResolutionDefinition = createCFamilyNavigationResolutionDefinition('cpp');
38
+ export const objectiveCNavigationResolutionDefinition = createCFamilyNavigationResolutionDefinition('objective-c');
39
+ export const objectiveCppNavigationResolutionDefinition = createCFamilyNavigationResolutionDefinition('objective-cpp');
40
+ export const cFamilyNavigationResolutionDefinition = createCFamilyNavigationResolutionDefinition('c-family');
@@ -0,0 +1,32 @@
1
+ import { matchesPathSuffix } from './path-specifier-resolver.js';
2
+ function accepts(value) {
3
+ return /^[\p{L}_\p{Nl}][\p{L}\p{Nl}\p{Nd}\p{Pc}\p{Mn}\p{Mc}]*(?:\.[\p{L}_\p{Nl}][\p{L}\p{Nl}\p{Nd}\p{Pc}\p{Mn}\p{Mc}]*)*$/u.test(value);
4
+ }
5
+ function matches(path, _currentPath, specifier) {
6
+ if (!path.endsWith('.cs'))
7
+ return false;
8
+ return namespaceSuffixes(specifier).some((suffix) => matchesPathSuffix(path, `${suffix}.cs`) ||
9
+ path.startsWith(`${suffix}/`) ||
10
+ path.includes(`/${suffix}/`));
11
+ }
12
+ function score(path, _currentPath, specifier) {
13
+ const suffixes = namespaceSuffixes(specifier);
14
+ const index = suffixes.findIndex((suffix) => matchesPathSuffix(path, `${suffix}.cs`) ||
15
+ path.startsWith(`${suffix}/`) ||
16
+ path.includes(`/${suffix}/`));
17
+ return index < 0 ? Number.MAX_SAFE_INTEGER : index * 10_000 + path.length;
18
+ }
19
+ function namespaceSuffixes(specifier) {
20
+ const segments = specifier.split('.');
21
+ return segments.map((_, index) => segments.slice(index).join('/'));
22
+ }
23
+ export const csharpPathSpecifierResolver = {
24
+ id: 'csharp.path-specifier',
25
+ accepts,
26
+ matches,
27
+ score
28
+ };
29
+ export const csharpNavigationResolutionDefinition = {
30
+ languageId: 'csharp',
31
+ resolver: csharpPathSpecifierResolver
32
+ };