@aigrc/core 0.1.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.
package/dist/index.js ADDED
@@ -0,0 +1,2337 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
11
+ var __export = (target, all) => {
12
+ for (var name in all)
13
+ __defProp(target, name, { get: all[name], enumerable: true });
14
+ };
15
+ var __copyProps = (to, from, except, desc) => {
16
+ if (from && typeof from === "object" || typeof from === "function") {
17
+ for (let key of __getOwnPropNames(from))
18
+ if (!__hasOwnProp.call(to, key) && key !== except)
19
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
20
+ }
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
+ // If the importer is in node compatibility mode or this is not an ESM
25
+ // file that has been converted to a CommonJS file using a Babel-
26
+ // compatible transform (i.e. "__esModule" has not been set), then set
27
+ // "default" to the CommonJS "module.exports" for node compatibility.
28
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
29
+ mod
30
+ ));
31
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
+
33
+ // src/detection/patterns/registry.ts
34
+ var registry_exports = {};
35
+ __export(registry_exports, {
36
+ clearRegistry: () => clearRegistry,
37
+ createImplication: () => createImplication,
38
+ getAllPatterns: () => getAllPatterns,
39
+ getPattern: () => getPattern,
40
+ getPatternsByCategory: () => getPatternsByCategory,
41
+ getPatternsByLanguage: () => getPatternsByLanguage,
42
+ isRegistryInitialized: () => isRegistryInitialized,
43
+ registerPattern: () => registerPattern
44
+ });
45
+ function registerPattern(pattern) {
46
+ if (registry.has(pattern.id)) {
47
+ throw new Error(`Pattern with ID "${pattern.id}" already registered`);
48
+ }
49
+ registry.set(pattern.id, pattern);
50
+ }
51
+ function getPattern(id) {
52
+ return registry.get(id);
53
+ }
54
+ function getAllPatterns() {
55
+ return Array.from(registry.values());
56
+ }
57
+ function getPatternsByCategory(category) {
58
+ return getAllPatterns().filter((p) => p.category === category);
59
+ }
60
+ function getPatternsByLanguage(language) {
61
+ return getAllPatterns().filter((p) => p.language === language || p.language === "any");
62
+ }
63
+ function clearRegistry() {
64
+ registry.clear();
65
+ }
66
+ function isRegistryInitialized() {
67
+ return registry.size > 0;
68
+ }
69
+ function createImplication(factor, value, reason) {
70
+ return { factor, value, reason };
71
+ }
72
+ var registry;
73
+ var init_registry = __esm({
74
+ "src/detection/patterns/registry.ts"() {
75
+ "use strict";
76
+ registry = /* @__PURE__ */ new Map();
77
+ }
78
+ });
79
+
80
+ // src/detection/patterns/python.ts
81
+ var python_exports = {};
82
+ __export(python_exports, {
83
+ pythonPatterns: () => pythonPatterns,
84
+ registerPythonPatterns: () => registerPythonPatterns
85
+ });
86
+ function registerPythonPatterns() {
87
+ pythonPatterns.forEach(registerPattern);
88
+ }
89
+ var pythonPatterns;
90
+ var init_python = __esm({
91
+ "src/detection/patterns/python.ts"() {
92
+ "use strict";
93
+ init_registry();
94
+ pythonPatterns = [
95
+ // ─────────────────────────────────────────────────────────────────
96
+ // ML FRAMEWORKS
97
+ // ─────────────────────────────────────────────────────────────────
98
+ {
99
+ id: "pytorch",
100
+ name: "PyTorch",
101
+ category: "ml_framework",
102
+ language: "python",
103
+ patterns: [
104
+ { type: "import", pattern: "import torch", confidence: "high" },
105
+ { type: "import", pattern: "from torch", confidence: "high" },
106
+ { type: "regex", pattern: "torch\\.nn\\.", confidence: "medium" },
107
+ { type: "regex", pattern: "torch\\.tensor", confidence: "medium" },
108
+ { type: "regex", pattern: "torch\\.cuda", confidence: "medium" }
109
+ ],
110
+ implies: []
111
+ },
112
+ {
113
+ id: "tensorflow",
114
+ name: "TensorFlow",
115
+ category: "ml_framework",
116
+ language: "python",
117
+ patterns: [
118
+ { type: "import", pattern: "import tensorflow", confidence: "high" },
119
+ { type: "import", pattern: "from tensorflow", confidence: "high" },
120
+ { type: "regex", pattern: "tf\\.keras", confidence: "medium" },
121
+ { type: "regex", pattern: "tf\\.data", confidence: "medium" }
122
+ ],
123
+ implies: []
124
+ },
125
+ {
126
+ id: "keras",
127
+ name: "Keras",
128
+ category: "ml_framework",
129
+ language: "python",
130
+ patterns: [
131
+ { type: "import", pattern: "import keras", confidence: "high" },
132
+ { type: "import", pattern: "from keras", confidence: "high" },
133
+ { type: "regex", pattern: "Sequential\\(", confidence: "medium" }
134
+ ],
135
+ implies: []
136
+ },
137
+ {
138
+ id: "scikit-learn",
139
+ name: "Scikit-learn",
140
+ category: "ml_framework",
141
+ language: "python",
142
+ patterns: [
143
+ { type: "import", pattern: "import sklearn", confidence: "high" },
144
+ { type: "import", pattern: "from sklearn", confidence: "high" },
145
+ { type: "regex", pattern: "\\.fit\\(", confidence: "low" },
146
+ { type: "regex", pattern: "\\.predict\\(", confidence: "low" }
147
+ ],
148
+ implies: []
149
+ },
150
+ // ─────────────────────────────────────────────────────────────────
151
+ // LLM PROVIDERS
152
+ // ─────────────────────────────────────────────────────────────────
153
+ {
154
+ id: "openai-python",
155
+ name: "OpenAI Python SDK",
156
+ category: "llm_provider",
157
+ language: "python",
158
+ patterns: [
159
+ { type: "import", pattern: "from openai", confidence: "high" },
160
+ { type: "import", pattern: "import openai", confidence: "high" },
161
+ { type: "regex", pattern: "OpenAI\\s*\\(", confidence: "high" },
162
+ { type: "regex", pattern: "client\\.chat\\.completions", confidence: "medium" },
163
+ { type: "regex", pattern: "ChatCompletion\\.create", confidence: "medium" }
164
+ ],
165
+ implies: [
166
+ createImplication("externalDataAccess", true, "OpenAI SDK calls external API")
167
+ ]
168
+ },
169
+ {
170
+ id: "anthropic-python",
171
+ name: "Anthropic Python SDK",
172
+ category: "llm_provider",
173
+ language: "python",
174
+ patterns: [
175
+ { type: "import", pattern: "from anthropic", confidence: "high" },
176
+ { type: "import", pattern: "import anthropic", confidence: "high" },
177
+ { type: "regex", pattern: "Anthropic\\s*\\(", confidence: "high" },
178
+ { type: "regex", pattern: "client\\.messages\\.create", confidence: "medium" }
179
+ ],
180
+ implies: [
181
+ createImplication("externalDataAccess", true, "Anthropic SDK calls external API")
182
+ ]
183
+ },
184
+ {
185
+ id: "cohere-python",
186
+ name: "Cohere Python SDK",
187
+ category: "llm_provider",
188
+ language: "python",
189
+ patterns: [
190
+ { type: "import", pattern: "import cohere", confidence: "high" },
191
+ { type: "import", pattern: "from cohere", confidence: "high" },
192
+ { type: "regex", pattern: "cohere\\.Client", confidence: "high" }
193
+ ],
194
+ implies: [
195
+ createImplication("externalDataAccess", true, "Cohere SDK calls external API")
196
+ ]
197
+ },
198
+ {
199
+ id: "google-genai",
200
+ name: "Google Generative AI",
201
+ category: "llm_provider",
202
+ language: "python",
203
+ patterns: [
204
+ { type: "import", pattern: "import google.generativeai", confidence: "high" },
205
+ { type: "import", pattern: "from google.generativeai", confidence: "high" },
206
+ { type: "regex", pattern: "genai\\.GenerativeModel", confidence: "high" }
207
+ ],
208
+ implies: [
209
+ createImplication("externalDataAccess", true, "Google GenAI SDK calls external API")
210
+ ]
211
+ },
212
+ // ─────────────────────────────────────────────────────────────────
213
+ // FRAMEWORKS
214
+ // ─────────────────────────────────────────────────────────────────
215
+ {
216
+ id: "huggingface-transformers",
217
+ name: "Hugging Face Transformers",
218
+ category: "framework",
219
+ language: "python",
220
+ patterns: [
221
+ { type: "import", pattern: "from transformers", confidence: "high" },
222
+ { type: "import", pattern: "import transformers", confidence: "high" },
223
+ { type: "regex", pattern: "AutoModel\\.from_pretrained", confidence: "high" },
224
+ { type: "regex", pattern: "AutoTokenizer", confidence: "medium" },
225
+ { type: "regex", pattern: "pipeline\\s*\\(", confidence: "medium" }
226
+ ],
227
+ implies: [
228
+ createImplication("externalDataAccess", true, "Hugging Face typically loads models from Hub")
229
+ ]
230
+ },
231
+ {
232
+ id: "langchain-python",
233
+ name: "LangChain",
234
+ category: "framework",
235
+ language: "python",
236
+ patterns: [
237
+ { type: "import", pattern: "from langchain", confidence: "high" },
238
+ { type: "import", pattern: "import langchain", confidence: "high" },
239
+ { type: "import", pattern: "from langchain_core", confidence: "high" },
240
+ { type: "import", pattern: "from langchain_openai", confidence: "high" },
241
+ { type: "import", pattern: "from langchain_anthropic", confidence: "high" },
242
+ { type: "import", pattern: "from langchain_community", confidence: "high" },
243
+ { type: "regex", pattern: "LLMChain", confidence: "high" },
244
+ { type: "regex", pattern: "ChatPromptTemplate", confidence: "medium" },
245
+ { type: "regex", pattern: "\\.invoke\\s*\\(", confidence: "medium" }
246
+ ],
247
+ implies: [
248
+ createImplication("toolExecution", true, "LangChain supports tool/function calling"),
249
+ createImplication("externalDataAccess", true, "LangChain chains often access external data")
250
+ ]
251
+ },
252
+ {
253
+ id: "llamaindex",
254
+ name: "LlamaIndex",
255
+ category: "framework",
256
+ language: "python",
257
+ patterns: [
258
+ { type: "import", pattern: "from llama_index", confidence: "high" },
259
+ { type: "import", pattern: "import llama_index", confidence: "high" },
260
+ { type: "regex", pattern: "VectorStoreIndex", confidence: "medium" },
261
+ { type: "regex", pattern: "ServiceContext", confidence: "medium" },
262
+ { type: "regex", pattern: "SimpleDirectoryReader", confidence: "medium" }
263
+ ],
264
+ implies: [
265
+ createImplication("externalDataAccess", true, "LlamaIndex typically ingests external data")
266
+ ]
267
+ },
268
+ // ─────────────────────────────────────────────────────────────────
269
+ // AGENT FRAMEWORKS
270
+ // ─────────────────────────────────────────────────────────────────
271
+ {
272
+ id: "crewai",
273
+ name: "CrewAI",
274
+ category: "agent_framework",
275
+ language: "python",
276
+ patterns: [
277
+ { type: "import", pattern: "from crewai", confidence: "high" },
278
+ { type: "import", pattern: "import crewai", confidence: "high" },
279
+ { type: "decorator", pattern: "@agent", confidence: "high" },
280
+ { type: "decorator", pattern: "@task", confidence: "high" },
281
+ { type: "decorator", pattern: "@crew", confidence: "high" },
282
+ { type: "regex", pattern: "Crew\\s*\\(", confidence: "high" },
283
+ { type: "regex", pattern: "Agent\\s*\\(", confidence: "medium" }
284
+ ],
285
+ implies: [
286
+ createImplication("autonomousDecisions", true, "CrewAI enables autonomous agent orchestration"),
287
+ createImplication("toolExecution", true, "CrewAI agents execute tools autonomously")
288
+ ]
289
+ },
290
+ {
291
+ id: "autogen",
292
+ name: "AutoGen",
293
+ category: "agent_framework",
294
+ language: "python",
295
+ patterns: [
296
+ { type: "import", pattern: "from autogen", confidence: "high" },
297
+ { type: "import", pattern: "import autogen", confidence: "high" },
298
+ { type: "regex", pattern: "AssistantAgent", confidence: "high" },
299
+ { type: "regex", pattern: "UserProxyAgent", confidence: "high" },
300
+ { type: "regex", pattern: "GroupChat", confidence: "medium" }
301
+ ],
302
+ implies: [
303
+ createImplication("autonomousDecisions", true, "AutoGen enables multi-agent autonomous systems"),
304
+ createImplication("toolExecution", true, "AutoGen agents can execute code and tools")
305
+ ]
306
+ },
307
+ {
308
+ id: "langgraph",
309
+ name: "LangGraph",
310
+ category: "agent_framework",
311
+ language: "python",
312
+ patterns: [
313
+ { type: "import", pattern: "from langgraph", confidence: "high" },
314
+ { type: "import", pattern: "import langgraph", confidence: "high" },
315
+ { type: "regex", pattern: "StateGraph", confidence: "high" },
316
+ { type: "regex", pattern: "add_node", confidence: "medium" },
317
+ { type: "regex", pattern: "add_edge", confidence: "medium" }
318
+ ],
319
+ implies: [
320
+ createImplication("autonomousDecisions", true, "LangGraph enables stateful agent workflows"),
321
+ createImplication("toolExecution", true, "LangGraph agents execute tools in graph nodes")
322
+ ]
323
+ },
324
+ {
325
+ id: "agency-swarm",
326
+ name: "Agency Swarm",
327
+ category: "agent_framework",
328
+ language: "python",
329
+ patterns: [
330
+ { type: "import", pattern: "from agency_swarm", confidence: "high" },
331
+ { type: "regex", pattern: "Agency\\s*\\(", confidence: "high" }
332
+ ],
333
+ implies: [
334
+ createImplication("autonomousDecisions", true, "Agency Swarm enables multi-agent systems"),
335
+ createImplication("toolExecution", true, "Agency Swarm agents execute tools")
336
+ ]
337
+ },
338
+ // ─────────────────────────────────────────────────────────────────
339
+ // ML OPS
340
+ // ─────────────────────────────────────────────────────────────────
341
+ {
342
+ id: "mlflow",
343
+ name: "MLflow",
344
+ category: "ml_ops",
345
+ language: "python",
346
+ patterns: [
347
+ { type: "import", pattern: "import mlflow", confidence: "high" },
348
+ { type: "import", pattern: "from mlflow", confidence: "high" },
349
+ { type: "regex", pattern: "mlflow\\.log_", confidence: "medium" },
350
+ { type: "regex", pattern: "mlflow\\.start_run", confidence: "medium" }
351
+ ],
352
+ implies: []
353
+ },
354
+ {
355
+ id: "wandb",
356
+ name: "Weights & Biases",
357
+ category: "ml_ops",
358
+ language: "python",
359
+ patterns: [
360
+ { type: "import", pattern: "import wandb", confidence: "high" },
361
+ { type: "import", pattern: "from wandb", confidence: "high" },
362
+ { type: "regex", pattern: "wandb\\.init", confidence: "medium" }
363
+ ],
364
+ implies: [
365
+ createImplication("externalDataAccess", true, "W&B syncs to external service")
366
+ ]
367
+ }
368
+ ];
369
+ }
370
+ });
371
+
372
+ // src/detection/patterns/javascript.ts
373
+ var javascript_exports = {};
374
+ __export(javascript_exports, {
375
+ javascriptPatterns: () => javascriptPatterns,
376
+ registerJavaScriptPatterns: () => registerJavaScriptPatterns
377
+ });
378
+ function registerJavaScriptPatterns() {
379
+ javascriptPatterns.forEach(registerPattern);
380
+ }
381
+ var javascriptPatterns;
382
+ var init_javascript = __esm({
383
+ "src/detection/patterns/javascript.ts"() {
384
+ "use strict";
385
+ init_registry();
386
+ javascriptPatterns = [
387
+ // ─────────────────────────────────────────────────────────────────
388
+ // LLM PROVIDERS
389
+ // ─────────────────────────────────────────────────────────────────
390
+ {
391
+ id: "openai-js",
392
+ name: "OpenAI JavaScript SDK",
393
+ category: "llm_provider",
394
+ language: "javascript",
395
+ patterns: [
396
+ { type: "import", pattern: 'from "openai"', confidence: "high" },
397
+ { type: "import", pattern: "from 'openai'", confidence: "high" },
398
+ { type: "regex", pattern: "new OpenAI\\s*\\(", confidence: "high" },
399
+ { type: "regex", pattern: "openai\\.chat\\.completions", confidence: "medium" }
400
+ ],
401
+ implies: [
402
+ createImplication("externalDataAccess", true, "OpenAI SDK calls external API")
403
+ ]
404
+ },
405
+ {
406
+ id: "anthropic-js",
407
+ name: "Anthropic JavaScript SDK",
408
+ category: "llm_provider",
409
+ language: "javascript",
410
+ patterns: [
411
+ { type: "import", pattern: 'from "@anthropic-ai/sdk"', confidence: "high" },
412
+ { type: "import", pattern: "from '@anthropic-ai/sdk'", confidence: "high" },
413
+ { type: "regex", pattern: "new Anthropic\\s*\\(", confidence: "high" },
414
+ { type: "regex", pattern: "\\.messages\\.create", confidence: "medium" }
415
+ ],
416
+ implies: [
417
+ createImplication("externalDataAccess", true, "Anthropic SDK calls external API")
418
+ ]
419
+ },
420
+ {
421
+ id: "cohere-js",
422
+ name: "Cohere JavaScript SDK",
423
+ category: "llm_provider",
424
+ language: "javascript",
425
+ patterns: [
426
+ { type: "import", pattern: 'from "cohere-ai"', confidence: "high" },
427
+ { type: "import", pattern: "from 'cohere-ai'", confidence: "high" },
428
+ { type: "regex", pattern: "new CohereClient", confidence: "high" }
429
+ ],
430
+ implies: [
431
+ createImplication("externalDataAccess", true, "Cohere SDK calls external API")
432
+ ]
433
+ },
434
+ {
435
+ id: "replicate-js",
436
+ name: "Replicate",
437
+ category: "llm_provider",
438
+ language: "javascript",
439
+ patterns: [
440
+ { type: "import", pattern: 'from "replicate"', confidence: "high" },
441
+ { type: "import", pattern: "from 'replicate'", confidence: "high" },
442
+ { type: "regex", pattern: "new Replicate\\s*\\(", confidence: "high" }
443
+ ],
444
+ implies: [
445
+ createImplication("externalDataAccess", true, "Replicate SDK calls external API")
446
+ ]
447
+ },
448
+ {
449
+ id: "huggingface-js",
450
+ name: "Hugging Face Inference",
451
+ category: "llm_provider",
452
+ language: "javascript",
453
+ patterns: [
454
+ { type: "import", pattern: 'from "@huggingface/inference"', confidence: "high" },
455
+ { type: "import", pattern: "from '@huggingface/inference'", confidence: "high" },
456
+ { type: "regex", pattern: "HfInference\\s*\\(", confidence: "high" }
457
+ ],
458
+ implies: [
459
+ createImplication("externalDataAccess", true, "Hugging Face SDK calls external API")
460
+ ]
461
+ },
462
+ {
463
+ id: "together-js",
464
+ name: "Together AI",
465
+ category: "llm_provider",
466
+ language: "javascript",
467
+ patterns: [
468
+ { type: "import", pattern: 'from "together-ai"', confidence: "high" },
469
+ { type: "import", pattern: "from 'together-ai'", confidence: "high" },
470
+ { type: "regex", pattern: "new Together\\s*\\(", confidence: "high" }
471
+ ],
472
+ implies: [
473
+ createImplication("externalDataAccess", true, "Together AI SDK calls external API")
474
+ ]
475
+ },
476
+ {
477
+ id: "groq-js",
478
+ name: "Groq SDK",
479
+ category: "llm_provider",
480
+ language: "javascript",
481
+ patterns: [
482
+ { type: "import", pattern: 'from "groq-sdk"', confidence: "high" },
483
+ { type: "import", pattern: "from 'groq-sdk'", confidence: "high" },
484
+ { type: "regex", pattern: "new Groq\\s*\\(", confidence: "high" }
485
+ ],
486
+ implies: [
487
+ createImplication("externalDataAccess", true, "Groq SDK calls external API")
488
+ ]
489
+ },
490
+ // ─────────────────────────────────────────────────────────────────
491
+ // FRAMEWORKS
492
+ // ─────────────────────────────────────────────────────────────────
493
+ {
494
+ id: "langchain-js",
495
+ name: "LangChain.js",
496
+ category: "framework",
497
+ language: "javascript",
498
+ patterns: [
499
+ { type: "import", pattern: 'from "langchain"', confidence: "high" },
500
+ { type: "import", pattern: "from 'langchain'", confidence: "high" },
501
+ { type: "import", pattern: 'from "@langchain/core"', confidence: "high" },
502
+ { type: "import", pattern: 'from "@langchain/openai"', confidence: "high" },
503
+ { type: "import", pattern: 'from "@langchain/anthropic"', confidence: "high" },
504
+ { type: "import", pattern: 'from "@langchain/community"', confidence: "high" },
505
+ { type: "regex", pattern: "new ChatOpenAI", confidence: "medium" },
506
+ { type: "regex", pattern: "ChatPromptTemplate", confidence: "medium" },
507
+ { type: "regex", pattern: "\\.invoke\\s*\\(", confidence: "low" }
508
+ ],
509
+ implies: [
510
+ createImplication("toolExecution", true, "LangChain.js supports tool calling"),
511
+ createImplication("externalDataAccess", true, "LangChain.js chains access external data")
512
+ ]
513
+ },
514
+ {
515
+ id: "vercel-ai-sdk",
516
+ name: "Vercel AI SDK",
517
+ category: "framework",
518
+ language: "javascript",
519
+ patterns: [
520
+ { type: "import", pattern: 'from "ai"', confidence: "medium" },
521
+ { type: "import", pattern: "from 'ai'", confidence: "medium" },
522
+ { type: "import", pattern: 'from "ai/react"', confidence: "high" },
523
+ { type: "import", pattern: 'from "@ai-sdk/openai"', confidence: "high" },
524
+ { type: "import", pattern: 'from "@ai-sdk/anthropic"', confidence: "high" },
525
+ { type: "regex", pattern: "generateText\\s*\\(", confidence: "high" },
526
+ { type: "regex", pattern: "streamText\\s*\\(", confidence: "high" },
527
+ { type: "regex", pattern: "useChat\\s*\\(", confidence: "high" },
528
+ { type: "regex", pattern: "useCompletion\\s*\\(", confidence: "high" }
529
+ ],
530
+ implies: [
531
+ createImplication("customerFacing", true, "Vercel AI SDK typically used in user-facing apps"),
532
+ createImplication("externalDataAccess", true, "Vercel AI SDK calls LLM providers")
533
+ ]
534
+ },
535
+ {
536
+ id: "llamaindex-js",
537
+ name: "LlamaIndex.TS",
538
+ category: "framework",
539
+ language: "javascript",
540
+ patterns: [
541
+ { type: "import", pattern: 'from "llamaindex"', confidence: "high" },
542
+ { type: "import", pattern: "from 'llamaindex'", confidence: "high" },
543
+ { type: "regex", pattern: "VectorStoreIndex", confidence: "medium" }
544
+ ],
545
+ implies: [
546
+ createImplication("externalDataAccess", true, "LlamaIndex typically ingests external data")
547
+ ]
548
+ },
549
+ // ─────────────────────────────────────────────────────────────────
550
+ // ML FRAMEWORKS
551
+ // ─────────────────────────────────────────────────────────────────
552
+ {
553
+ id: "tensorflow-js",
554
+ name: "TensorFlow.js",
555
+ category: "ml_framework",
556
+ language: "javascript",
557
+ patterns: [
558
+ { type: "import", pattern: 'from "@tensorflow/tfjs"', confidence: "high" },
559
+ { type: "import", pattern: "from '@tensorflow/tfjs'", confidence: "high" },
560
+ { type: "import", pattern: 'from "@tensorflow/tfjs-node"', confidence: "high" },
561
+ { type: "regex", pattern: "tf\\.loadLayersModel", confidence: "medium" },
562
+ { type: "regex", pattern: "tf\\.sequential", confidence: "medium" }
563
+ ],
564
+ implies: []
565
+ },
566
+ {
567
+ id: "onnxruntime-js",
568
+ name: "ONNX Runtime Web",
569
+ category: "ml_framework",
570
+ language: "javascript",
571
+ patterns: [
572
+ { type: "import", pattern: 'from "onnxruntime-web"', confidence: "high" },
573
+ { type: "import", pattern: 'from "onnxruntime-node"', confidence: "high" },
574
+ { type: "regex", pattern: "InferenceSession\\.create", confidence: "high" }
575
+ ],
576
+ implies: []
577
+ },
578
+ {
579
+ id: "transformers-js",
580
+ name: "Transformers.js",
581
+ category: "ml_framework",
582
+ language: "javascript",
583
+ patterns: [
584
+ { type: "import", pattern: 'from "@xenova/transformers"', confidence: "high" },
585
+ { type: "import", pattern: 'from "@huggingface/transformers"', confidence: "high" },
586
+ { type: "regex", pattern: "pipeline\\s*\\(", confidence: "medium" }
587
+ ],
588
+ implies: []
589
+ },
590
+ // ─────────────────────────────────────────────────────────────────
591
+ // AGENT FRAMEWORKS
592
+ // ─────────────────────────────────────────────────────────────────
593
+ {
594
+ id: "langgraph-js",
595
+ name: "LangGraph.js",
596
+ category: "agent_framework",
597
+ language: "javascript",
598
+ patterns: [
599
+ { type: "import", pattern: 'from "@langchain/langgraph"', confidence: "high" },
600
+ { type: "regex", pattern: "StateGraph", confidence: "high" },
601
+ { type: "regex", pattern: "addNode", confidence: "medium" }
602
+ ],
603
+ implies: [
604
+ createImplication("autonomousDecisions", true, "LangGraph enables stateful agent workflows"),
605
+ createImplication("toolExecution", true, "LangGraph agents execute tools")
606
+ ]
607
+ },
608
+ {
609
+ id: "autogen-js",
610
+ name: "AutoGen.js",
611
+ category: "agent_framework",
612
+ language: "javascript",
613
+ patterns: [
614
+ { type: "import", pattern: 'from "autogen"', confidence: "high" },
615
+ { type: "regex", pattern: "AssistantAgent", confidence: "high" }
616
+ ],
617
+ implies: [
618
+ createImplication("autonomousDecisions", true, "AutoGen enables multi-agent systems"),
619
+ createImplication("toolExecution", true, "AutoGen agents execute tools")
620
+ ]
621
+ }
622
+ ];
623
+ }
624
+ });
625
+
626
+ // src/detection/patterns/model-files.ts
627
+ var model_files_exports = {};
628
+ __export(model_files_exports, {
629
+ modelFilePatterns: () => modelFilePatterns,
630
+ registerModelFilePatterns: () => registerModelFilePatterns
631
+ });
632
+ function registerModelFilePatterns() {
633
+ modelFilePatterns.forEach(registerPattern);
634
+ }
635
+ var modelFilePatterns;
636
+ var init_model_files = __esm({
637
+ "src/detection/patterns/model-files.ts"() {
638
+ "use strict";
639
+ init_registry();
640
+ modelFilePatterns = [
641
+ {
642
+ id: "pytorch-model",
643
+ name: "PyTorch Model File",
644
+ category: "model_file",
645
+ language: "any",
646
+ patterns: [
647
+ { type: "literal", pattern: ".pt", confidence: "high" },
648
+ { type: "literal", pattern: ".pth", confidence: "high" },
649
+ { type: "literal", pattern: ".bin", confidence: "medium", description: "May be transformer weights" }
650
+ ],
651
+ implies: []
652
+ },
653
+ {
654
+ id: "safetensors-model",
655
+ name: "SafeTensors Model File",
656
+ category: "model_file",
657
+ language: "any",
658
+ patterns: [
659
+ { type: "literal", pattern: ".safetensors", confidence: "high" }
660
+ ],
661
+ implies: []
662
+ },
663
+ {
664
+ id: "onnx-model",
665
+ name: "ONNX Model File",
666
+ category: "model_file",
667
+ language: "any",
668
+ patterns: [
669
+ { type: "literal", pattern: ".onnx", confidence: "high" }
670
+ ],
671
+ implies: []
672
+ },
673
+ {
674
+ id: "keras-model",
675
+ name: "Keras/TensorFlow Model File",
676
+ category: "model_file",
677
+ language: "any",
678
+ patterns: [
679
+ { type: "literal", pattern: ".h5", confidence: "high" },
680
+ { type: "literal", pattern: ".keras", confidence: "high" },
681
+ { type: "literal", pattern: ".pb", confidence: "medium", description: "TensorFlow frozen graph" }
682
+ ],
683
+ implies: []
684
+ },
685
+ {
686
+ id: "sklearn-model",
687
+ name: "Scikit-learn Model File",
688
+ category: "model_file",
689
+ language: "any",
690
+ patterns: [
691
+ { type: "literal", pattern: ".pkl", confidence: "low", description: "Could be any pickle file" },
692
+ { type: "literal", pattern: ".joblib", confidence: "high" }
693
+ ],
694
+ implies: []
695
+ },
696
+ {
697
+ id: "model-config",
698
+ name: "Model Configuration File",
699
+ category: "model_file",
700
+ language: "any",
701
+ patterns: [
702
+ { type: "regex", pattern: "config\\.json$", confidence: "low", description: "May be model config" },
703
+ { type: "regex", pattern: "model\\.json$", confidence: "medium" },
704
+ { type: "regex", pattern: "adapter_config\\.json$", confidence: "high", description: "LoRA adapter" },
705
+ { type: "regex", pattern: "tokenizer\\.json$", confidence: "high" },
706
+ { type: "regex", pattern: "tokenizer_config\\.json$", confidence: "high" },
707
+ { type: "regex", pattern: "generation_config\\.json$", confidence: "high" }
708
+ ],
709
+ implies: []
710
+ },
711
+ {
712
+ id: "gguf-model",
713
+ name: "GGUF Model File",
714
+ category: "model_file",
715
+ language: "any",
716
+ patterns: [
717
+ { type: "literal", pattern: ".gguf", confidence: "high", description: "llama.cpp format" },
718
+ { type: "literal", pattern: ".ggml", confidence: "high", description: "Legacy GGML format" }
719
+ ],
720
+ implies: []
721
+ },
722
+ {
723
+ id: "mlx-model",
724
+ name: "MLX Model File",
725
+ category: "model_file",
726
+ language: "any",
727
+ patterns: [
728
+ { type: "literal", pattern: ".npz", confidence: "low", description: "May be MLX weights" }
729
+ ],
730
+ implies: []
731
+ }
732
+ ];
733
+ }
734
+ });
735
+
736
+ // src/detection/patterns/risk-indicators.ts
737
+ var risk_indicators_exports = {};
738
+ __export(risk_indicators_exports, {
739
+ registerRiskIndicatorPatterns: () => registerRiskIndicatorPatterns,
740
+ riskIndicatorPatterns: () => riskIndicatorPatterns
741
+ });
742
+ function registerRiskIndicatorPatterns() {
743
+ riskIndicatorPatterns.forEach(registerPattern);
744
+ }
745
+ var riskIndicatorPatterns;
746
+ var init_risk_indicators = __esm({
747
+ "src/detection/patterns/risk-indicators.ts"() {
748
+ "use strict";
749
+ init_registry();
750
+ riskIndicatorPatterns = [
751
+ // ─────────────────────────────────────────────────────────────────
752
+ // AUTONOMOUS EXECUTION
753
+ // ─────────────────────────────────────────────────────────────────
754
+ {
755
+ id: "autonomous-execution",
756
+ name: "Autonomous Execution Patterns",
757
+ category: "framework",
758
+ language: "any",
759
+ patterns: [
760
+ { type: "regex", pattern: "\\.invoke\\s*\\(", confidence: "medium", description: "Agent invocation" },
761
+ { type: "regex", pattern: "\\.run\\s*\\(", confidence: "low", description: "Run method (generic)" },
762
+ { type: "regex", pattern: "while\\s+True", confidence: "medium", description: "Potential agent loop (Python)" },
763
+ { type: "regex", pattern: "while\\s*\\(\\s*true\\s*\\)", confidence: "medium", description: "Potential agent loop (JS)" },
764
+ { type: "regex", pattern: "agent\\.execute", confidence: "high", description: "Agent execution" },
765
+ { type: "regex", pattern: "AgentExecutor", confidence: "high", description: "LangChain agent executor" }
766
+ ],
767
+ implies: [
768
+ createImplication("autonomousDecisions", true, "Pattern indicates autonomous execution capability")
769
+ ]
770
+ },
771
+ // ─────────────────────────────────────────────────────────────────
772
+ // TOOL EXECUTION
773
+ // ─────────────────────────────────────────────────────────────────
774
+ {
775
+ id: "tool-execution",
776
+ name: "Tool Execution Patterns",
777
+ category: "framework",
778
+ language: "any",
779
+ patterns: [
780
+ { type: "decorator", pattern: "@tool", confidence: "high", description: "Tool decorator" },
781
+ { type: "regex", pattern: "function_calling", confidence: "high" },
782
+ { type: "regex", pattern: "tools\\s*[=:]\\s*\\[", confidence: "medium" },
783
+ { type: "regex", pattern: "bind_tools", confidence: "high" },
784
+ { type: "regex", pattern: "create_tool", confidence: "high" },
785
+ { type: "regex", pattern: "StructuredTool", confidence: "high" },
786
+ { type: "regex", pattern: "BaseTool", confidence: "high" },
787
+ { type: "regex", pattern: "mcp_server", confidence: "high", description: "MCP tool server" },
788
+ { type: "regex", pattern: "McpServer", confidence: "high", description: "MCP server" }
789
+ ],
790
+ implies: [
791
+ createImplication("toolExecution", true, "Pattern indicates tool execution capability")
792
+ ]
793
+ },
794
+ // ─────────────────────────────────────────────────────────────────
795
+ // EXTERNAL DATA ACCESS
796
+ // ─────────────────────────────────────────────────────────────────
797
+ {
798
+ id: "external-data-access",
799
+ name: "External Data Access Patterns",
800
+ category: "framework",
801
+ language: "any",
802
+ patterns: [
803
+ { type: "regex", pattern: "requests\\.(get|post|put|delete|patch)", confidence: "medium" },
804
+ { type: "regex", pattern: "fetch\\s*\\(", confidence: "medium" },
805
+ { type: "regex", pattern: "axios\\.", confidence: "medium" },
806
+ { type: "regex", pattern: "httpx\\.", confidence: "medium" },
807
+ { type: "regex", pattern: "aiohttp\\.", confidence: "medium" },
808
+ { type: "regex", pattern: "WebBrowser", confidence: "high", description: "Web browsing capability" },
809
+ { type: "regex", pattern: "Retriever", confidence: "medium", description: "RAG retrieval" },
810
+ { type: "regex", pattern: "VectorStore", confidence: "medium", description: "Vector database access" }
811
+ ],
812
+ implies: [
813
+ createImplication("externalDataAccess", true, "Pattern indicates external data access")
814
+ ]
815
+ },
816
+ // ─────────────────────────────────────────────────────────────────
817
+ // DATABASE ACCESS
818
+ // ─────────────────────────────────────────────────────────────────
819
+ {
820
+ id: "database-access",
821
+ name: "Database Access Patterns",
822
+ category: "framework",
823
+ language: "any",
824
+ patterns: [
825
+ { type: "regex", pattern: "SQLDatabase", confidence: "high" },
826
+ { type: "regex", pattern: "create_sql_agent", confidence: "high" },
827
+ { type: "regex", pattern: "sql_agent", confidence: "high" },
828
+ { type: "regex", pattern: "MongoClient", confidence: "medium" },
829
+ { type: "regex", pattern: "psycopg", confidence: "medium" },
830
+ { type: "regex", pattern: "pymongo", confidence: "medium" }
831
+ ],
832
+ implies: [
833
+ createImplication("externalDataAccess", true, "Pattern indicates database access")
834
+ ]
835
+ },
836
+ // ─────────────────────────────────────────────────────────────────
837
+ // PII PROCESSING
838
+ // ─────────────────────────────────────────────────────────────────
839
+ {
840
+ id: "pii-processing",
841
+ name: "PII Processing Patterns",
842
+ category: "framework",
843
+ language: "any",
844
+ patterns: [
845
+ { type: "regex", pattern: "email|e-mail|e_mail", confidence: "low" },
846
+ { type: "regex", pattern: "phone_number|phone|telephone|mobile", confidence: "low" },
847
+ { type: "regex", pattern: "ssn|social_security|social-security", confidence: "high" },
848
+ { type: "regex", pattern: "password|passwd|pwd", confidence: "medium" },
849
+ { type: "regex", pattern: "credit_card|creditcard|cc_number", confidence: "high" },
850
+ { type: "regex", pattern: "date_of_birth|dob|birthdate", confidence: "medium" },
851
+ { type: "regex", pattern: "address|street|city|zipcode|zip_code", confidence: "low" },
852
+ { type: "regex", pattern: "passport|driver_license|drivers_license", confidence: "high" }
853
+ ],
854
+ implies: [
855
+ createImplication("piiProcessing", "yes", "Pattern suggests PII handling")
856
+ ]
857
+ },
858
+ // ─────────────────────────────────────────────────────────────────
859
+ // HIGH-STAKES DECISIONS
860
+ // ─────────────────────────────────────────────────────────────────
861
+ {
862
+ id: "high-stakes-medical",
863
+ name: "Medical/Healthcare Patterns",
864
+ category: "framework",
865
+ language: "any",
866
+ patterns: [
867
+ { type: "regex", pattern: "medical|diagnosis|patient|treatment", confidence: "high" },
868
+ { type: "regex", pattern: "healthcare|health_care|clinical", confidence: "high" },
869
+ { type: "regex", pattern: "prescription|medication|drug", confidence: "medium" },
870
+ { type: "regex", pattern: "symptom|disease|condition", confidence: "medium" }
871
+ ],
872
+ implies: [
873
+ createImplication("highStakesDecisions", true, "Pattern indicates medical/healthcare domain")
874
+ ]
875
+ },
876
+ {
877
+ id: "high-stakes-legal",
878
+ name: "Legal Patterns",
879
+ category: "framework",
880
+ language: "any",
881
+ patterns: [
882
+ { type: "regex", pattern: "legal|lawsuit|attorney|lawyer", confidence: "high" },
883
+ { type: "regex", pattern: "contract|agreement|terms", confidence: "low" },
884
+ { type: "regex", pattern: "court|judge|verdict|sentence", confidence: "high" },
885
+ { type: "regex", pattern: "compliance|regulation|regulatory", confidence: "medium" }
886
+ ],
887
+ implies: [
888
+ createImplication("highStakesDecisions", true, "Pattern indicates legal domain")
889
+ ]
890
+ },
891
+ {
892
+ id: "high-stakes-financial",
893
+ name: "Financial Patterns",
894
+ category: "framework",
895
+ language: "any",
896
+ patterns: [
897
+ { type: "regex", pattern: "financial|trading|investment|loan", confidence: "high" },
898
+ { type: "regex", pattern: "credit_score|creditworthiness|credit_rating", confidence: "high" },
899
+ { type: "regex", pattern: "mortgage|banking|transaction", confidence: "medium" },
900
+ { type: "regex", pattern: "portfolio|stock|bond|asset", confidence: "medium" }
901
+ ],
902
+ implies: [
903
+ createImplication("highStakesDecisions", true, "Pattern indicates financial domain")
904
+ ]
905
+ },
906
+ {
907
+ id: "high-stakes-hiring",
908
+ name: "Hiring/Employment Patterns",
909
+ category: "framework",
910
+ language: "any",
911
+ patterns: [
912
+ { type: "regex", pattern: "hiring|recruitment|candidate|applicant", confidence: "high" },
913
+ { type: "regex", pattern: "resume|cv|curriculum_vitae", confidence: "high" },
914
+ { type: "regex", pattern: "interview|screening|background_check", confidence: "high" },
915
+ { type: "regex", pattern: "employee|termination|performance_review", confidence: "medium" }
916
+ ],
917
+ implies: [
918
+ createImplication("highStakesDecisions", true, "Pattern indicates hiring/employment domain")
919
+ ]
920
+ },
921
+ // ─────────────────────────────────────────────────────────────────
922
+ // CUSTOMER FACING
923
+ // ─────────────────────────────────────────────────────────────────
924
+ {
925
+ id: "customer-facing",
926
+ name: "Customer-Facing Patterns",
927
+ category: "framework",
928
+ language: "any",
929
+ patterns: [
930
+ { type: "regex", pattern: "chatbot|chat_bot|conversational", confidence: "high" },
931
+ { type: "regex", pattern: "customer_service|customer_support", confidence: "high" },
932
+ { type: "regex", pattern: "useChat|useCompletion", confidence: "high", description: "Vercel AI hooks" },
933
+ { type: "regex", pattern: "StreamingTextResponse", confidence: "high" },
934
+ { type: "regex", pattern: "user_input|user_message|user_query", confidence: "medium" }
935
+ ],
936
+ implies: [
937
+ createImplication("customerFacing", true, "Pattern indicates customer-facing application")
938
+ ]
939
+ }
940
+ ];
941
+ }
942
+ });
943
+
944
+ // src/index.ts
945
+ var index_exports = {};
946
+ __export(index_exports, {
947
+ ApprovalSchema: () => ApprovalSchema,
948
+ AssetCardSchema: () => AssetCardSchema,
949
+ ClassificationSchema: () => ClassificationSchema,
950
+ ConfidenceLevelSchema: () => ConfidenceLevelSchema,
951
+ ConstraintsSchema: () => ConstraintsSchema,
952
+ ControlStatusSchema: () => ControlStatusSchema,
953
+ DetectionStrategySchema: () => DetectionStrategySchema,
954
+ FrameworkCategorySchema: () => FrameworkCategorySchema,
955
+ GovernanceSchema: () => GovernanceSchema,
956
+ IntentSchema: () => IntentSchema,
957
+ JurisdictionClassificationSchema: () => JurisdictionClassificationSchema,
958
+ MODEL_EXTENSIONS: () => MODEL_EXTENSIONS,
959
+ OwnerSchema: () => OwnerSchema,
960
+ RiskFactorsSchema: () => RiskFactorsSchema,
961
+ TechnicalSchema: () => TechnicalSchema,
962
+ TrustworthinessCharacteristicSchema: () => TrustworthinessCharacteristicSchema,
963
+ TrustworthinessSchema: () => TrustworthinessSchema,
964
+ addJurisdiction: () => addJurisdiction,
965
+ analyzeImports: () => analyzeImports,
966
+ applyImplicationChains: () => applyImplicationChains,
967
+ classifyRisk: () => classifyRisk,
968
+ clearRegistry: () => clearRegistry,
969
+ createAssetCard: () => createAssetCard,
970
+ createImplication: () => createImplication,
971
+ detectAnnotations: () => detectAnnotations,
972
+ formatDate: () => formatDate,
973
+ generateAssetId: () => generateAssetId,
974
+ getAllPatterns: () => getAllPatterns,
975
+ getPattern: () => getPattern,
976
+ getPatternsByCategory: () => getPatternsByCategory,
977
+ getPatternsByLanguage: () => getPatternsByLanguage,
978
+ inferRiskFactors: () => inferRiskFactors,
979
+ initializePatterns: () => initializePatterns,
980
+ isModelFile: () => isModelFile,
981
+ isRegistryInitialized: () => isRegistryInitialized,
982
+ javascriptPatterns: () => javascriptPatterns,
983
+ linkAssetToTicket: () => linkAssetToTicket,
984
+ loadAssetCard: () => loadAssetCard,
985
+ matchPatterns: () => matchPatterns,
986
+ modelFilePatterns: () => modelFilePatterns,
987
+ parseDate: () => parseDate,
988
+ pythonPatterns: () => pythonPatterns,
989
+ registerPattern: () => registerPattern,
990
+ resetPatterns: () => resetPatterns,
991
+ riskIndicatorPatterns: () => riskIndicatorPatterns,
992
+ saveAssetCard: () => saveAssetCard,
993
+ scan: () => scan,
994
+ scanFileExtension: () => scanFileExtension,
995
+ scanSync: () => scanSync,
996
+ slugify: () => slugify,
997
+ suggestAssetCard: () => suggestAssetCard,
998
+ updateJurisdictionCompliance: () => updateJurisdictionCompliance,
999
+ validateAssetCard: () => validateAssetCard,
1000
+ validateGoldenThread: () => validateGoldenThread,
1001
+ validateRiskFactors: () => validateRiskFactors
1002
+ });
1003
+ module.exports = __toCommonJS(index_exports);
1004
+
1005
+ // src/schemas/index.ts
1006
+ var import_zod = require("zod");
1007
+ var OwnerSchema = import_zod.z.object({
1008
+ name: import_zod.z.string().min(1),
1009
+ email: import_zod.z.string().email(),
1010
+ team: import_zod.z.string().optional()
1011
+ });
1012
+ var TechnicalSchema = import_zod.z.object({
1013
+ type: import_zod.z.enum(["model", "agent", "api_client", "framework", "pipeline"]),
1014
+ framework: import_zod.z.string().optional(),
1015
+ frameworkVersion: import_zod.z.string().optional(),
1016
+ components: import_zod.z.array(
1017
+ import_zod.z.object({
1018
+ type: import_zod.z.string(),
1019
+ provider: import_zod.z.string().optional(),
1020
+ model: import_zod.z.string().optional()
1021
+ })
1022
+ ).optional(),
1023
+ sourceFiles: import_zod.z.array(import_zod.z.string()).optional()
1024
+ });
1025
+ var RiskFactorsSchema = import_zod.z.object({
1026
+ autonomousDecisions: import_zod.z.boolean().default(false),
1027
+ customerFacing: import_zod.z.boolean().default(false),
1028
+ toolExecution: import_zod.z.boolean().default(false),
1029
+ externalDataAccess: import_zod.z.boolean().default(false),
1030
+ piiProcessing: import_zod.z.enum(["yes", "no", "unknown"]).default("unknown"),
1031
+ highStakesDecisions: import_zod.z.boolean().default(false)
1032
+ });
1033
+ var ControlStatusSchema = import_zod.z.object({
1034
+ controlId: import_zod.z.string(),
1035
+ status: import_zod.z.enum(["implemented", "partial", "not_implemented", "not_applicable"]),
1036
+ evidence: import_zod.z.string().optional(),
1037
+ notes: import_zod.z.string().optional(),
1038
+ lastUpdated: import_zod.z.string().datetime().optional()
1039
+ });
1040
+ var JurisdictionClassificationSchema = import_zod.z.object({
1041
+ /** Profile/jurisdiction ID (e.g., "eu-ai-act", "us-omb-m24") */
1042
+ jurisdictionId: import_zod.z.string(),
1043
+ /** Risk level mapped to this jurisdiction's terminology */
1044
+ riskLevel: import_zod.z.string(),
1045
+ /** Jurisdiction-specific category (e.g., EU AI Act category) */
1046
+ category: import_zod.z.string().optional(),
1047
+ /** Status of controls for this jurisdiction */
1048
+ controlStatuses: import_zod.z.array(ControlStatusSchema).optional(),
1049
+ /** Required artifacts for this jurisdiction */
1050
+ requiredArtifacts: import_zod.z.array(
1051
+ import_zod.z.object({
1052
+ artifactId: import_zod.z.string(),
1053
+ status: import_zod.z.enum(["pending", "complete", "not_applicable"]),
1054
+ path: import_zod.z.string().optional()
1055
+ })
1056
+ ).optional(),
1057
+ /** Last compliance check date */
1058
+ lastChecked: import_zod.z.string().datetime().optional(),
1059
+ /** Compliance percentage for this jurisdiction */
1060
+ compliancePercentage: import_zod.z.number().min(0).max(100).optional()
1061
+ });
1062
+ var TrustworthinessCharacteristicSchema = import_zod.z.object({
1063
+ score: import_zod.z.number().min(0).max(100).optional(),
1064
+ notes: import_zod.z.string().optional(),
1065
+ lastAssessed: import_zod.z.string().datetime().optional(),
1066
+ assessedBy: import_zod.z.string().optional()
1067
+ });
1068
+ var TrustworthinessSchema = import_zod.z.object({
1069
+ /** Valid and reliable: produces accurate, consistent results */
1070
+ valid: TrustworthinessCharacteristicSchema.optional(),
1071
+ reliable: TrustworthinessCharacteristicSchema.optional(),
1072
+ /** Safe: minimizes harm and risk */
1073
+ safe: TrustworthinessCharacteristicSchema.optional(),
1074
+ /** Secure: protected against threats */
1075
+ secure: TrustworthinessCharacteristicSchema.optional(),
1076
+ /** Accountable: clear responsibility and oversight */
1077
+ accountable: TrustworthinessCharacteristicSchema.optional(),
1078
+ /** Transparent: understandable and open about limitations */
1079
+ transparent: TrustworthinessCharacteristicSchema.optional(),
1080
+ /** Explainable: decisions can be understood */
1081
+ explainable: TrustworthinessCharacteristicSchema.optional(),
1082
+ /** Privacy-enhanced: protects personal information */
1083
+ privacyEnhanced: TrustworthinessCharacteristicSchema.optional(),
1084
+ /** Fair: avoids bias and discrimination */
1085
+ fair: TrustworthinessCharacteristicSchema.optional()
1086
+ });
1087
+ var ClassificationSchema = import_zod.z.object({
1088
+ /** Primary AIGRC risk level */
1089
+ riskLevel: import_zod.z.enum(["minimal", "limited", "high", "unacceptable"]),
1090
+ /** Risk factors that influenced the classification */
1091
+ riskFactors: RiskFactorsSchema,
1092
+ /** EU AI Act specific classification (legacy, prefer jurisdictions) */
1093
+ euAiAct: import_zod.z.object({
1094
+ category: import_zod.z.string(),
1095
+ transparencyRequired: import_zod.z.boolean().default(false)
1096
+ }).optional(),
1097
+ /** Required artifacts based on classification */
1098
+ requiredArtifacts: import_zod.z.array(
1099
+ import_zod.z.object({
1100
+ type: import_zod.z.string(),
1101
+ status: import_zod.z.enum(["pending", "complete", "not_applicable"]),
1102
+ path: import_zod.z.string().optional()
1103
+ })
1104
+ ).optional(),
1105
+ /** Per-jurisdiction classifications for multi-jurisdiction compliance */
1106
+ jurisdictions: import_zod.z.array(JurisdictionClassificationSchema).optional(),
1107
+ /** NIST AI RMF trustworthiness characteristics */
1108
+ trustworthiness: TrustworthinessSchema.optional()
1109
+ });
1110
+ var IntentSchema = import_zod.z.object({
1111
+ linked: import_zod.z.boolean().default(false),
1112
+ ticketSystem: import_zod.z.enum(["jira", "ado", "github", "gitlab"]).nullable().optional(),
1113
+ ticketId: import_zod.z.string().nullable().optional(),
1114
+ ticketUrl: import_zod.z.string().url().nullable().optional(),
1115
+ businessJustification: import_zod.z.string().nullable().optional(),
1116
+ riskTolerance: import_zod.z.enum(["low", "medium", "high"]).nullable().optional(),
1117
+ importedAt: import_zod.z.string().datetime().nullable().optional()
1118
+ });
1119
+ var ApprovalSchema = import_zod.z.object({
1120
+ role: import_zod.z.string(),
1121
+ name: import_zod.z.string(),
1122
+ email: import_zod.z.string().email().optional(),
1123
+ date: import_zod.z.string(),
1124
+ source: import_zod.z.string().optional()
1125
+ });
1126
+ var GovernanceSchema = import_zod.z.object({
1127
+ status: import_zod.z.enum(["draft", "linked", "approved", "production", "deprecated", "revoked"]),
1128
+ approvals: import_zod.z.array(ApprovalSchema).default([]),
1129
+ deployment: import_zod.z.object({
1130
+ environments: import_zod.z.array(import_zod.z.string()).default([]),
1131
+ lastDeployed: import_zod.z.string().datetime().nullable().optional()
1132
+ }).optional()
1133
+ });
1134
+ var ConstraintsSchema = import_zod.z.object({
1135
+ runtime: import_zod.z.object({
1136
+ maxIterations: import_zod.z.number().positive().optional(),
1137
+ timeoutSeconds: import_zod.z.number().positive().optional(),
1138
+ maxTokensPerRequest: import_zod.z.number().positive().optional(),
1139
+ maxCostPerRequestUsd: import_zod.z.number().positive().optional()
1140
+ }).optional(),
1141
+ humanApprovalRequired: import_zod.z.array(import_zod.z.string()).optional(),
1142
+ monitoring: import_zod.z.object({
1143
+ logAllDecisions: import_zod.z.boolean().default(true),
1144
+ logToolInvocations: import_zod.z.boolean().default(true)
1145
+ }).optional()
1146
+ });
1147
+ var AssetCardSchema = import_zod.z.object({
1148
+ $schema: import_zod.z.string().optional(),
1149
+ id: import_zod.z.string().regex(/^aigrc-\d{4}-[a-f0-9]{8}$/),
1150
+ name: import_zod.z.string().min(1).max(100),
1151
+ description: import_zod.z.string().max(500).optional(),
1152
+ version: import_zod.z.string().default("1.0.0"),
1153
+ created: import_zod.z.string().datetime(),
1154
+ updated: import_zod.z.string().datetime(),
1155
+ ownership: import_zod.z.object({
1156
+ owner: OwnerSchema,
1157
+ team: import_zod.z.string().optional()
1158
+ }),
1159
+ technical: TechnicalSchema,
1160
+ classification: ClassificationSchema,
1161
+ intent: IntentSchema,
1162
+ governance: GovernanceSchema,
1163
+ constraints: ConstraintsSchema.optional()
1164
+ });
1165
+
1166
+ // src/classification.ts
1167
+ function classifyRisk(factors) {
1168
+ const reasons = [];
1169
+ let riskLevel = "minimal";
1170
+ if (factors.highStakesDecisions) {
1171
+ riskLevel = "high";
1172
+ reasons.push("Makes high-stakes decisions affecting individuals");
1173
+ }
1174
+ if (factors.autonomousDecisions && factors.toolExecution) {
1175
+ riskLevel = "high";
1176
+ reasons.push("Autonomous agent with tool execution capability");
1177
+ }
1178
+ if (factors.customerFacing && riskLevel === "minimal") {
1179
+ riskLevel = "limited";
1180
+ reasons.push("Customer-facing AI requires transparency");
1181
+ }
1182
+ if (factors.piiProcessing === "yes" && riskLevel === "minimal") {
1183
+ riskLevel = "limited";
1184
+ reasons.push("Processes personal data");
1185
+ }
1186
+ const euAiActCategory = mapToEuAiAct(riskLevel, factors);
1187
+ const requiredArtifacts = getRequiredArtifacts(riskLevel, factors);
1188
+ return {
1189
+ riskLevel,
1190
+ reasons,
1191
+ euAiActCategory,
1192
+ requiredArtifacts
1193
+ };
1194
+ }
1195
+ function mapToEuAiAct(level, factors) {
1196
+ if (level === "unacceptable") return "prohibited";
1197
+ if (level === "high") return "high_risk";
1198
+ if (level === "limited" || factors.customerFacing) return "limited_risk";
1199
+ return "minimal_risk";
1200
+ }
1201
+ function getRequiredArtifacts(level, factors) {
1202
+ const artifacts = ["ai_asset_card"];
1203
+ if (level === "limited" || level === "high") {
1204
+ if (factors.customerFacing) {
1205
+ artifacts.push("transparency_notice");
1206
+ }
1207
+ }
1208
+ if (level === "high") {
1209
+ artifacts.push("risk_assessment");
1210
+ artifacts.push("human_oversight_plan");
1211
+ if (factors.toolExecution) {
1212
+ artifacts.push("tool_inventory");
1213
+ }
1214
+ }
1215
+ return artifacts;
1216
+ }
1217
+ function validateRiskFactors(factors) {
1218
+ const requiredProperties = [
1219
+ "highStakesDecisions",
1220
+ "autonomousDecisions",
1221
+ "toolExecution",
1222
+ "customerFacing",
1223
+ "piiProcessing"
1224
+ ];
1225
+ for (const prop of requiredProperties) {
1226
+ if (!(prop in factors)) {
1227
+ console.error(`Missing required property: ${prop}`);
1228
+ return false;
1229
+ }
1230
+ }
1231
+ return true;
1232
+ }
1233
+
1234
+ // src/asset-card.ts
1235
+ var import_fs = require("fs");
1236
+ var import_path = require("path");
1237
+ var import_yaml = __toESM(require("yaml"));
1238
+ var import_crypto = require("crypto");
1239
+ function generateAssetId() {
1240
+ const year = (/* @__PURE__ */ new Date()).getFullYear();
1241
+ const random = (0, import_crypto.randomBytes)(4).toString("hex");
1242
+ return `aigrc-${year}-${random}`;
1243
+ }
1244
+ function createAssetCard(options) {
1245
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1246
+ const id = generateAssetId();
1247
+ const jurisdictions = options.jurisdictions && options.jurisdictions.length > 0 ? options.jurisdictions.map((jurisdictionId) => ({
1248
+ jurisdictionId,
1249
+ riskLevel: "minimal",
1250
+ // Will be updated by classify
1251
+ controlStatuses: [],
1252
+ requiredArtifacts: []
1253
+ })) : void 0;
1254
+ const card = {
1255
+ $schema: "https://aigrc.dev/schemas/asset-card/v1",
1256
+ id,
1257
+ name: options.name,
1258
+ description: options.description,
1259
+ version: "1.0.0",
1260
+ created: now,
1261
+ updated: now,
1262
+ ownership: {
1263
+ owner: options.owner,
1264
+ team: options.owner.team
1265
+ },
1266
+ technical: {
1267
+ type: options.technical.type,
1268
+ framework: options.technical.framework,
1269
+ frameworkVersion: options.technical.frameworkVersion
1270
+ },
1271
+ classification: {
1272
+ riskLevel: "minimal",
1273
+ riskFactors: {
1274
+ autonomousDecisions: options.riskFactors?.autonomousDecisions ?? false,
1275
+ customerFacing: options.riskFactors?.customerFacing ?? false,
1276
+ toolExecution: options.riskFactors?.toolExecution ?? false,
1277
+ externalDataAccess: options.riskFactors?.externalDataAccess ?? false,
1278
+ piiProcessing: options.riskFactors?.piiProcessing ?? "unknown",
1279
+ highStakesDecisions: options.riskFactors?.highStakesDecisions ?? false
1280
+ },
1281
+ jurisdictions,
1282
+ trustworthiness: options.trustworthiness
1283
+ },
1284
+ intent: {
1285
+ linked: false
1286
+ },
1287
+ governance: {
1288
+ status: "draft",
1289
+ approvals: []
1290
+ }
1291
+ };
1292
+ const result = AssetCardSchema.safeParse(card);
1293
+ if (!result.success) {
1294
+ throw new Error(`Invalid asset card: ${result.error.message}`);
1295
+ }
1296
+ return result.data;
1297
+ }
1298
+ function addJurisdiction(card, jurisdictionId, riskLevel) {
1299
+ const jurisdictions = card.classification.jurisdictions || [];
1300
+ const existing = jurisdictions.find((j) => j.jurisdictionId === jurisdictionId);
1301
+ if (existing) {
1302
+ if (riskLevel) {
1303
+ existing.riskLevel = riskLevel;
1304
+ }
1305
+ } else {
1306
+ jurisdictions.push({
1307
+ jurisdictionId,
1308
+ riskLevel: riskLevel || "minimal",
1309
+ controlStatuses: [],
1310
+ requiredArtifacts: []
1311
+ });
1312
+ }
1313
+ return {
1314
+ ...card,
1315
+ classification: {
1316
+ ...card.classification,
1317
+ jurisdictions
1318
+ }
1319
+ };
1320
+ }
1321
+ function updateJurisdictionCompliance(card, jurisdictionId, update) {
1322
+ const jurisdictions = card.classification.jurisdictions || [];
1323
+ const idx = jurisdictions.findIndex((j) => j.jurisdictionId === jurisdictionId);
1324
+ if (idx === -1) {
1325
+ jurisdictions.push({
1326
+ jurisdictionId,
1327
+ riskLevel: update.riskLevel || "minimal",
1328
+ ...update,
1329
+ lastChecked: (/* @__PURE__ */ new Date()).toISOString()
1330
+ });
1331
+ } else {
1332
+ jurisdictions[idx] = {
1333
+ ...jurisdictions[idx],
1334
+ ...update,
1335
+ lastChecked: (/* @__PURE__ */ new Date()).toISOString()
1336
+ };
1337
+ }
1338
+ return {
1339
+ ...card,
1340
+ classification: {
1341
+ ...card.classification,
1342
+ jurisdictions
1343
+ }
1344
+ };
1345
+ }
1346
+ function loadAssetCard(filePath) {
1347
+ if (!(0, import_fs.existsSync)(filePath)) {
1348
+ throw new Error(`Asset card not found: ${filePath}`);
1349
+ }
1350
+ const content = (0, import_fs.readFileSync)(filePath, "utf-8");
1351
+ const data = import_yaml.default.parse(content);
1352
+ const result = AssetCardSchema.safeParse(data);
1353
+ if (!result.success) {
1354
+ throw new Error(`Invalid asset card at ${filePath}: ${result.error.message}`);
1355
+ }
1356
+ return result.data;
1357
+ }
1358
+ function saveAssetCard(card, filePath) {
1359
+ const result = AssetCardSchema.safeParse(card);
1360
+ if (!result.success) {
1361
+ throw new Error(`Invalid asset card: ${result.error.message}`);
1362
+ }
1363
+ const dir = (0, import_path.dirname)(filePath);
1364
+ if (!(0, import_fs.existsSync)(dir)) {
1365
+ (0, import_fs.mkdirSync)(dir, { recursive: true });
1366
+ }
1367
+ card.updated = (/* @__PURE__ */ new Date()).toISOString();
1368
+ const content = import_yaml.default.stringify(card, { indent: 2, lineWidth: 100 });
1369
+ (0, import_fs.writeFileSync)(filePath, content, "utf-8");
1370
+ }
1371
+ function validateAssetCard(card) {
1372
+ const result = AssetCardSchema.safeParse(card);
1373
+ if (result.success) {
1374
+ return { valid: true };
1375
+ }
1376
+ return {
1377
+ valid: false,
1378
+ errors: result.error.errors.map((e) => `${e.path.join(".")}: ${e.message}`)
1379
+ };
1380
+ }
1381
+
1382
+ // src/golden-thread.ts
1383
+ function linkAssetToTicket(asset, ticket) {
1384
+ const warnings = [];
1385
+ const intent = {
1386
+ linked: true,
1387
+ ticketSystem: ticket.system,
1388
+ ticketId: ticket.id,
1389
+ ticketUrl: ticket.url,
1390
+ businessJustification: ticket.businessJustification,
1391
+ riskTolerance: ticket.riskTolerance,
1392
+ importedAt: (/* @__PURE__ */ new Date()).toISOString()
1393
+ };
1394
+ if (ticket.riskTolerance && asset.classification.riskLevel) {
1395
+ const toleranceMap = { low: 0, medium: 1, high: 2 };
1396
+ const levelMap = { minimal: 0, limited: 1, high: 2, unacceptable: 3 };
1397
+ if (levelMap[asset.classification.riskLevel] > toleranceMap[ticket.riskTolerance]) {
1398
+ warnings.push(
1399
+ `Asset risk (${asset.classification.riskLevel}) exceeds ticket tolerance (${ticket.riskTolerance})`
1400
+ );
1401
+ }
1402
+ }
1403
+ return {
1404
+ success: true,
1405
+ intent,
1406
+ warnings: warnings.length > 0 ? warnings : void 0
1407
+ };
1408
+ }
1409
+ function validateGoldenThread(asset) {
1410
+ const issues = [];
1411
+ let score = 100;
1412
+ if (!asset.intent.linked) {
1413
+ issues.push("Asset is not linked to any ticket");
1414
+ score -= 50;
1415
+ return { valid: false, healthScore: score, issues };
1416
+ }
1417
+ if (!asset.intent.businessJustification) {
1418
+ issues.push("Missing business justification");
1419
+ score -= 20;
1420
+ }
1421
+ if (asset.classification.riskLevel === "high" && asset.governance.approvals.length === 0) {
1422
+ issues.push("High-risk asset missing approvals");
1423
+ score -= 30;
1424
+ }
1425
+ return {
1426
+ valid: issues.length === 0,
1427
+ healthScore: Math.max(0, score),
1428
+ issues
1429
+ };
1430
+ }
1431
+
1432
+ // src/detection/types.ts
1433
+ var import_zod2 = require("zod");
1434
+ var ConfidenceLevelSchema = import_zod2.z.enum(["high", "medium", "low"]);
1435
+ var DetectionStrategySchema = import_zod2.z.enum([
1436
+ "pattern_match",
1437
+ "import_analysis",
1438
+ "file_extension",
1439
+ "annotation"
1440
+ ]);
1441
+ var FrameworkCategorySchema = import_zod2.z.enum([
1442
+ "llm_provider",
1443
+ "framework",
1444
+ "agent_framework",
1445
+ "ml_framework",
1446
+ "ml_ops",
1447
+ "model_file"
1448
+ ]);
1449
+
1450
+ // src/detection/scanner.ts
1451
+ var import_fs2 = require("fs");
1452
+ var import_path3 = require("path");
1453
+
1454
+ // src/detection/patterns/index.ts
1455
+ init_registry();
1456
+ init_python();
1457
+ init_javascript();
1458
+ init_model_files();
1459
+ init_risk_indicators();
1460
+ var initialized = false;
1461
+ function initializePatterns() {
1462
+ if (initialized) {
1463
+ return;
1464
+ }
1465
+ const { registerPythonPatterns: registerPythonPatterns2 } = (init_python(), __toCommonJS(python_exports));
1466
+ const { registerJavaScriptPatterns: registerJavaScriptPatterns2 } = (init_javascript(), __toCommonJS(javascript_exports));
1467
+ const { registerModelFilePatterns: registerModelFilePatterns2 } = (init_model_files(), __toCommonJS(model_files_exports));
1468
+ const { registerRiskIndicatorPatterns: registerRiskIndicatorPatterns2 } = (init_risk_indicators(), __toCommonJS(risk_indicators_exports));
1469
+ registerPythonPatterns2();
1470
+ registerJavaScriptPatterns2();
1471
+ registerModelFilePatterns2();
1472
+ registerRiskIndicatorPatterns2();
1473
+ initialized = true;
1474
+ }
1475
+ function resetPatterns() {
1476
+ const { clearRegistry: clearRegistry2 } = (init_registry(), __toCommonJS(registry_exports));
1477
+ clearRegistry2();
1478
+ initialized = false;
1479
+ }
1480
+
1481
+ // src/detection/strategies/pattern-matcher.ts
1482
+ function matchPatterns(filePath, lines, patterns) {
1483
+ const detections = [];
1484
+ for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
1485
+ const line = lines[lineIndex];
1486
+ for (const pattern of patterns) {
1487
+ for (const rule of pattern.patterns) {
1488
+ if (rule.type !== "regex" && rule.type !== "literal") continue;
1489
+ const match = matchRule(line, rule);
1490
+ if (match) {
1491
+ detections.push({
1492
+ filePath,
1493
+ line: lineIndex + 1,
1494
+ column: match.index,
1495
+ match: match.text,
1496
+ matchContext: getContext(lines, lineIndex),
1497
+ registryCard: pattern.id,
1498
+ framework: pattern.name,
1499
+ category: pattern.category,
1500
+ confidence: rule.confidence,
1501
+ strategy: "pattern_match",
1502
+ implies: pattern.implies
1503
+ });
1504
+ }
1505
+ }
1506
+ }
1507
+ }
1508
+ return detections;
1509
+ }
1510
+ function matchRule(line, rule) {
1511
+ if (rule.type === "literal") {
1512
+ const index = line.indexOf(rule.pattern);
1513
+ if (index !== -1) {
1514
+ return { text: rule.pattern, index };
1515
+ }
1516
+ } else if (rule.type === "regex") {
1517
+ try {
1518
+ const regex = new RegExp(rule.pattern, "i");
1519
+ const match = regex.exec(line);
1520
+ if (match) {
1521
+ return { text: match[0], index: match.index };
1522
+ }
1523
+ } catch {
1524
+ }
1525
+ }
1526
+ return null;
1527
+ }
1528
+ function getContext(lines, index, contextLines = 2) {
1529
+ const start = Math.max(0, index - contextLines);
1530
+ const end = Math.min(lines.length, index + contextLines + 1);
1531
+ return lines.slice(start, end).join("\n");
1532
+ }
1533
+
1534
+ // src/detection/strategies/import-analyzer.ts
1535
+ var PYTHON_IMPORT_REGEX = /^(?:from\s+(\S+)\s+import|import\s+(\S+))/;
1536
+ var JS_IMPORT_REGEX = /(?:import\s+(?:[\w{},*\s]+\s+from\s+)?['"]([^'"]+)['"]|require\s*\(\s*['"]([^'"]+)['"]\s*\))/;
1537
+ function analyzeImports(filePath, content, patterns) {
1538
+ const detections = [];
1539
+ const lines = content.split("\n");
1540
+ const isPython = filePath.endsWith(".py");
1541
+ for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
1542
+ const line = lines[lineIndex].trim();
1543
+ if (!line) continue;
1544
+ if (isPython && line.startsWith("#")) continue;
1545
+ if (!isPython && (line.startsWith("//") || line.startsWith("/*"))) continue;
1546
+ const importMatch = isPython ? extractPythonImport(line) : extractJsImport(line);
1547
+ if (!importMatch) continue;
1548
+ for (const pattern of patterns) {
1549
+ if (pattern.language !== "any" && (isPython && pattern.language !== "python" || !isPython && pattern.language !== "javascript" && pattern.language !== "typescript")) {
1550
+ continue;
1551
+ }
1552
+ for (const rule of pattern.patterns) {
1553
+ if (rule.type !== "import") continue;
1554
+ if (matchesImport(line, rule.pattern)) {
1555
+ detections.push({
1556
+ filePath,
1557
+ line: lineIndex + 1,
1558
+ match: line,
1559
+ registryCard: pattern.id,
1560
+ framework: pattern.name,
1561
+ category: pattern.category,
1562
+ confidence: rule.confidence,
1563
+ strategy: "import_analysis",
1564
+ implies: pattern.implies,
1565
+ metadata: { importedModule: importMatch }
1566
+ });
1567
+ }
1568
+ }
1569
+ }
1570
+ }
1571
+ return detections;
1572
+ }
1573
+ function extractPythonImport(line) {
1574
+ const match = PYTHON_IMPORT_REGEX.exec(line);
1575
+ if (match) {
1576
+ return match[1] || match[2];
1577
+ }
1578
+ return null;
1579
+ }
1580
+ function extractJsImport(line) {
1581
+ const match = JS_IMPORT_REGEX.exec(line);
1582
+ if (match) {
1583
+ return match[1] || match[2];
1584
+ }
1585
+ return null;
1586
+ }
1587
+ function matchesImport(line, pattern) {
1588
+ const normalizedLine = line.toLowerCase().replace(/'/g, '"');
1589
+ const normalizedPattern = pattern.toLowerCase().replace(/'/g, '"');
1590
+ return normalizedLine.includes(normalizedPattern);
1591
+ }
1592
+
1593
+ // src/detection/strategies/file-scanner.ts
1594
+ var import_path2 = require("path");
1595
+ init_registry();
1596
+ function scanFileExtension(filePath) {
1597
+ const detections = [];
1598
+ const ext = (0, import_path2.extname)(filePath).toLowerCase();
1599
+ const filename = (0, import_path2.basename)(filePath);
1600
+ const modelPatterns = getPatternsByCategory("model_file");
1601
+ for (const pattern of modelPatterns) {
1602
+ for (const rule of pattern.patterns) {
1603
+ let matched = false;
1604
+ if (rule.type === "literal") {
1605
+ if (ext === rule.pattern.toLowerCase()) {
1606
+ matched = true;
1607
+ }
1608
+ } else if (rule.type === "regex") {
1609
+ try {
1610
+ const regex = new RegExp(rule.pattern, "i");
1611
+ matched = regex.test(filename);
1612
+ } catch {
1613
+ }
1614
+ }
1615
+ if (matched) {
1616
+ detections.push({
1617
+ filePath,
1618
+ line: 0,
1619
+ // N/A for file-level detection
1620
+ match: filename,
1621
+ registryCard: pattern.id,
1622
+ framework: pattern.name,
1623
+ category: pattern.category,
1624
+ confidence: rule.confidence,
1625
+ strategy: "file_extension",
1626
+ implies: pattern.implies,
1627
+ metadata: { extension: ext, filename }
1628
+ });
1629
+ }
1630
+ }
1631
+ }
1632
+ return detections;
1633
+ }
1634
+ var MODEL_EXTENSIONS = [
1635
+ ".pt",
1636
+ ".pth",
1637
+ ".safetensors",
1638
+ ".onnx",
1639
+ ".h5",
1640
+ ".keras",
1641
+ ".pb",
1642
+ ".pkl",
1643
+ ".joblib",
1644
+ ".bin",
1645
+ ".gguf",
1646
+ ".ggml",
1647
+ ".npz"
1648
+ ];
1649
+ function isModelFile(filePath) {
1650
+ const ext = (0, import_path2.extname)(filePath).toLowerCase();
1651
+ return MODEL_EXTENSIONS.includes(ext);
1652
+ }
1653
+
1654
+ // src/detection/strategies/annotation-detector.ts
1655
+ var PYTHON_DECORATOR_REGEX = /^\s*@(\w+)(?:\(.*\))?\s*$/;
1656
+ var TS_DECORATOR_REGEX = /^\s*@(\w+)(?:\(.*\))?\s*$/;
1657
+ function detectAnnotations(filePath, lines, patterns) {
1658
+ const detections = [];
1659
+ const isPython = filePath.endsWith(".py");
1660
+ for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
1661
+ const line = lines[lineIndex];
1662
+ const trimmedLine = line.trim();
1663
+ if (!trimmedLine.startsWith("@")) continue;
1664
+ const decoratorMatch = isPython ? PYTHON_DECORATOR_REGEX.exec(trimmedLine) : TS_DECORATOR_REGEX.exec(trimmedLine);
1665
+ if (!decoratorMatch) continue;
1666
+ const decoratorName = decoratorMatch[1];
1667
+ for (const pattern of patterns) {
1668
+ if (pattern.language !== "any" && (isPython && pattern.language !== "python" || !isPython && pattern.language !== "javascript" && pattern.language !== "typescript")) {
1669
+ continue;
1670
+ }
1671
+ for (const rule of pattern.patterns) {
1672
+ if (rule.type !== "decorator") continue;
1673
+ const ruleDecorator = rule.pattern.replace(/^@/, "");
1674
+ if (decoratorName.toLowerCase() === ruleDecorator.toLowerCase()) {
1675
+ const nextLine = lineIndex + 1 < lines.length ? lines[lineIndex + 1] : "";
1676
+ const decoratedName = extractDecoratedName(nextLine, isPython);
1677
+ detections.push({
1678
+ filePath,
1679
+ line: lineIndex + 1,
1680
+ match: trimmedLine,
1681
+ matchContext: decoratedName ? `${trimmedLine}
1682
+ ${nextLine.trim()}` : trimmedLine,
1683
+ registryCard: pattern.id,
1684
+ framework: pattern.name,
1685
+ category: pattern.category,
1686
+ confidence: rule.confidence,
1687
+ strategy: "annotation",
1688
+ implies: pattern.implies,
1689
+ metadata: {
1690
+ decorator: decoratorName,
1691
+ decorated: decoratedName
1692
+ }
1693
+ });
1694
+ }
1695
+ }
1696
+ }
1697
+ }
1698
+ return detections;
1699
+ }
1700
+ function extractDecoratedName(line, isPython) {
1701
+ if (isPython) {
1702
+ const pythonMatch = /(?:def|class|async\s+def)\s+(\w+)/.exec(line);
1703
+ if (pythonMatch) return pythonMatch[1];
1704
+ } else {
1705
+ const tsMatch = /(?:function|class|async\s+function)\s+(\w+)/.exec(line);
1706
+ if (tsMatch) return tsMatch[1];
1707
+ const methodMatch = /^\s*(?:async\s+)?(\w+)\s*\(/.exec(line);
1708
+ if (methodMatch) return methodMatch[1];
1709
+ }
1710
+ return null;
1711
+ }
1712
+
1713
+ // src/detection/risk-inference.ts
1714
+ function inferRiskFactors(detections) {
1715
+ const implications = collectImplications(detections);
1716
+ return {
1717
+ autonomousDecisions: inferBoolean(implications, "autonomousDecisions"),
1718
+ customerFacing: inferBoolean(implications, "customerFacing"),
1719
+ toolExecution: inferBoolean(implications, "toolExecution"),
1720
+ externalDataAccess: inferBoolean(implications, "externalDataAccess"),
1721
+ piiProcessing: inferPiiProcessing(implications),
1722
+ highStakesDecisions: inferBoolean(implications, "highStakesDecisions")
1723
+ };
1724
+ }
1725
+ function collectImplications(detections) {
1726
+ const implications = [];
1727
+ for (const detection of detections) {
1728
+ const weight = confidenceWeight(detection.confidence);
1729
+ for (const implication of detection.implies) {
1730
+ if (weight >= 2) {
1731
+ implications.push({
1732
+ ...implication,
1733
+ weight
1734
+ });
1735
+ }
1736
+ }
1737
+ }
1738
+ return implications;
1739
+ }
1740
+ function confidenceWeight(confidence) {
1741
+ const weights = {
1742
+ high: 3,
1743
+ medium: 2,
1744
+ low: 1
1745
+ };
1746
+ return weights[confidence];
1747
+ }
1748
+ function inferBoolean(implications, factor) {
1749
+ const relevant = implications.filter((i) => i.factor === factor);
1750
+ if (relevant.length === 0) return false;
1751
+ const highWeight = relevant.filter((i) => i.weight >= 3 && i.value === true);
1752
+ if (highWeight.length > 0) return true;
1753
+ const mediumWeight = relevant.filter((i) => i.weight >= 2 && i.value === true);
1754
+ if (mediumWeight.length >= 2) return true;
1755
+ if (mediumWeight.length >= 1) return true;
1756
+ return false;
1757
+ }
1758
+ function inferPiiProcessing(implications) {
1759
+ const relevant = implications.filter((i) => i.factor === "piiProcessing");
1760
+ if (relevant.length === 0) return "unknown";
1761
+ const highYes = relevant.filter((i) => i.weight >= 3 && i.value === "yes");
1762
+ if (highYes.length > 0) return "yes";
1763
+ const mediumYes = relevant.filter((i) => i.weight >= 2 && i.value === "yes");
1764
+ if (mediumYes.length >= 2) return "yes";
1765
+ if (relevant.some((i) => i.value === "yes")) return "yes";
1766
+ if (relevant.every((i) => i.value === "no")) return "no";
1767
+ return "unknown";
1768
+ }
1769
+ var IMPLICATION_CHAINS = {
1770
+ // LangChain implies tool execution and external data access
1771
+ "langchain-python": [
1772
+ { factor: "toolExecution", value: true, reason: "LangChain enables tool calling" },
1773
+ { factor: "externalDataAccess", value: true, reason: "LangChain chains access external data" }
1774
+ ],
1775
+ "langchain-js": [
1776
+ { factor: "toolExecution", value: true, reason: "LangChain.js enables tool calling" },
1777
+ { factor: "externalDataAccess", value: true, reason: "LangChain.js chains access external data" }
1778
+ ],
1779
+ // CrewAI implies autonomous decisions and tool execution
1780
+ crewai: [
1781
+ { factor: "autonomousDecisions", value: true, reason: "CrewAI enables autonomous agents" },
1782
+ { factor: "toolExecution", value: true, reason: "CrewAI agents execute tools" }
1783
+ ],
1784
+ // AutoGen implies autonomous decisions and tool execution
1785
+ autogen: [
1786
+ { factor: "autonomousDecisions", value: true, reason: "AutoGen enables autonomous agents" },
1787
+ { factor: "toolExecution", value: true, reason: "AutoGen agents can execute code" }
1788
+ ],
1789
+ // LangGraph implies autonomous decisions
1790
+ langgraph: [
1791
+ { factor: "autonomousDecisions", value: true, reason: "LangGraph enables stateful agents" }
1792
+ ],
1793
+ "langgraph-js": [
1794
+ { factor: "autonomousDecisions", value: true, reason: "LangGraph.js enables stateful agents" }
1795
+ ],
1796
+ // Vercel AI SDK implies customer-facing
1797
+ "vercel-ai-sdk": [
1798
+ { factor: "customerFacing", value: true, reason: "Vercel AI SDK used in user-facing apps" }
1799
+ ]
1800
+ };
1801
+ function applyImplicationChains(detections) {
1802
+ return detections.map((detection) => {
1803
+ const chainedImplications = IMPLICATION_CHAINS[detection.registryCard];
1804
+ if (chainedImplications) {
1805
+ return {
1806
+ ...detection,
1807
+ implies: [...detection.implies, ...chainedImplications]
1808
+ };
1809
+ }
1810
+ return detection;
1811
+ });
1812
+ }
1813
+
1814
+ // src/detection/scanner.ts
1815
+ var DEFAULT_IGNORE_PATTERNS = [
1816
+ "node_modules",
1817
+ "__pycache__",
1818
+ ".git",
1819
+ "dist",
1820
+ "build",
1821
+ ".next",
1822
+ ".nuxt",
1823
+ "venv",
1824
+ ".venv",
1825
+ "env",
1826
+ ".env",
1827
+ ".aigrc",
1828
+ "*.min.js",
1829
+ "*.bundle.js",
1830
+ "*.map",
1831
+ "coverage",
1832
+ ".pytest_cache",
1833
+ ".mypy_cache",
1834
+ ".tox",
1835
+ "egg-info"
1836
+ ];
1837
+ var DEFAULT_CODE_EXTENSIONS = [
1838
+ ".py",
1839
+ ".js",
1840
+ ".ts",
1841
+ ".jsx",
1842
+ ".tsx",
1843
+ ".mjs",
1844
+ ".cjs"
1845
+ ];
1846
+ async function scan(options, onProgress) {
1847
+ const startTime = Date.now();
1848
+ const detections = [];
1849
+ const errors = [];
1850
+ let scannedFiles = 0;
1851
+ let skippedFiles = 0;
1852
+ if (!isRegistryInitialized()) {
1853
+ initializePatterns();
1854
+ }
1855
+ const resolvedOptions = resolveOptions(options);
1856
+ const files = collectFiles(resolvedOptions);
1857
+ const totalFiles = files.length;
1858
+ for (const filePath of files) {
1859
+ if (resolvedOptions.maxFiles && scannedFiles >= resolvedOptions.maxFiles) {
1860
+ break;
1861
+ }
1862
+ if (onProgress) {
1863
+ onProgress({
1864
+ totalFiles,
1865
+ scannedFiles,
1866
+ currentFile: (0, import_path3.relative)(resolvedOptions.directory, filePath),
1867
+ detections: detections.length
1868
+ });
1869
+ }
1870
+ try {
1871
+ const fileDetections = await scanFile(filePath, resolvedOptions);
1872
+ detections.push(...fileDetections);
1873
+ scannedFiles++;
1874
+ if (resolvedOptions.earlyExit && fileDetections.some((d) => d.confidence === "high")) {
1875
+ break;
1876
+ }
1877
+ } catch (error) {
1878
+ errors.push({
1879
+ filePath,
1880
+ error: error instanceof Error ? error.message : String(error),
1881
+ recoverable: true
1882
+ });
1883
+ skippedFiles++;
1884
+ }
1885
+ }
1886
+ const uniqueDetections = deduplicateDetections(detections);
1887
+ const summary = createSummary(uniqueDetections);
1888
+ const inferredRiskFactors = inferRiskFactors(uniqueDetections);
1889
+ const suggestedTechnical = suggestTechnical(uniqueDetections, summary);
1890
+ return {
1891
+ detections: uniqueDetections,
1892
+ summary,
1893
+ inferredRiskFactors,
1894
+ suggestedTechnical,
1895
+ scannedFiles,
1896
+ skippedFiles,
1897
+ duration: Date.now() - startTime,
1898
+ errors: errors.length > 0 ? errors : void 0
1899
+ };
1900
+ }
1901
+ function scanSync(options, onProgress) {
1902
+ const startTime = Date.now();
1903
+ const detections = [];
1904
+ const errors = [];
1905
+ let scannedFiles = 0;
1906
+ let skippedFiles = 0;
1907
+ if (!isRegistryInitialized()) {
1908
+ initializePatterns();
1909
+ }
1910
+ const resolvedOptions = resolveOptions(options);
1911
+ const files = collectFiles(resolvedOptions);
1912
+ const totalFiles = files.length;
1913
+ for (const filePath of files) {
1914
+ if (resolvedOptions.maxFiles && scannedFiles >= resolvedOptions.maxFiles) {
1915
+ break;
1916
+ }
1917
+ if (onProgress) {
1918
+ onProgress({
1919
+ totalFiles,
1920
+ scannedFiles,
1921
+ currentFile: (0, import_path3.relative)(resolvedOptions.directory, filePath),
1922
+ detections: detections.length
1923
+ });
1924
+ }
1925
+ try {
1926
+ const fileDetections = scanFileSync(filePath, resolvedOptions);
1927
+ detections.push(...fileDetections);
1928
+ scannedFiles++;
1929
+ if (resolvedOptions.earlyExit && fileDetections.some((d) => d.confidence === "high")) {
1930
+ break;
1931
+ }
1932
+ } catch (error) {
1933
+ errors.push({
1934
+ filePath,
1935
+ error: error instanceof Error ? error.message : String(error),
1936
+ recoverable: true
1937
+ });
1938
+ skippedFiles++;
1939
+ }
1940
+ }
1941
+ const uniqueDetections = deduplicateDetections(detections);
1942
+ const summary = createSummary(uniqueDetections);
1943
+ const inferredRiskFactors = inferRiskFactors(uniqueDetections);
1944
+ const suggestedTechnical = suggestTechnical(uniqueDetections, summary);
1945
+ return {
1946
+ detections: uniqueDetections,
1947
+ summary,
1948
+ inferredRiskFactors,
1949
+ suggestedTechnical,
1950
+ scannedFiles,
1951
+ skippedFiles,
1952
+ duration: Date.now() - startTime,
1953
+ errors: errors.length > 0 ? errors : void 0
1954
+ };
1955
+ }
1956
+ function resolveOptions(options) {
1957
+ return {
1958
+ directory: options.directory,
1959
+ recursive: options.recursive ?? true,
1960
+ extensions: options.extensions ?? [...DEFAULT_CODE_EXTENSIONS, ...MODEL_EXTENSIONS],
1961
+ ignorePatterns: options.ignorePatterns ?? DEFAULT_IGNORE_PATTERNS,
1962
+ strategies: options.strategies ?? [
1963
+ "pattern_match",
1964
+ "import_analysis",
1965
+ "file_extension",
1966
+ "annotation"
1967
+ ],
1968
+ maxFileSize: options.maxFileSize ?? 1024 * 1024,
1969
+ // 1MB default
1970
+ maxFiles: options.maxFiles ?? 1e4,
1971
+ earlyExit: options.earlyExit ?? false,
1972
+ respectGitignore: options.respectGitignore ?? true,
1973
+ customPatterns: options.customPatterns ?? []
1974
+ };
1975
+ }
1976
+ function collectFiles(options) {
1977
+ const files = [];
1978
+ const gitignorePatterns = options.respectGitignore ? loadGitignore(options.directory) : [];
1979
+ function walk(dir) {
1980
+ let entries;
1981
+ try {
1982
+ entries = (0, import_fs2.readdirSync)(dir, { withFileTypes: true });
1983
+ } catch {
1984
+ return;
1985
+ }
1986
+ for (const entry of entries) {
1987
+ const fullPath = (0, import_path3.join)(dir, entry.name);
1988
+ const relativePath = (0, import_path3.relative)(options.directory, fullPath);
1989
+ if (shouldIgnore(relativePath, entry.name, options.ignorePatterns, gitignorePatterns)) {
1990
+ continue;
1991
+ }
1992
+ if (entry.isDirectory() && options.recursive) {
1993
+ walk(fullPath);
1994
+ } else if (entry.isFile()) {
1995
+ const ext = (0, import_path3.extname)(entry.name).toLowerCase();
1996
+ if (options.extensions.some((e) => e.toLowerCase() === ext)) {
1997
+ try {
1998
+ const stats = (0, import_fs2.statSync)(fullPath);
1999
+ if (stats.size <= options.maxFileSize) {
2000
+ files.push(fullPath);
2001
+ }
2002
+ } catch {
2003
+ }
2004
+ }
2005
+ }
2006
+ }
2007
+ }
2008
+ if ((0, import_fs2.existsSync)(options.directory)) {
2009
+ const stat = (0, import_fs2.statSync)(options.directory);
2010
+ if (stat.isDirectory()) {
2011
+ walk(options.directory);
2012
+ } else if (stat.isFile()) {
2013
+ files.push(options.directory);
2014
+ }
2015
+ }
2016
+ return files;
2017
+ }
2018
+ function shouldIgnore(relativePath, name, ignorePatterns, gitignorePatterns) {
2019
+ const allPatterns = [...ignorePatterns, ...gitignorePatterns];
2020
+ for (const pattern of allPatterns) {
2021
+ if (name === pattern || relativePath === pattern) {
2022
+ return true;
2023
+ }
2024
+ if (relativePath.includes(pattern)) {
2025
+ return true;
2026
+ }
2027
+ if (pattern.includes("*")) {
2028
+ const regexPattern = pattern.replace(/\./g, "\\.").replace(/\*/g, ".*");
2029
+ try {
2030
+ const regex = new RegExp(regexPattern);
2031
+ if (regex.test(name) || regex.test(relativePath)) {
2032
+ return true;
2033
+ }
2034
+ } catch {
2035
+ }
2036
+ }
2037
+ }
2038
+ return false;
2039
+ }
2040
+ function loadGitignore(directory) {
2041
+ const gitignorePath = (0, import_path3.join)(directory, ".gitignore");
2042
+ if (!(0, import_fs2.existsSync)(gitignorePath)) {
2043
+ return [];
2044
+ }
2045
+ try {
2046
+ const content = (0, import_fs2.readFileSync)(gitignorePath, "utf-8");
2047
+ return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
2048
+ } catch {
2049
+ return [];
2050
+ }
2051
+ }
2052
+ async function scanFile(filePath, options) {
2053
+ return scanFileSync(filePath, options);
2054
+ }
2055
+ function scanFileSync(filePath, options) {
2056
+ const detections = [];
2057
+ const ext = (0, import_path3.extname)(filePath).toLowerCase();
2058
+ const patterns = [...getAllPatterns(), ...options.customPatterns ?? []];
2059
+ if (options.strategies.includes("file_extension") && MODEL_EXTENSIONS.some((e) => e.toLowerCase() === ext)) {
2060
+ const extensionDetections = scanFileExtension(filePath);
2061
+ detections.push(...extensionDetections);
2062
+ }
2063
+ if (DEFAULT_CODE_EXTENSIONS.some((e) => e.toLowerCase() === ext)) {
2064
+ const content = (0, import_fs2.readFileSync)(filePath, "utf-8");
2065
+ const lines = content.split("\n");
2066
+ if (options.strategies.includes("import_analysis")) {
2067
+ const importDetections = analyzeImports(filePath, content, patterns);
2068
+ detections.push(...importDetections);
2069
+ }
2070
+ if (options.strategies.includes("pattern_match")) {
2071
+ const patternDetections = matchPatterns(filePath, lines, patterns);
2072
+ detections.push(...patternDetections);
2073
+ }
2074
+ if (options.strategies.includes("annotation")) {
2075
+ const annotationDetections = detectAnnotations(filePath, lines, patterns);
2076
+ detections.push(...annotationDetections);
2077
+ }
2078
+ }
2079
+ return detections;
2080
+ }
2081
+ function deduplicateDetections(detections) {
2082
+ const seen = /* @__PURE__ */ new Map();
2083
+ for (const detection of detections) {
2084
+ const key = `${detection.filePath}:${detection.line}:${detection.registryCard}`;
2085
+ const existing = seen.get(key);
2086
+ if (!existing || confidenceRank(detection.confidence) > confidenceRank(existing.confidence)) {
2087
+ seen.set(key, detection);
2088
+ }
2089
+ }
2090
+ return Array.from(seen.values());
2091
+ }
2092
+ function confidenceRank(level) {
2093
+ const ranks = { high: 3, medium: 2, low: 1 };
2094
+ return ranks[level];
2095
+ }
2096
+ function createSummary(detections) {
2097
+ const byFramework = {};
2098
+ const byCategory = {
2099
+ llm_provider: 0,
2100
+ framework: 0,
2101
+ agent_framework: 0,
2102
+ ml_framework: 0,
2103
+ ml_ops: 0,
2104
+ model_file: 0
2105
+ };
2106
+ const byConfidence = {
2107
+ high: 0,
2108
+ medium: 0,
2109
+ low: 0
2110
+ };
2111
+ for (const detection of detections) {
2112
+ byFramework[detection.framework] = (byFramework[detection.framework] || 0) + 1;
2113
+ byCategory[detection.category]++;
2114
+ byConfidence[detection.confidence]++;
2115
+ }
2116
+ let primaryFramework;
2117
+ let maxScore = 0;
2118
+ for (const [framework] of Object.entries(byFramework)) {
2119
+ const frameworkDetections = detections.filter((d) => d.framework === framework);
2120
+ const score = frameworkDetections.reduce(
2121
+ (sum, d) => sum + confidenceRank(d.confidence),
2122
+ 0
2123
+ );
2124
+ if (score > maxScore) {
2125
+ maxScore = score;
2126
+ primaryFramework = framework;
2127
+ }
2128
+ }
2129
+ let primaryCategory;
2130
+ let maxCategoryCount = 0;
2131
+ for (const [cat, count] of Object.entries(byCategory)) {
2132
+ if (count > maxCategoryCount) {
2133
+ maxCategoryCount = count;
2134
+ primaryCategory = cat;
2135
+ }
2136
+ }
2137
+ return {
2138
+ totalDetections: detections.length,
2139
+ byFramework,
2140
+ byCategory,
2141
+ byConfidence,
2142
+ primaryFramework,
2143
+ primaryCategory
2144
+ };
2145
+ }
2146
+ function suggestTechnical(detections, summary) {
2147
+ const typeMap = {
2148
+ llm_provider: "api_client",
2149
+ framework: "framework",
2150
+ agent_framework: "agent",
2151
+ ml_framework: "model",
2152
+ ml_ops: "pipeline",
2153
+ model_file: "model"
2154
+ };
2155
+ const sourceFiles = [...new Set(detections.map((d) => d.filePath))];
2156
+ return {
2157
+ type: typeMap[summary.primaryCategory ?? "framework"],
2158
+ framework: summary.primaryFramework,
2159
+ sourceFiles
2160
+ };
2161
+ }
2162
+
2163
+ // src/detection/asset-suggestion.ts
2164
+ function suggestAssetCard(scanResult) {
2165
+ const { detections, summary, inferredRiskFactors, suggestedTechnical } = scanResult;
2166
+ const name = generateName(summary.primaryFramework, suggestedTechnical?.type);
2167
+ const description = generateDescription(detections, summary);
2168
+ const components = collectComponents(detections);
2169
+ const sourceFiles = [...new Set(detections.map((d) => d.filePath))];
2170
+ const confidence = calculateOverallConfidence(detections);
2171
+ const basedOn = [...new Set(detections.map((d) => d.registryCard))];
2172
+ return {
2173
+ name,
2174
+ description,
2175
+ technical: {
2176
+ type: suggestedTechnical?.type ?? "framework",
2177
+ framework: suggestedTechnical?.framework ?? summary.primaryFramework ?? "unknown",
2178
+ components,
2179
+ sourceFiles
2180
+ },
2181
+ riskFactors: inferredRiskFactors,
2182
+ confidence,
2183
+ basedOn
2184
+ };
2185
+ }
2186
+ function generateName(primaryFramework, type) {
2187
+ if (!primaryFramework) {
2188
+ return "AI Asset";
2189
+ }
2190
+ const typeLabel = {
2191
+ model: "Model",
2192
+ agent: "Agent",
2193
+ api_client: "Integration",
2194
+ framework: "Application",
2195
+ pipeline: "Pipeline"
2196
+ };
2197
+ return `${primaryFramework} ${typeLabel[type ?? "framework"]}`;
2198
+ }
2199
+ function generateDescription(detections, summary) {
2200
+ const frameworks = Object.keys(summary.byFramework);
2201
+ const parts = [];
2202
+ if (frameworks.length === 1) {
2203
+ parts.push(`AI asset using ${frameworks[0]}.`);
2204
+ } else if (frameworks.length > 1) {
2205
+ parts.push(`AI asset using ${frameworks.slice(0, 3).join(", ")}${frameworks.length > 3 ? ` and ${frameworks.length - 3} more` : ""}.`);
2206
+ } else {
2207
+ parts.push("AI asset detected in codebase.");
2208
+ }
2209
+ const categories = summary.byCategory;
2210
+ if (categories.agent_framework > 0) {
2211
+ parts.push("Includes autonomous agent capabilities.");
2212
+ }
2213
+ if (categories.llm_provider > 0) {
2214
+ parts.push("Integrates with LLM providers.");
2215
+ }
2216
+ if (categories.ml_framework > 0) {
2217
+ parts.push("Uses machine learning frameworks.");
2218
+ }
2219
+ if (categories.model_file > 0) {
2220
+ parts.push("Contains model files.");
2221
+ }
2222
+ return parts.join(" ");
2223
+ }
2224
+ function collectComponents(detections) {
2225
+ const components = [];
2226
+ const seen = /* @__PURE__ */ new Set();
2227
+ for (const detection of detections) {
2228
+ const key = `${detection.category}-${detection.framework}`;
2229
+ if (seen.has(key)) continue;
2230
+ seen.add(key);
2231
+ const component = {
2232
+ type: mapCategoryToComponentType(detection.category)
2233
+ };
2234
+ if (detection.category === "llm_provider") {
2235
+ component.provider = detection.framework;
2236
+ }
2237
+ components.push(component);
2238
+ }
2239
+ return components;
2240
+ }
2241
+ function mapCategoryToComponentType(category) {
2242
+ const mapping = {
2243
+ llm_provider: "llm",
2244
+ framework: "framework",
2245
+ agent_framework: "agent",
2246
+ ml_framework: "model",
2247
+ ml_ops: "mlops",
2248
+ model_file: "model"
2249
+ };
2250
+ return mapping[category] ?? category;
2251
+ }
2252
+ function calculateOverallConfidence(detections) {
2253
+ if (detections.length === 0) return "low";
2254
+ const highCount = detections.filter((d) => d.confidence === "high").length;
2255
+ const mediumCount = detections.filter((d) => d.confidence === "medium").length;
2256
+ if (highCount >= 3) return "high";
2257
+ if (highCount >= 1 && mediumCount >= 2) return "high";
2258
+ if (highCount >= 1 || mediumCount >= 3) return "medium";
2259
+ if (mediumCount >= 1) return "medium";
2260
+ return "low";
2261
+ }
2262
+
2263
+ // src/detection/index.ts
2264
+ init_python();
2265
+ init_javascript();
2266
+ init_model_files();
2267
+ init_risk_indicators();
2268
+
2269
+ // src/utils.ts
2270
+ function formatDate(date) {
2271
+ return date.toISOString();
2272
+ }
2273
+ function parseDate(dateString) {
2274
+ return new Date(dateString);
2275
+ }
2276
+ function slugify(text) {
2277
+ return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
2278
+ }
2279
+ // Annotate the CommonJS export names for ESM import in node:
2280
+ 0 && (module.exports = {
2281
+ ApprovalSchema,
2282
+ AssetCardSchema,
2283
+ ClassificationSchema,
2284
+ ConfidenceLevelSchema,
2285
+ ConstraintsSchema,
2286
+ ControlStatusSchema,
2287
+ DetectionStrategySchema,
2288
+ FrameworkCategorySchema,
2289
+ GovernanceSchema,
2290
+ IntentSchema,
2291
+ JurisdictionClassificationSchema,
2292
+ MODEL_EXTENSIONS,
2293
+ OwnerSchema,
2294
+ RiskFactorsSchema,
2295
+ TechnicalSchema,
2296
+ TrustworthinessCharacteristicSchema,
2297
+ TrustworthinessSchema,
2298
+ addJurisdiction,
2299
+ analyzeImports,
2300
+ applyImplicationChains,
2301
+ classifyRisk,
2302
+ clearRegistry,
2303
+ createAssetCard,
2304
+ createImplication,
2305
+ detectAnnotations,
2306
+ formatDate,
2307
+ generateAssetId,
2308
+ getAllPatterns,
2309
+ getPattern,
2310
+ getPatternsByCategory,
2311
+ getPatternsByLanguage,
2312
+ inferRiskFactors,
2313
+ initializePatterns,
2314
+ isModelFile,
2315
+ isRegistryInitialized,
2316
+ javascriptPatterns,
2317
+ linkAssetToTicket,
2318
+ loadAssetCard,
2319
+ matchPatterns,
2320
+ modelFilePatterns,
2321
+ parseDate,
2322
+ pythonPatterns,
2323
+ registerPattern,
2324
+ resetPatterns,
2325
+ riskIndicatorPatterns,
2326
+ saveAssetCard,
2327
+ scan,
2328
+ scanFileExtension,
2329
+ scanSync,
2330
+ slugify,
2331
+ suggestAssetCard,
2332
+ updateJurisdictionCompliance,
2333
+ validateAssetCard,
2334
+ validateGoldenThread,
2335
+ validateRiskFactors
2336
+ });
2337
+ //# sourceMappingURL=index.js.map