@myagentroam/node 0.9.98 → 0.9.99

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.
@@ -1,4 +1,5 @@
1
1
  import { posix } from 'node:path';
2
+ import { trailingPathCandidateScore } from './path-specifier-resolver.js';
2
3
  const importExtensionMappings = [
3
4
  { importExtension: '.js', sourceExtensions: ['.ts', '.tsx'] },
4
5
  { importExtension: '.jsx', sourceExtensions: ['.tsx'] },
@@ -8,11 +9,12 @@ const importExtensionMappings = [
8
9
  const extensionlessSourceExtensions = ['.ts', '.tsx', '.js', '.jsx'];
9
10
  function accepts(value) {
10
11
  return (/^(?:\.\.?\/)[A-Za-z0-9_./$-]+$/u.test(value) ||
12
+ /^@\/[A-Za-z0-9_./$-]+$/u.test(value) ||
11
13
  /^(?:@?[A-Za-z0-9_$-]+)(?:\/[A-Za-z0-9_.$-]+)+$/u.test(value));
12
14
  }
13
15
  function matches(path, currentPath, specifier) {
14
16
  if (!specifier.startsWith('.'))
15
- return sourceFileStem(path) === sourceFileStem(specifier);
17
+ return unresolvedSpecifierScore(path, specifier) !== undefined;
16
18
  const resolved = resolveRelative(currentPath, specifier);
17
19
  return (resolved !== undefined &&
18
20
  candidates(resolved).some((candidate) => path === candidate ||
@@ -23,7 +25,7 @@ function matches(path, currentPath, specifier) {
23
25
  }
24
26
  function score(path, currentPath, specifier) {
25
27
  if (!specifier.startsWith('.'))
26
- return path.length;
28
+ return unresolvedSpecifierScore(path, specifier) ?? Number.MAX_SAFE_INTEGER;
27
29
  const resolved = resolveRelative(currentPath, specifier);
28
30
  if (resolved === undefined)
29
31
  return Number.MAX_SAFE_INTEGER;
@@ -72,6 +74,19 @@ function sourceFileStem(path) {
72
74
  const name = path.slice(path.lastIndexOf('/') + 1);
73
75
  return name.replace(/(?:\.d)?\.[^.]+$/u, '');
74
76
  }
77
+ function unresolvedSpecifierScore(path, specifier) {
78
+ const normalizedSpecifier = specifier.startsWith('@/') ? specifier.slice(2) : specifier;
79
+ return trailingPathCandidateScore(path, unresolvedCandidates(normalizedSpecifier));
80
+ }
81
+ function unresolvedCandidates(specifier) {
82
+ return candidates(specifier).flatMap((candidate) => [
83
+ candidate,
84
+ `${candidate}/index.ts`,
85
+ `${candidate}/index.tsx`,
86
+ `${candidate}/index.js`,
87
+ `${candidate}/index.jsx`
88
+ ]);
89
+ }
75
90
  export const ecmascriptPathSpecifierResolver = {
76
91
  id: 'ecmascript.path-specifier',
77
92
  accepts,
@@ -4,3 +4,23 @@ export function matchesPathSuffix(path, suffix) {
4
4
  export function shortestPathScore(path) {
5
5
  return path.length;
6
6
  }
7
+ export function trailingPathCandidateScore(path, candidates) {
8
+ let best;
9
+ for (const [candidateIndex, candidate] of candidates.entries()) {
10
+ const pathSegments = path.split('/');
11
+ const candidateSegments = candidate.split('/');
12
+ let matchedSegments = 0;
13
+ while (matchedSegments < pathSegments.length &&
14
+ matchedSegments < candidateSegments.length &&
15
+ pathSegments[pathSegments.length - matchedSegments - 1] ===
16
+ candidateSegments[candidateSegments.length - matchedSegments - 1])
17
+ matchedSegments += 1;
18
+ if (matchedSegments === 0)
19
+ continue;
20
+ const unmatchedSegments = candidateSegments.length - matchedSegments;
21
+ const leadingPathSegments = pathSegments.length - matchedSegments;
22
+ const candidateScore = unmatchedSegments * 10_000 + candidateIndex * 100 + leadingPathSegments;
23
+ best = best === undefined ? candidateScore : Math.min(best, candidateScore);
24
+ }
25
+ return best;
26
+ }
@@ -1,15 +1,21 @@
1
1
  import { posix } from 'node:path';
2
+ import { trailingPathCandidateScore } from './path-specifier-resolver.js';
2
3
  function accepts(value) {
3
4
  return /^(?:\.\.?\/)?[A-Za-z0-9_./$+@ -]+$/u.test(value);
4
5
  }
5
6
  function createResolver(languageId, extensions, partials = false) {
6
7
  const candidates = (currentPath, specifier) => pathCandidates(currentPath, specifier, extensions, partials);
8
+ const aliasCandidates = (specifier) => pathCandidates('', specifier.slice(2), extensions, partials);
7
9
  return {
8
10
  id: `${languageId}.path-specifier`,
9
11
  accepts,
10
- directCandidates: candidates,
11
- matches: (path, currentPath, specifier) => candidates(currentPath, specifier).includes(path),
12
+ directCandidates: (currentPath, specifier) => specifier.startsWith('@/') ? [] : candidates(currentPath, specifier),
13
+ matches: (path, currentPath, specifier) => specifier.startsWith('@/')
14
+ ? trailingPathCandidateScore(path, aliasCandidates(specifier)) !== undefined
15
+ : candidates(currentPath, specifier).includes(path),
12
16
  score: (path, currentPath, specifier) => {
17
+ if (specifier.startsWith('@/'))
18
+ return (trailingPathCandidateScore(path, aliasCandidates(specifier)) ?? Number.MAX_SAFE_INTEGER);
13
19
  const index = candidates(currentPath, specifier).indexOf(path);
14
20
  return index >= 0 ? index : Number.MAX_SAFE_INTEGER;
15
21
  }
@@ -3,6 +3,7 @@ import { constants } from 'node:fs';
3
3
  import { access, open, realpath, rename, rm, stat, writeFile } from 'node:fs/promises';
4
4
  import { homedir } from 'node:os';
5
5
  import { relative, resolve, sep } from 'node:path';
6
+ import { isNavigationSymbol } from '@myagentroam/code-navigation';
6
7
  import { supportsSymbolNavigationPath } from '@myagentroam/code-navigation/symbol-navigation';
7
8
  import { workspaceFileReferenceSchema } from '@myagentroam/protocol';
8
9
  import { bundledCtagsPath, BUNDLED_CTAGS_VERSION, repairBundledCtagsExecutable } from '../ctags-binary.js';
@@ -95,7 +96,7 @@ export class WorkspaceCodeNavigationService {
95
96
  path.length > 4096 ||
96
97
  (typeof symbol === 'string' && reference !== undefined) ||
97
98
  (typeof symbol !== 'string' && reference === undefined) ||
98
- (typeof symbol === 'string' && !isSymbol(symbol)) ||
99
+ (typeof symbol === 'string' && !isNavigationSymbol(path, symbol)) ||
99
100
  (reference !== undefined && !reference.success))
100
101
  throw new Error('SYMBOL_DEFINITION_INVALID');
101
102
  if (reference !== undefined) {
@@ -595,9 +596,6 @@ function emptyDefinitionResult(input) {
595
596
  function isCtagsSourcePath(path) {
596
597
  return supportsSymbolNavigationPath(path);
597
598
  }
598
- function isSymbol(value) {
599
- return value.length > 0 && value.length <= 512 && /^[\p{L}_$][\p{L}\p{N}_$]*$/u.test(value);
600
- }
601
599
  function buildFailure(error) {
602
600
  return error instanceof Error && error.message === 'SYMBOL_INDEX_LIMIT_EXCEEDED'
603
601
  ? 'SYMBOL_INDEX_LIMIT_EXCEEDED'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myagentroam/node",
3
- "version": "0.9.98",
3
+ "version": "0.9.99",
4
4
  "description": "MyAgentRoam Node runtime CLI.",
5
5
  "license": "Apache-2.0 AND GPL-2.0-or-later",
6
6
  "type": "module",
@@ -30,9 +30,9 @@
30
30
  "npm": "11.12.1",
31
31
  "ws": "^8.21.3",
32
32
  "zod": "4.4.3",
33
- "@myagentroam/agent": "0.9.98",
34
- "@myagentroam/protocol": "0.9.98",
35
- "@myagentroam/code-navigation": "0.9.98"
33
+ "@myagentroam/agent": "0.9.99",
34
+ "@myagentroam/code-navigation": "0.9.99",
35
+ "@myagentroam/protocol": "0.9.99"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/ws": "^8.18.1"