@octocodeai/octocode-engine 16.5.1 → 16.6.2
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.
- package/README.md +153 -235
- package/dist/lsp/client.d.ts +6 -0
- package/dist/lsp/client.js +31 -0
- package/dist/lsp/config.d.ts +29 -1
- package/dist/lsp/config.js +156 -1
- package/dist/lsp/ideContext.d.ts +18 -0
- package/dist/lsp/ideContext.js +29 -0
- package/dist/lsp/index.d.ts +8 -3
- package/dist/lsp/index.js +7 -2
- package/dist/lsp/manager.d.ts +11 -0
- package/dist/lsp/manager.js +75 -13
- package/dist/lsp/native.d.ts +5 -0
- package/dist/lsp/platform.d.ts +20 -0
- package/dist/lsp/platform.js +64 -0
- package/dist/lsp/serverDiscovery.d.ts +63 -0
- package/dist/lsp/serverDiscovery.js +226 -0
- package/dist/lsp/serverManifest.d.ts +70 -0
- package/dist/lsp/serverManifest.js +78 -0
- package/dist/lsp/serverManifestData.d.ts +2 -0
- package/dist/lsp/serverManifestData.js +33 -0
- package/dist/lsp/serverProvisioner.d.ts +19 -0
- package/dist/lsp/serverProvisioner.js +253 -0
- package/dist/lsp/types.d.ts +7 -0
- package/dist/lsp/workspaceRoot.d.ts +1 -1
- package/dist/lsp/workspaceRoot.js +3 -1
- package/dist/security/commandValidator.js +10 -10
- package/dist/security/discoveryFilter.js +7 -3
- package/dist/security/filePatterns.js +6 -0
- package/dist/security/ignoredPathFilter.js +5 -0
- package/dist/security/mask.js +5 -22
- package/dist/security/maskUtils.d.ts +6 -0
- package/dist/security/maskUtils.js +22 -0
- package/dist/security/native.js +5 -22
- package/dist/security/pathPatterns.js +5 -0
- package/dist/security/pathValidator.js +21 -18
- package/dist/security/withSecurityValidation.d.ts +0 -3
- package/dist/security/withSecurityValidation.js +3 -21
- package/index.cjs +32 -2
- package/index.d.ts +113 -0
- package/index.js +5 -0
- package/package.json +49 -8
package/index.cjs
CHANGED
|
@@ -75,13 +75,38 @@ function loadNativeBinding() {
|
|
|
75
75
|
join(__dirname, '..', '..', 'runtime', 'engine', `${binaryName}.${key}.node`),
|
|
76
76
|
]
|
|
77
77
|
|
|
78
|
+
const loadErrors = []
|
|
78
79
|
for (const candidate of candidates) {
|
|
79
80
|
if (existsSync(candidate)) {
|
|
80
|
-
|
|
81
|
+
try {
|
|
82
|
+
return require(candidate)
|
|
83
|
+
} catch (err) {
|
|
84
|
+
// The .node file exists but the host refused to load it — most often a
|
|
85
|
+
// hardened/sandboxed runtime (e.g. an editor/app-embedded Node) that
|
|
86
|
+
// blocks native addons, or an ABI/arch mismatch. Distinguish this from
|
|
87
|
+
// "binary missing" so callers don't report a generic tool failure.
|
|
88
|
+
loadErrors.push(`${candidate}: ${err && err.message ? err.message : err}`)
|
|
89
|
+
}
|
|
81
90
|
}
|
|
82
91
|
}
|
|
83
92
|
|
|
84
|
-
|
|
93
|
+
try {
|
|
94
|
+
return require(`${packageName}-${key}`)
|
|
95
|
+
} catch (err) {
|
|
96
|
+
loadErrors.push(`${packageName}-${key}: ${err && err.message ? err.message : err}`)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const detail = loadErrors.length
|
|
100
|
+
? `\nNative load attempts:\n - ${loadErrors.join('\n - ')}`
|
|
101
|
+
: `\nNo native binary found for ${key} (looked in ${candidates.length} locations and the ${packageName}-${key} package).`
|
|
102
|
+
const error = new Error(
|
|
103
|
+
`@octocodeai/octocode-engine: could not load the native ${binaryName} addon for ${key}.` +
|
|
104
|
+
detail +
|
|
105
|
+
`\nIf a .node file exists above but failed to load, the current Node runtime is likely sandboxed and rejects ` +
|
|
106
|
+
`native addons (e.g. an editor/app-embedded Node). Re-run with system Node (\`which node\`).`
|
|
107
|
+
)
|
|
108
|
+
error.code = 'OCTOCODE_ENGINE_NATIVE_LOAD_FAILED'
|
|
109
|
+
throw error
|
|
85
110
|
}
|
|
86
111
|
|
|
87
112
|
const nativeBinding = loadNativeBinding()
|
|
@@ -90,6 +115,11 @@ nativeBinding.MINIFY_CONFIG = nativeBinding.getMINIFY_CONFIG()
|
|
|
90
115
|
nativeBinding.SUPPORTED_SIGNATURE_EXTENSIONS = Object.freeze(
|
|
91
116
|
nativeBinding.getSupportedSignatureExtensions().sort()
|
|
92
117
|
)
|
|
118
|
+
nativeBinding.SUPPORTED_GRAPH_FACT_EXTENSIONS = Object.freeze(
|
|
119
|
+
typeof nativeBinding.getSupportedGraphFactExtensions === 'function'
|
|
120
|
+
? nativeBinding.getSupportedGraphFactExtensions().sort()
|
|
121
|
+
: []
|
|
122
|
+
)
|
|
93
123
|
nativeBinding.SUPPORTED_STRUCTURAL_EXTENSIONS = Object.freeze(
|
|
94
124
|
nativeBinding.getSupportedStructuralExtensions().sort()
|
|
95
125
|
)
|
package/index.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export declare class NativeLspClient {
|
|
|
6
6
|
stop(): Promise<void>
|
|
7
7
|
waitForReady(timeoutMs?: number | undefined | null): Promise<void>
|
|
8
8
|
hasCapability(capability: string): boolean
|
|
9
|
+
/** Server-selected LSP `positionEncoding` (utf-16 unless the server is non-conformant); null if omitted/not started. */
|
|
10
|
+
positionEncoding(): string | null
|
|
9
11
|
getRecentStderr(): Array<string>
|
|
10
12
|
openDocument(filePath: string, content: string): Promise<void>
|
|
11
13
|
closeDocument(filePath: string): Promise<void>
|
|
@@ -18,6 +20,16 @@ export declare class NativeLspClient {
|
|
|
18
20
|
prepareCallHierarchy(filePath: string, line: number, character: number): Promise<any>
|
|
19
21
|
incomingCalls(item: any): Promise<any>
|
|
20
22
|
outgoingCalls(item: any): Promise<any>
|
|
23
|
+
/** Project-wide fuzzy symbol search — `workspace/symbol`. Returns `WorkspaceSymbol[] | SymbolInformation[]`. */
|
|
24
|
+
workspaceSymbol(query: string): Promise<any>
|
|
25
|
+
/** Prepare a type-hierarchy item at a position — `textDocument/prepareTypeHierarchy`. */
|
|
26
|
+
prepareTypeHierarchy(filePath: string, line: number, character: number): Promise<any>
|
|
27
|
+
/** Supertypes (base classes / implemented interfaces) — `typeHierarchy/supertypes`. */
|
|
28
|
+
typeHierarchySupertypes(item: any): Promise<any>
|
|
29
|
+
/** Subtypes (subclasses / implementors) — `typeHierarchy/subtypes`. */
|
|
30
|
+
typeHierarchySubtypes(item: any): Promise<any>
|
|
31
|
+
/** Pull diagnostics for a single file — `textDocument/diagnostic` (LSP 3.17+). */
|
|
32
|
+
getDiagnostics(filePath: string): Promise<any>
|
|
21
33
|
}
|
|
22
34
|
|
|
23
35
|
/**
|
|
@@ -206,6 +218,94 @@ export declare function extractJsSymbols(content: string, filePath: string): str
|
|
|
206
218
|
*/
|
|
207
219
|
export declare function findInFileReferences(content: string, filePath: string, line: number, character: number): string | null
|
|
208
220
|
|
|
221
|
+
export interface GraphFactPosition {
|
|
222
|
+
line: number
|
|
223
|
+
character: number
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export interface GraphFactRange {
|
|
227
|
+
start: GraphFactPosition
|
|
228
|
+
end: GraphFactPosition
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export interface GraphFactDeclaration {
|
|
232
|
+
id: string
|
|
233
|
+
name: string
|
|
234
|
+
kind: string
|
|
235
|
+
line: number
|
|
236
|
+
range: GraphFactRange
|
|
237
|
+
selectionRange: GraphFactRange
|
|
238
|
+
exported: boolean
|
|
239
|
+
parent?: string
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export interface GraphFactImport {
|
|
243
|
+
id: string
|
|
244
|
+
specifier: string
|
|
245
|
+
line: number
|
|
246
|
+
importKind: string
|
|
247
|
+
localName?: string
|
|
248
|
+
importedName?: string
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export interface GraphFactExport {
|
|
252
|
+
id: string
|
|
253
|
+
name: string
|
|
254
|
+
line: number
|
|
255
|
+
exportKind: string
|
|
256
|
+
localName?: string
|
|
257
|
+
source?: string
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export interface GraphFactCall {
|
|
261
|
+
id: string
|
|
262
|
+
caller: string
|
|
263
|
+
callee: string
|
|
264
|
+
line: number
|
|
265
|
+
range: GraphFactRange
|
|
266
|
+
kind: string
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export interface GraphFactEdge {
|
|
270
|
+
id: string
|
|
271
|
+
from: string
|
|
272
|
+
to: string
|
|
273
|
+
relation: string
|
|
274
|
+
source: string
|
|
275
|
+
line: number
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export interface GraphFacts {
|
|
279
|
+
kind: 'graphFacts'
|
|
280
|
+
source: 'native-ast'
|
|
281
|
+
language: string
|
|
282
|
+
file: string
|
|
283
|
+
declarations: Array<GraphFactDeclaration>
|
|
284
|
+
imports: Array<GraphFactImport>
|
|
285
|
+
exports: Array<GraphFactExport>
|
|
286
|
+
calls: Array<GraphFactCall>
|
|
287
|
+
edges: Array<GraphFactEdge>
|
|
288
|
+
diagnostics: Array<string>
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export interface GraphFactCapability {
|
|
292
|
+
extension: string
|
|
293
|
+
language: string
|
|
294
|
+
languageId?: string
|
|
295
|
+
structuralSearch: boolean
|
|
296
|
+
signatureOutline: boolean
|
|
297
|
+
graphFacts: boolean
|
|
298
|
+
factFamilies: Array<string>
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Native graph facts as a JSON `GraphFacts` object, or null when no graph-fact
|
|
303
|
+
* extractor supports the file. JS/TS use the richer OXC lane; other supported
|
|
304
|
+
* source languages use tree-sitter syntax inventory. Cross-file semantic
|
|
305
|
+
* identity still needs LSP proof.
|
|
306
|
+
*/
|
|
307
|
+
export declare function extractGraphFacts(content: string, filePath: string): string | null
|
|
308
|
+
|
|
209
309
|
/**
|
|
210
310
|
* Canonical list of file extensions (lowercase, no leading dot) handled by the
|
|
211
311
|
* native oxc JS/TS path (`extractJsSymbols` / `findInFileReferences`). Gate
|
|
@@ -213,6 +313,18 @@ export declare function findInFileReferences(content: string, filePath: string,
|
|
|
213
313
|
*/
|
|
214
314
|
export declare function getSupportedJsTsExtensions(): Array<string>
|
|
215
315
|
|
|
316
|
+
/**
|
|
317
|
+
* Canonical list of file extensions (lowercase, no leading dot) that can emit
|
|
318
|
+
* native graph facts. JS/TS use OXC; other entries use tree-sitter syntax
|
|
319
|
+
* inventory.
|
|
320
|
+
*/
|
|
321
|
+
export declare function getSupportedGraphFactExtensions(): Array<string>
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* JSON `GraphFactCapability[]` describing graph-fact coverage by extension.
|
|
325
|
+
*/
|
|
326
|
+
export declare function getGraphFactCapabilities(): string
|
|
327
|
+
|
|
216
328
|
export interface FileSystemEntry {
|
|
217
329
|
/** Absolute or input-root-relative path as returned by the platform. */
|
|
218
330
|
path: string
|
|
@@ -362,6 +474,7 @@ export interface MinifyConfigSnapshot {
|
|
|
362
474
|
|
|
363
475
|
export declare const MINIFY_CONFIG: MinifyConfigSnapshot
|
|
364
476
|
export declare const SUPPORTED_SIGNATURE_EXTENSIONS: readonly string[]
|
|
477
|
+
export declare const SUPPORTED_GRAPH_FACT_EXTENSIONS: readonly string[]
|
|
365
478
|
export declare const SUPPORTED_STRUCTURAL_EXTENSIONS: readonly string[]
|
|
366
479
|
|
|
367
480
|
/**
|
package/index.js
CHANGED
|
@@ -32,7 +32,10 @@ export const stripPythonDocstrings = nativeBinding.stripPythonDocstrings
|
|
|
32
32
|
export const extractSignatures = nativeBinding.extractSignatures
|
|
33
33
|
export const extractJsSymbols = nativeBinding.extractJsSymbols
|
|
34
34
|
export const findInFileReferences = nativeBinding.findInFileReferences
|
|
35
|
+
export const extractGraphFacts = nativeBinding.extractGraphFacts
|
|
35
36
|
export const getSupportedJsTsExtensions = nativeBinding.getSupportedJsTsExtensions
|
|
37
|
+
export const getSupportedGraphFactExtensions = nativeBinding.getSupportedGraphFactExtensions
|
|
38
|
+
export const getGraphFactCapabilities = nativeBinding.getGraphFactCapabilities
|
|
36
39
|
export const structuralSearch = nativeBinding.structuralSearch
|
|
37
40
|
export const structuralSearchDetailed = nativeBinding.structuralSearchDetailed
|
|
38
41
|
export const structuralSearchFiles = nativeBinding.structuralSearchFiles
|
|
@@ -44,6 +47,7 @@ export const jsonToYamlString = nativeBinding.jsonToYamlString
|
|
|
44
47
|
export const getMINIFY_CONFIG = nativeBinding.getMINIFY_CONFIG
|
|
45
48
|
export const MINIFY_CONFIG = nativeBinding.MINIFY_CONFIG
|
|
46
49
|
export const SUPPORTED_SIGNATURE_EXTENSIONS = nativeBinding.SUPPORTED_SIGNATURE_EXTENSIONS
|
|
50
|
+
export const SUPPORTED_GRAPH_FACT_EXTENSIONS = nativeBinding.SUPPORTED_GRAPH_FACT_EXTENSIONS
|
|
47
51
|
export const SUPPORTED_STRUCTURAL_EXTENSIONS = nativeBinding.SUPPORTED_STRUCTURAL_EXTENSIONS
|
|
48
52
|
export const parseRipgrepJson = nativeBinding.parseRipgrepJson
|
|
49
53
|
export const searchRipgrep = nativeBinding.searchRipgrep
|
|
@@ -55,6 +59,7 @@ export const byteSliceContent = nativeBinding.byteSliceContent
|
|
|
55
59
|
export const sliceContent = nativeBinding.sliceContent
|
|
56
60
|
export const extractMatchingLines = nativeBinding.extractMatchingLines
|
|
57
61
|
export const filterPatch = nativeBinding.filterPatch
|
|
62
|
+
export const PatchLineType = nativeBinding.PatchLineType
|
|
58
63
|
export const inspectBinaryNative = nativeBinding.inspectBinaryNative
|
|
59
64
|
export const extractBinaryStringsNative = nativeBinding.extractBinaryStringsNative
|
|
60
65
|
export const NativeLspClient = nativeBinding.NativeLspClient
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@octocodeai/octocode-engine",
|
|
3
|
-
"version": "16.
|
|
3
|
+
"version": "16.6.2",
|
|
4
4
|
"description": "Rust native Octocode engine for context compression, structural search, and LSP semantic navigation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.cjs",
|
|
7
7
|
"types": "index.d.ts",
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"author": "Guy Bary <bgauryy@octocodeai.com>",
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
10
13
|
"repository": {
|
|
11
14
|
"type": "git",
|
|
12
15
|
"url": "https://github.com/bgauryy/octocode-mcp.git",
|
|
@@ -109,6 +112,26 @@
|
|
|
109
112
|
"import": "./dist/lsp/manager.js",
|
|
110
113
|
"default": "./dist/lsp/manager.js"
|
|
111
114
|
},
|
|
115
|
+
"./lsp/platform": {
|
|
116
|
+
"types": "./dist/lsp/platform.d.ts",
|
|
117
|
+
"import": "./dist/lsp/platform.js",
|
|
118
|
+
"default": "./dist/lsp/platform.js"
|
|
119
|
+
},
|
|
120
|
+
"./lsp/serverDiscovery": {
|
|
121
|
+
"types": "./dist/lsp/serverDiscovery.d.ts",
|
|
122
|
+
"import": "./dist/lsp/serverDiscovery.js",
|
|
123
|
+
"default": "./dist/lsp/serverDiscovery.js"
|
|
124
|
+
},
|
|
125
|
+
"./lsp/serverManifest": {
|
|
126
|
+
"types": "./dist/lsp/serverManifest.d.ts",
|
|
127
|
+
"import": "./dist/lsp/serverManifest.js",
|
|
128
|
+
"default": "./dist/lsp/serverManifest.js"
|
|
129
|
+
},
|
|
130
|
+
"./lsp/serverProvisioner": {
|
|
131
|
+
"types": "./dist/lsp/serverProvisioner.d.ts",
|
|
132
|
+
"import": "./dist/lsp/serverProvisioner.js",
|
|
133
|
+
"default": "./dist/lsp/serverProvisioner.js"
|
|
134
|
+
},
|
|
112
135
|
"./lsp/resolver": {
|
|
113
136
|
"types": "./dist/lsp/resolver.d.ts",
|
|
114
137
|
"import": "./dist/lsp/resolver.js",
|
|
@@ -196,6 +219,18 @@
|
|
|
196
219
|
"lsp/manager": [
|
|
197
220
|
"./dist/lsp/manager.d.ts"
|
|
198
221
|
],
|
|
222
|
+
"lsp/platform": [
|
|
223
|
+
"./dist/lsp/platform.d.ts"
|
|
224
|
+
],
|
|
225
|
+
"lsp/serverDiscovery": [
|
|
226
|
+
"./dist/lsp/serverDiscovery.d.ts"
|
|
227
|
+
],
|
|
228
|
+
"lsp/serverManifest": [
|
|
229
|
+
"./dist/lsp/serverManifest.d.ts"
|
|
230
|
+
],
|
|
231
|
+
"lsp/serverProvisioner": [
|
|
232
|
+
"./dist/lsp/serverProvisioner.d.ts"
|
|
233
|
+
],
|
|
199
234
|
"lsp/resolver": [
|
|
200
235
|
"./dist/lsp/resolver.d.ts"
|
|
201
236
|
],
|
|
@@ -227,12 +262,12 @@
|
|
|
227
262
|
"README.md"
|
|
228
263
|
],
|
|
229
264
|
"optionalDependencies": {
|
|
230
|
-
"@octocodeai/octocode-engine-darwin-arm64": "16.
|
|
231
|
-
"@octocodeai/octocode-engine-darwin-x64": "16.
|
|
232
|
-
"@octocodeai/octocode-engine-linux-arm64-gnu": "16.
|
|
233
|
-
"@octocodeai/octocode-engine-linux-x64-gnu": "16.
|
|
234
|
-
"@octocodeai/octocode-engine-linux-x64-musl": "16.
|
|
235
|
-
"@octocodeai/octocode-engine-win32-x64-msvc": "16.
|
|
265
|
+
"@octocodeai/octocode-engine-darwin-arm64": "16.6.2",
|
|
266
|
+
"@octocodeai/octocode-engine-darwin-x64": "16.6.2",
|
|
267
|
+
"@octocodeai/octocode-engine-linux-arm64-gnu": "16.6.2",
|
|
268
|
+
"@octocodeai/octocode-engine-linux-x64-gnu": "16.6.2",
|
|
269
|
+
"@octocodeai/octocode-engine-linux-x64-musl": "16.6.2",
|
|
270
|
+
"@octocodeai/octocode-engine-win32-x64-msvc": "16.6.2"
|
|
236
271
|
},
|
|
237
272
|
"engines": {
|
|
238
273
|
"node": ">=20.0.0"
|
|
@@ -256,10 +291,11 @@
|
|
|
256
291
|
"build:linux-x64-musl": "node scripts/prebuild.cjs && napi build --platform --release --cross-compile --target x86_64-unknown-linux-musl && node scripts/postbuild.cjs",
|
|
257
292
|
"build:linux-arm64-gnu": "node scripts/prebuild.cjs && napi build --platform --release --cross-compile --target aarch64-unknown-linux-gnu && node scripts/postbuild.cjs",
|
|
258
293
|
"build:windows-x64": "node scripts/prebuild.cjs && napi build --platform --release --cross-compile --target x86_64-pc-windows-msvc && node scripts/postbuild.cjs",
|
|
259
|
-
"build:all": "yarn build:darwin-arm64 && yarn build:darwin-x64 && yarn build:linux-x64-gnu && yarn build:linux-x64-musl && yarn build:linux-arm64-gnu && yarn build:windows-x64 && yarn build:ts",
|
|
294
|
+
"build:all": "yarn clean:binaries && yarn build:darwin-arm64 && yarn build:darwin-x64 && yarn build:linux-x64-gnu && yarn build:linux-x64-musl && yarn build:linux-arm64-gnu && yarn build:windows-x64 && yarn build:ts",
|
|
260
295
|
"build:dev": "yarn readme:sync && node scripts/prebuild.cjs && napi build --platform && node scripts/postbuild.cjs && tsc -p tsconfig.build.json",
|
|
261
296
|
"build:ts": "yarn readme:sync && rm -rf dist && tsc -p tsconfig.build.json",
|
|
262
297
|
"clean": "rm -rf dist/ && rm -f *.node",
|
|
298
|
+
"clean:binaries": "rm -f *.node && find npm -name '*.node' -delete",
|
|
263
299
|
"gen": "node scripts/gen-patterns.mjs",
|
|
264
300
|
"verify:patterns": "node scripts/gen-patterns.mjs && git diff --exit-code src/security/patterns.rs || (echo 'ERROR: src/security/patterns.rs is out of sync with the TS source — run yarn gen and commit the result' && exit 1)",
|
|
265
301
|
"pack:check": "node scripts/check-pack-size.cjs",
|
|
@@ -302,8 +338,13 @@
|
|
|
302
338
|
"prepublishOnly": "yarn version:sync"
|
|
303
339
|
},
|
|
304
340
|
"dependencies": {
|
|
341
|
+
"bash-language-server": "^5.6.0",
|
|
342
|
+
"intelephense": "^1.14.1",
|
|
343
|
+
"pyright": "^1.1.411",
|
|
305
344
|
"typescript": "^5.9.3",
|
|
306
345
|
"typescript-language-server": "^4.4.0",
|
|
346
|
+
"vscode-langservers-extracted": "^4.10.0",
|
|
347
|
+
"yaml-language-server": "^1.23.0",
|
|
307
348
|
"zod": "^4.4.3"
|
|
308
349
|
},
|
|
309
350
|
"devDependencies": {
|