@softerist/heuristic-mcp 2.1.47 → 3.0.0

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 (109) hide show
  1. package/.agent/workflows/code-review.md +60 -0
  2. package/.prettierrc +7 -0
  3. package/ARCHITECTURE.md +105 -170
  4. package/CONTRIBUTING.md +32 -113
  5. package/GEMINI.md +73 -0
  6. package/LICENSE +21 -21
  7. package/README.md +161 -54
  8. package/config.json +876 -75
  9. package/debug-pids.js +27 -0
  10. package/eslint.config.js +36 -0
  11. package/features/ann-config.js +37 -26
  12. package/features/clear-cache.js +28 -19
  13. package/features/find-similar-code.js +142 -66
  14. package/features/hybrid-search.js +253 -93
  15. package/features/index-codebase.js +1455 -394
  16. package/features/lifecycle.js +813 -180
  17. package/features/register.js +58 -52
  18. package/index.js +450 -306
  19. package/lib/cache-ops.js +22 -0
  20. package/lib/cache-utils.js +68 -0
  21. package/lib/cache.js +1392 -587
  22. package/lib/call-graph.js +165 -50
  23. package/lib/cli.js +154 -0
  24. package/lib/config.js +462 -121
  25. package/lib/embedding-process.js +77 -0
  26. package/lib/embedding-worker.js +545 -30
  27. package/lib/ignore-patterns.js +61 -59
  28. package/lib/json-worker.js +14 -0
  29. package/lib/json-writer.js +344 -0
  30. package/lib/logging.js +88 -0
  31. package/lib/memory-logger.js +13 -0
  32. package/lib/project-detector.js +13 -17
  33. package/lib/server-lifecycle.js +38 -0
  34. package/lib/settings-editor.js +645 -0
  35. package/lib/tokenizer.js +207 -104
  36. package/lib/utils.js +273 -198
  37. package/lib/vector-store-binary.js +592 -0
  38. package/mcp_config.example.json +13 -0
  39. package/package.json +13 -2
  40. package/scripts/clear-cache.js +6 -17
  41. package/scripts/download-model.js +14 -9
  42. package/scripts/postinstall.js +5 -5
  43. package/search-configs.js +36 -0
  44. package/test/ann-config.test.js +179 -0
  45. package/test/ann-fallback.test.js +6 -6
  46. package/test/binary-store.test.js +69 -0
  47. package/test/cache-branches.test.js +120 -0
  48. package/test/cache-errors.test.js +264 -0
  49. package/test/cache-extra.test.js +300 -0
  50. package/test/cache-helpers.test.js +205 -0
  51. package/test/cache-hnsw-failure.test.js +40 -0
  52. package/test/cache-json-worker.test.js +190 -0
  53. package/test/cache-worker.test.js +102 -0
  54. package/test/cache.test.js +443 -0
  55. package/test/call-graph.test.js +103 -4
  56. package/test/clear-cache.test.js +69 -68
  57. package/test/code-review-workflow.test.js +50 -0
  58. package/test/config.test.js +418 -0
  59. package/test/coverage-gap.test.js +497 -0
  60. package/test/coverage-maximizer.test.js +236 -0
  61. package/test/debug-analysis.js +107 -0
  62. package/test/embedding-model.test.js +173 -103
  63. package/test/embedding-worker-extra.test.js +272 -0
  64. package/test/embedding-worker.test.js +158 -0
  65. package/test/features.test.js +139 -0
  66. package/test/final-boost.test.js +271 -0
  67. package/test/final-polish.test.js +183 -0
  68. package/test/final.test.js +95 -0
  69. package/test/find-similar-code.test.js +191 -0
  70. package/test/helpers.js +92 -11
  71. package/test/helpers.test.js +46 -0
  72. package/test/hybrid-search-basic.test.js +62 -0
  73. package/test/hybrid-search-branch.test.js +202 -0
  74. package/test/hybrid-search-callgraph.test.js +229 -0
  75. package/test/hybrid-search-extra.test.js +81 -0
  76. package/test/hybrid-search.test.js +484 -71
  77. package/test/index-cli.test.js +520 -0
  78. package/test/index-codebase-batch.test.js +119 -0
  79. package/test/index-codebase-branches.test.js +585 -0
  80. package/test/index-codebase-core.test.js +1032 -0
  81. package/test/index-codebase-edge-cases.test.js +254 -0
  82. package/test/index-codebase-errors.test.js +132 -0
  83. package/test/index-codebase-gap.test.js +239 -0
  84. package/test/index-codebase-lines.test.js +151 -0
  85. package/test/index-codebase-watcher.test.js +259 -0
  86. package/test/index-codebase-zone.test.js +259 -0
  87. package/test/index-codebase.test.js +371 -69
  88. package/test/index-memory.test.js +220 -0
  89. package/test/indexer-detailed.test.js +176 -0
  90. package/test/integration.test.js +148 -92
  91. package/test/json-worker.test.js +50 -0
  92. package/test/lifecycle.test.js +541 -0
  93. package/test/master.test.js +198 -0
  94. package/test/perfection.test.js +349 -0
  95. package/test/project-detector.test.js +65 -0
  96. package/test/register.test.js +262 -0
  97. package/test/tokenizer.test.js +55 -93
  98. package/test/ultra-maximizer.test.js +116 -0
  99. package/test/utils-branches.test.js +161 -0
  100. package/test/utils-extra.test.js +116 -0
  101. package/test/utils.test.js +131 -0
  102. package/test/verify_fixes.js +76 -0
  103. package/test/worker-errors.test.js +96 -0
  104. package/test/worker-init.test.js +102 -0
  105. package/test/worker_throttling.test.js +93 -0
  106. package/tools/scripts/benchmark-search.js +95 -0
  107. package/tools/scripts/cache-stats.js +71 -0
  108. package/tools/scripts/manual-search.js +34 -0
  109. package/vitest.config.js +19 -9
package/lib/call-graph.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * Works across multiple languages without external dependencies.
6
6
  */
7
7
 
8
- import path from "path";
8
+ import path from 'path';
9
9
 
10
10
  // Language-specific patterns for function/method definitions
11
11
  const DEFINITION_PATTERNS = {
@@ -19,30 +19,30 @@ const DEFINITION_PATTERNS = {
19
19
  // method definitions: name() { or async name() {
20
20
  /^\s*(?:async\s+)?([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\([^)]*\)\s*\{/gm,
21
21
  // object method shorthand: name() { inside object
22
- /([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\([^)]*\)\s*\{/g
22
+ /([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\([^)]*\)\s*\{/g,
23
23
  ],
24
24
  python: [
25
25
  // def name():
26
26
  /def\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*\(/g,
27
27
  // class Name:
28
- /class\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*[:(]/g
28
+ /class\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*[:(]/g,
29
29
  ],
30
30
  go: [
31
31
  // func name() or func (r Receiver) name()
32
- /func\s+(?:\([^)]*\)\s+)?([a-zA-Z_][a-zA-Z0-9_]*)\s*\(/g
32
+ /func\s+(?:\([^)]*\)\s+)?([a-zA-Z_][a-zA-Z0-9_]*)\s*\(/g,
33
33
  ],
34
34
  rust: [
35
35
  // fn name()
36
36
  /fn\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*[<(]/g,
37
37
  // impl Name
38
- /impl(?:\s*<[^>]*>)?\s+([a-zA-Z_][a-zA-Z0-9_]*)/g
38
+ /impl(?:\s*<[^>]*>)?\s+([a-zA-Z_][a-zA-Z0-9_]*)/g,
39
39
  ],
40
40
  java: [
41
41
  // public void name() or private static String name()
42
42
  /(?:public|private|protected)?\s*(?:static)?\s*(?:\w+)\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*\(/g,
43
43
  // class Name
44
- /class\s+([a-zA-Z_][a-zA-Z0-9_]*)/g
45
- ]
44
+ /class\s+([a-zA-Z_][a-zA-Z0-9_]*)/g,
45
+ ],
46
46
  };
47
47
 
48
48
  // Pattern for function calls (language-agnostic, catches most cases)
@@ -51,19 +51,117 @@ const CALL_PATTERN = /\b([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\(/g;
51
51
  // Common built-ins to exclude from call detection (all lowercase for case-insensitive matching)
52
52
  const BUILTIN_EXCLUSIONS = new Set([
53
53
  // JavaScript
54
- "if", "for", "while", "switch", "catch", "function", "async", "await",
55
- "return", "throw", "new", "typeof", "instanceof", "delete", "void",
56
- "console", "require", "import", "export", "super", "this",
54
+ 'if',
55
+ 'for',
56
+ 'while',
57
+ 'switch',
58
+ 'catch',
59
+ 'function',
60
+ 'async',
61
+ 'await',
62
+ 'return',
63
+ 'throw',
64
+ 'new',
65
+ 'typeof',
66
+ 'instanceof',
67
+ 'delete',
68
+ 'void',
69
+ 'console',
70
+ 'require',
71
+ 'import',
72
+ 'export',
73
+ 'super',
74
+ 'this',
57
75
  // Common functions that aren't meaningful for call graphs
58
- "parseint", "parsefloat", "string", "number", "boolean", "array", "object",
59
- "map", "set", "promise", "error", "json", "math", "date", "regexp",
76
+ 'parseint',
77
+ 'parsefloat',
78
+ 'string',
79
+ 'number',
80
+ 'boolean',
81
+ 'array',
82
+ 'object',
83
+ 'map',
84
+ 'set',
85
+ 'promise',
86
+ 'error',
87
+ 'json',
88
+ 'math',
89
+ 'date',
90
+ 'regexp',
60
91
  // Python
61
- "def", "class", "print", "len", "range", "str", "int", "float", "list", "dict",
62
- "tuple", "bool", "type", "isinstance", "hasattr", "getattr", "setattr",
92
+ 'def',
93
+ 'class',
94
+ 'print',
95
+ 'len',
96
+ 'range',
97
+ 'str',
98
+ 'int',
99
+ 'float',
100
+ 'list',
101
+ 'dict',
102
+ 'tuple',
103
+ 'bool',
104
+ 'type',
105
+ 'isinstance',
106
+ 'hasattr',
107
+ 'getattr',
108
+ 'setattr',
63
109
  // Go
64
- "func", "make", "append", "cap", "panic", "recover",
110
+ 'func',
111
+ 'make',
112
+ 'append',
113
+ 'cap',
114
+ 'panic',
115
+ 'recover',
65
116
  // Control flow that looks like function calls
66
- "else", "try", "finally", "with", "assert", "raise", "yield"
117
+ 'else',
118
+ 'try',
119
+ 'finally',
120
+ 'with',
121
+ 'assert',
122
+ 'raise',
123
+ 'yield',
124
+ // Test frameworks
125
+ 'describe',
126
+ 'it',
127
+ 'test',
128
+ 'expect',
129
+ 'beforeeach',
130
+ 'aftereach',
131
+ 'beforeall',
132
+ 'afterall',
133
+ // Common prototypes / methods (too noisy)
134
+ 'match',
135
+ 'exec',
136
+ 'replace',
137
+ 'split',
138
+ 'join',
139
+ 'slice',
140
+ 'splice',
141
+ 'push',
142
+ 'pop',
143
+ 'shift',
144
+ 'unshift',
145
+ 'includes',
146
+ 'indexof',
147
+ 'foreach',
148
+ 'filter',
149
+ 'reduce',
150
+ 'find',
151
+ 'some',
152
+ 'every',
153
+ 'sort',
154
+ 'keys',
155
+ 'values',
156
+ 'entries',
157
+ 'from',
158
+ 'then',
159
+ 'catch',
160
+ 'finally',
161
+ 'all',
162
+ 'race',
163
+ 'resolve',
164
+ 'reject',
67
165
  ]);
68
166
 
69
167
  /**
@@ -72,29 +170,34 @@ const BUILTIN_EXCLUSIONS = new Set([
72
170
  function detectLanguage(file) {
73
171
  const ext = path.extname(file).toLowerCase();
74
172
  const langMap = {
75
- ".js": "javascript",
76
- ".jsx": "javascript",
77
- ".ts": "javascript",
78
- ".tsx": "javascript",
79
- ".mjs": "javascript",
80
- ".cjs": "javascript",
81
- ".py": "python",
82
- ".pyw": "python",
83
- ".go": "go",
84
- ".rs": "rust",
85
- ".java": "java",
86
- ".kt": "java",
87
- ".scala": "java"
173
+ '.js': 'javascript',
174
+ '.jsx': 'javascript',
175
+ '.ts': 'javascript',
176
+ '.tsx': 'javascript',
177
+ '.mjs': 'javascript',
178
+ '.cjs': 'javascript',
179
+ '.py': 'python',
180
+ '.pyw': 'python',
181
+ '.go': 'go',
182
+ '.rs': 'rust',
183
+ '.java': 'java',
184
+ '.kt': 'java',
185
+ '.scala': 'java',
88
186
  };
89
- return langMap[ext] || "javascript"; // Default to JS patterns
187
+ if (langMap[ext]) {
188
+ return langMap[ext];
189
+ } else {
190
+ return 'javascript'; // Default to JS patterns
191
+ }
90
192
  }
91
193
 
92
194
  /**
93
195
  * Extract function/class definitions from content
196
+ * Exported for testing; treat as internal helper.
94
197
  */
95
198
  export function extractDefinitions(content, file) {
96
199
  const language = detectLanguage(file);
97
- const patterns = DEFINITION_PATTERNS[language] || DEFINITION_PATTERNS.javascript;
200
+ const patterns = DEFINITION_PATTERNS[language];
98
201
  const definitions = new Set();
99
202
 
100
203
  for (const pattern of patterns) {
@@ -114,6 +217,7 @@ export function extractDefinitions(content, file) {
114
217
 
115
218
  /**
116
219
  * Extract function calls from content
220
+ * Exported for testing; treat as internal helper.
117
221
  */
118
222
  export function extractCalls(content, file) {
119
223
  const calls = new Set();
@@ -140,23 +244,23 @@ function removeStringsAndComments(content, file) {
140
244
  const ext = path.extname(file).toLowerCase();
141
245
 
142
246
  // Remove single-line comments
143
- let cleaned = content.replace(/\/\/.*$/gm, "");
247
+ let cleaned = content.replace(/\/\/.*$/gm, '');
144
248
 
145
249
  // Remove multi-line comments
146
- cleaned = cleaned.replace(/\/\*[\s\S]*?\*\//g, "");
250
+ cleaned = cleaned.replace(/\/\*[\s\S]*?\*\//g, '');
147
251
 
148
252
  // Remove Python comments
149
- if (ext === ".py" || ext === ".pyw") {
150
- cleaned = cleaned.replace(/#.*$/gm, "");
253
+ if (ext === '.py' || ext === '.pyw') {
254
+ cleaned = cleaned.replace(/#.*$/gm, '');
151
255
  // Remove triple-quoted strings (docstrings)
152
- cleaned = cleaned.replace(/"""[\s\S]*?"""/g, "");
153
- cleaned = cleaned.replace(/'''[\s\S]*?'''/g, "");
256
+ cleaned = cleaned.replace(/"""[\s\S]*?"""/g, '');
257
+ cleaned = cleaned.replace(/'''[\s\S]*?'''/g, '');
154
258
  }
155
259
 
156
260
  // Remove string literals (simplified - handles most cases)
157
261
  cleaned = cleaned.replace(/"(?:[^"\\]|\\.)*"/g, '""');
158
262
  cleaned = cleaned.replace(/'(?:[^'\\]|\\.)*'/g, "''");
159
- cleaned = cleaned.replace(/`(?:[^`\\]|\\.)*`/g, "``");
263
+ cleaned = cleaned.replace(/`(?:[^`\\]|\\.)*`/g, '``');
160
264
 
161
265
  return cleaned;
162
266
  }
@@ -170,11 +274,11 @@ export function extractCallData(content, file) {
170
274
 
171
275
  // Remove self-references (calls to functions defined in same file)
172
276
  const definitionSet = new Set(definitions);
173
- const externalCalls = calls.filter(c => !definitionSet.has(c));
277
+ const externalCalls = calls.filter((c) => !definitionSet.has(c));
174
278
 
175
279
  return {
176
280
  definitions,
177
- calls: externalCalls
281
+ calls: externalCalls,
178
282
  };
179
283
  }
180
284
 
@@ -182,7 +286,7 @@ export function extractCallData(content, file) {
182
286
  * Build a call graph from file data
183
287
  */
184
288
  export function buildCallGraph(fileCallData) {
185
- const defines = new Map(); // symbol -> files that define it
289
+ const defines = new Map(); // symbol -> files that define it
186
290
  const calledBy = new Map(); // symbol -> files that call it
187
291
  const fileCalls = new Map(); // file -> symbols it calls
188
292
 
@@ -253,21 +357,32 @@ export function getRelatedFiles(callGraph, symbols, maxHops = 1) {
253
357
  return related;
254
358
  }
255
359
 
360
+ // Patterns for extracting symbols from content
361
+ const SYMBOL_PATTERNS = [
362
+ // function name()
363
+ /function\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g,
364
+ // class Name
365
+ /class\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g,
366
+ // const/let/var name = ...
367
+ /(?:const|let|var)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=/g,
368
+ // Python def/class
369
+ /def\s+([a-zA-Z_][a-zA-Z0-9_]*)/g,
370
+ /class\s+([a-zA-Z_][a-zA-Z0-9_]*)/g,
371
+ // Go func
372
+ /func\s+([a-zA-Z_][a-zA-Z0-9_]*)/g,
373
+ // Rust fn
374
+ /fn\s+([a-zA-Z_][a-zA-Z0-9_]*)/g,
375
+ // Java/C# methods (simplified)
376
+ /(?:public|private|protected|static)\s+\w+\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*\(/g
377
+ ];
378
+
256
379
  /**
257
380
  * Extract symbols (function/class names) from search results
258
381
  */
259
382
  export function extractSymbolsFromContent(content) {
260
383
  const symbols = new Set();
261
384
 
262
- // Look for function/class definitions in the content
263
- const patterns = [
264
- /function\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g,
265
- /class\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g,
266
- /def\s+([a-zA-Z_][a-zA-Z0-9_]*)/g,
267
- /(?:const|let|var)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=/g
268
- ];
269
-
270
- for (const pattern of patterns) {
385
+ for (const pattern of SYMBOL_PATTERNS) {
271
386
  pattern.lastIndex = 0;
272
387
  let match;
273
388
  while ((match = pattern.exec(content)) !== null) {
package/lib/cli.js ADDED
@@ -0,0 +1,154 @@
1
+ export const DEFAULT_LOG_TAIL_LINES = 200;
2
+
3
+ export function printHelp(defaultTailLines = DEFAULT_LOG_TAIL_LINES) {
4
+ console.info(`Heuristic MCP Server
5
+
6
+ Usage:
7
+ heuristic-mcp [options]
8
+
9
+ Options:
10
+ --status Show server and cache status
11
+ --fix With --status, remove stale cache directories
12
+ --clear-cache Remove cache for current workspace (and stale global caches)
13
+ --logs Tail server logs (defaults to last 200 lines, follows)
14
+ --tail <lines> Lines to show with --logs (default: ${defaultTailLines})
15
+ --no-follow Do not follow log output with --logs
16
+ --start Ensure IDE config is registered (does not start server)
17
+ --stop Stop running server instances
18
+ --register [ide] Register MCP server with IDE (antigravity|cursor|"Claude Desktop")
19
+ --workspace <path> Workspace path (used by IDE launch / log viewer)
20
+ --version, -v Show version
21
+ --help, -h Show this help
22
+ `);
23
+ }
24
+
25
+ export function parseWorkspaceDir(args) {
26
+ const workspaceIndex = args.findIndex((arg) => arg.startsWith('--workspace'));
27
+ if (workspaceIndex === -1) return null;
28
+
29
+ const arg = args[workspaceIndex];
30
+ let rawWorkspace = null;
31
+
32
+ if (arg.includes('=')) {
33
+ rawWorkspace = arg.split('=')[1];
34
+ } else if (workspaceIndex + 1 < args.length) {
35
+ rawWorkspace = args[workspaceIndex + 1];
36
+ }
37
+
38
+ // Check if IDE variable wasn't expanded (contains ${})
39
+ if (rawWorkspace && rawWorkspace.includes('${')) {
40
+ console.error(
41
+ `[Server] IDE variable not expanded: ${rawWorkspace}, falling back to auto-detected workspace`
42
+ );
43
+ return null;
44
+ }
45
+
46
+ return rawWorkspace || null;
47
+ }
48
+
49
+ export function collectUnknownFlags(rawArgs, knownFlags, flagsWithValue) {
50
+ const unknownFlags = [];
51
+ for (let i = 0; i < rawArgs.length; i += 1) {
52
+ const arg = rawArgs[i];
53
+ if (flagsWithValue.has(arg)) {
54
+ if (arg.includes('=')) continue;
55
+ const next = rawArgs[i + 1];
56
+ if (next && !next.startsWith('-')) {
57
+ i += 1;
58
+ }
59
+ continue;
60
+ }
61
+ if (arg.startsWith('-') && !knownFlags.has(arg) && !arg.startsWith('--workspace=')) {
62
+ unknownFlags.push(arg);
63
+ }
64
+ }
65
+ return unknownFlags;
66
+ }
67
+
68
+ export function parseArgs(argv = process.argv) {
69
+ const args = argv.slice(2);
70
+ const rawArgs = [...args];
71
+
72
+ const wantsVersion = args.includes('--version') || args.includes('-v');
73
+ const wantsHelp = args.includes('--help') || args.includes('-h');
74
+ const wantsStatus = args.includes('--status');
75
+ const wantsClearCache = args.includes('--clear-cache');
76
+ const wantsLogs = args.includes('--logs');
77
+ const wantsStart = args.includes('--start');
78
+ const wantsStop = args.includes('--stop');
79
+ const wantsRegister = args.includes('--register');
80
+ const wantsFix = args.includes('--fix');
81
+ const wantsNoFollow = args.includes('--no-follow');
82
+
83
+ const isServerMode = !(
84
+ wantsStatus ||
85
+ wantsClearCache ||
86
+ wantsLogs ||
87
+ wantsStart ||
88
+ wantsStop ||
89
+ wantsRegister ||
90
+ wantsHelp ||
91
+ wantsVersion
92
+ );
93
+
94
+ const workspaceDir = parseWorkspaceDir(args);
95
+
96
+ let tailLines = DEFAULT_LOG_TAIL_LINES;
97
+ if (wantsLogs) {
98
+ const tailIndex = args.indexOf('--tail');
99
+ if (tailIndex !== -1 && args[tailIndex + 1]) {
100
+ const parsed = parseInt(args[tailIndex + 1], 10);
101
+ if (!isNaN(parsed) && parsed > 0) {
102
+ tailLines = parsed;
103
+ }
104
+ }
105
+ }
106
+
107
+ let registerFilter = null;
108
+ if (wantsRegister) {
109
+ const filterIndex = args.indexOf('--register');
110
+ registerFilter =
111
+ args[filterIndex + 1] && !args[filterIndex + 1].startsWith('-')
112
+ ? args[filterIndex + 1]
113
+ : null;
114
+ }
115
+
116
+ const knownFlags = new Set([
117
+ '--status',
118
+ '--fix',
119
+ '--clear-cache',
120
+ '--logs',
121
+ '--tail',
122
+ '--no-follow',
123
+ '--start',
124
+ '--stop',
125
+ '--register',
126
+ '--workspace',
127
+ '--version',
128
+ '-v',
129
+ '--help',
130
+ '-h',
131
+ ]);
132
+ const flagsWithValue = new Set(['--tail', '--workspace', '--register']);
133
+ const unknownFlags = collectUnknownFlags(rawArgs, knownFlags, flagsWithValue);
134
+
135
+ return {
136
+ args,
137
+ rawArgs,
138
+ isServerMode,
139
+ workspaceDir,
140
+ wantsVersion,
141
+ wantsHelp,
142
+ wantsStatus,
143
+ wantsClearCache,
144
+ wantsLogs,
145
+ wantsStart,
146
+ wantsStop,
147
+ wantsRegister,
148
+ wantsFix,
149
+ wantsNoFollow,
150
+ tailLines,
151
+ registerFilter,
152
+ unknownFlags,
153
+ };
154
+ }