progmune-runtime 2.1.6 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (356) hide show
  1. package/README.md +108 -468
  2. package/dist/ablation-study.js +144 -0
  3. package/dist/ablation-study.test.js +18 -0
  4. package/dist/action-runtime.js +3 -1
  5. package/dist/active-learning.js +211 -0
  6. package/dist/analytics.js +139 -0
  7. package/dist/asset-factory.js +309 -0
  8. package/dist/asset-growth.js +244 -0
  9. package/dist/asset-promotion.js +382 -0
  10. package/dist/asset-quality.js +550 -0
  11. package/dist/audit/business-translator.js +285 -0
  12. package/dist/audit/cli.js +66 -0
  13. package/dist/audit/formatters/html.js +379 -0
  14. package/dist/audit/formatters/json.js +11 -0
  15. package/dist/audit/formatters/markdown.js +192 -0
  16. package/dist/audit/formatters/terminal.js +189 -0
  17. package/dist/audit/index.js +25 -0
  18. package/dist/audit/report-builder.js +318 -0
  19. package/dist/audit/types.js +8 -0
  20. package/dist/audit.js +3 -3
  21. package/dist/auto-benchmark-generator.js +137 -0
  22. package/dist/auto-benchmark-generator.test.js +45 -0
  23. package/dist/auto-protocol-synthesizer.js +362 -0
  24. package/dist/auto-protocol-synthesizer.test.js +82 -0
  25. package/dist/autonomous-patch.js +175 -0
  26. package/dist/autonomous-patch.test.js +128 -0
  27. package/dist/badge/badge-server.js +98 -0
  28. package/dist/behavior-miner.js +442 -0
  29. package/dist/belief-layer.js +475 -0
  30. package/dist/benchmark-count.js +5 -0
  31. package/dist/benchmark-generator.js +211 -0
  32. package/dist/benchmark-harness.js +201 -0
  33. package/dist/benchmark-pass-rate.js +7 -0
  34. package/dist/benchmark-report.js +8 -3
  35. package/dist/benchmark-save.js +14 -1
  36. package/dist/bootstrap-validation.js +197 -0
  37. package/dist/bootstrap-validation.test.js +51 -0
  38. package/dist/branch-ledger.js +1 -1
  39. package/dist/capability-gap.js +130 -0
  40. package/dist/certify-html.js +351 -0
  41. package/dist/certify.js +326 -0
  42. package/dist/check.js +4 -4
  43. package/dist/compliance-miner.js +447 -0
  44. package/dist/continuous-benchmark.js +194 -0
  45. package/dist/continuous-benchmark.test.js +116 -0
  46. package/dist/corpus-stats.js +173 -0
  47. package/dist/counterfactual-engine.js +288 -0
  48. package/dist/coverage-dashboard.js +109 -0
  49. package/dist/coverage-system.test.js +205 -0
  50. package/dist/cross-repo-precision.js +352 -0
  51. package/dist/cve-benchmark.js +180 -0
  52. package/dist/cve-benchmark.test.js +28 -0
  53. package/dist/cve-collector.js +73 -0
  54. package/dist/data-quality.js +141 -0
  55. package/dist/decision-engine.js +388 -0
  56. package/dist/derive-metadata.js +250 -0
  57. package/dist/difficulty-active.test.js +198 -0
  58. package/dist/difficulty-map.js +244 -0
  59. package/dist/discovery-analytics.js +125 -0
  60. package/dist/discovery-model.js +149 -0
  61. package/dist/discovery-optimize.test.js +199 -0
  62. package/dist/discovery-trace.js +276 -0
  63. package/dist/discovery-trace.test.js +97 -0
  64. package/dist/emitter.js +83 -1
  65. package/dist/enterprise-dashboard.js +405 -0
  66. package/dist/eval-hardening.js +297 -0
  67. package/dist/eval-hardening.test.js +85 -0
  68. package/dist/evaluation-campaign.js +359 -0
  69. package/dist/evaluation-campaign.test.js +181 -0
  70. package/dist/evidence-growth.js +143 -0
  71. package/dist/evidence-repository.js +209 -0
  72. package/dist/evidence-system.js +441 -0
  73. package/dist/execute.js +15 -7
  74. package/dist/experimental/software-physics.js +291 -0
  75. package/dist/experimental/state-inference.js +516 -0
  76. package/dist/experimental/unsupervised-physics.js +230 -0
  77. package/dist/extract-ir-python.js +54 -7
  78. package/dist/extract-ir.js +376 -12
  79. package/dist/failure-collector.js +2 -2
  80. package/dist/failure-corpus.js +322 -9
  81. package/dist/feedback.js +16 -5
  82. package/dist/feedback.test.js +49 -0
  83. package/dist/file-lock.js +1 -1
  84. package/dist/flywheel-batch.js +292 -0
  85. package/dist/frameworks/express-cli.js +237 -0
  86. package/dist/frameworks/express-detector.js +445 -0
  87. package/dist/frameworks/express-detector.test.js +206 -0
  88. package/dist/frameworks/index.js +30 -0
  89. package/dist/frameworks/nestjs-detector.js +302 -0
  90. package/dist/frameworks/trpc-detector.js +161 -0
  91. package/dist/frameworks/version-awareness.js +179 -0
  92. package/dist/function-synonyms.js +164 -0
  93. package/dist/function-synonyms.test.js +68 -0
  94. package/dist/generalization.test.js +352 -0
  95. package/dist/goal-annotator.js +113 -0
  96. package/dist/goal-planner.js +563 -0
  97. package/dist/gold-cve.js +164 -0
  98. package/dist/gold-cve.test.js +104 -0
  99. package/dist/gold-quality.js +206 -0
  100. package/dist/gold-tiers.js +241 -0
  101. package/dist/governance-dashboard.js +327 -0
  102. package/dist/graph-viz.js +240 -0
  103. package/dist/guided-frontier.js +195 -0
  104. package/dist/hierarchical-planner.js +148 -0
  105. package/dist/identifier-parser.js +260 -0
  106. package/dist/immune-metrics.js +93 -0
  107. package/dist/immune-receiver.js +158 -0
  108. package/dist/immune-reporter.js +1 -1
  109. package/dist/improvement-orchestrator.js +206 -0
  110. package/dist/inject-p0-vocabulary.js +300 -0
  111. package/dist/intent-parser.js +218 -0
  112. package/dist/invariant-algebra.js +476 -0
  113. package/dist/invariant-calculus.js +533 -0
  114. package/dist/ir-utils.js +70 -0
  115. package/dist/ir-utils.test.js +50 -0
  116. package/dist/knowledge-api.js +312 -0
  117. package/dist/knowledge-evolution.js +452 -0
  118. package/dist/knowledge-explorer.js +506 -0
  119. package/dist/knowledge-flywheel.js +274 -0
  120. package/dist/knowledge-governance.js +338 -0
  121. package/dist/knowledge-governance.test.js +150 -0
  122. package/dist/knowledge-graph.js +181 -0
  123. package/dist/knowledge-guided-synth.js +246 -0
  124. package/dist/knowledge-loop.test.js +77 -0
  125. package/dist/knowledge-object.js +316 -0
  126. package/dist/knowledge-package.js +98 -0
  127. package/dist/kpi-dashboard.js +561 -0
  128. package/dist/l3-cross-function.js +280 -0
  129. package/dist/learning-ranker.js +148 -0
  130. package/dist/learning-ranker.test.js +291 -0
  131. package/dist/ledger/accountability.js +322 -0
  132. package/dist/ledger/chain-builder.js +185 -0
  133. package/dist/ledger/cli.js +222 -0
  134. package/dist/ledger/index.js +13 -0
  135. package/dist/ledger/signatures.js +193 -0
  136. package/dist/ledger/types.js +9 -0
  137. package/dist/llm.js +74 -3
  138. package/dist/load-benchmarks.js +8 -3
  139. package/dist/logger.js +66 -0
  140. package/dist/logger.test.js +37 -0
  141. package/dist/logistic-reward.js +339 -0
  142. package/dist/logistic-reward.test.js +180 -0
  143. package/dist/macro-graph.js +193 -0
  144. package/dist/macro-repair.js +183 -0
  145. package/dist/mcp-server.mjs +1202 -483
  146. package/dist/memory-layer.js +42 -5
  147. package/dist/multi-repo-precision.js +422 -0
  148. package/dist/name-free-protocol.js +425 -0
  149. package/dist/name-free-protocol.test.js +170 -0
  150. package/dist/name-scrambling.js +138 -0
  151. package/dist/name-scrambling.test.js +16 -0
  152. package/dist/p3-observability.test.js +281 -0
  153. package/dist/p5-orchestrator.test.js +225 -0
  154. package/dist/pairwise-preference.js +294 -0
  155. package/dist/pairwise-preference.test.js +140 -0
  156. package/dist/planner-constraints.js +104 -0
  157. package/dist/planner-prompts.js +155 -0
  158. package/dist/planner-telemetry.js +415 -0
  159. package/dist/planner-trace.js +214 -0
  160. package/dist/planner.js +162 -167
  161. package/dist/plsb/artifact.js +116 -0
  162. package/dist/plsb/cli.js +71 -0
  163. package/dist/plsb/index.js +19 -0
  164. package/dist/plsb/leaderboard.js +249 -0
  165. package/dist/plsb/report-md.js +156 -0
  166. package/dist/plsb/schema.js +179 -0
  167. package/dist/plsb-benchmark.js +284 -0
  168. package/dist/plsb-benchmark.test.js +119 -0
  169. package/dist/policy/cli.js +134 -0
  170. package/dist/policy/engine.js +333 -0
  171. package/dist/policy/index.js +12 -0
  172. package/dist/policy/types.js +59 -0
  173. package/dist/policy-miner.js +505 -0
  174. package/dist/precision-analyze.js +229 -0
  175. package/dist/precision-benchmark.js +147 -0
  176. package/dist/precision-label-c.js +134 -0
  177. package/dist/precision-label.js +193 -0
  178. package/dist/precision-report-c.js +149 -0
  179. package/dist/precision-report.js +246 -0
  180. package/dist/progmune-status.js +108 -0
  181. package/dist/proof-engine.js +479 -0
  182. package/dist/proof-provenance.js +315 -0
  183. package/dist/protocol-coverage.js +294 -0
  184. package/dist/protocol-detector.js +1189 -0
  185. package/dist/protocol-embedding-expanded.js +297 -0
  186. package/dist/protocol-embedding-expanded.test.js +97 -0
  187. package/dist/protocol-embedding.js +195 -0
  188. package/dist/protocol-embedding.test.js +82 -0
  189. package/dist/protocol-extractor-v2.js +354 -0
  190. package/dist/protocol-extractor-v2.test.js +140 -0
  191. package/dist/protocol-extractor.js +310 -0
  192. package/dist/protocol-extractor.test.js +113 -0
  193. package/dist/protocol-foundation.js +322 -0
  194. package/dist/protocol-foundation.test.js +163 -0
  195. package/dist/protocol-frontier.js +243 -0
  196. package/dist/protocol-frontier.test.js +92 -0
  197. package/dist/protocol-gap-analyzer.js +228 -0
  198. package/dist/protocol-gap-analyzer.test.js +49 -0
  199. package/dist/protocol-invariants.js +276 -0
  200. package/dist/protocol-invariants.test.js +111 -0
  201. package/dist/protocol-knowledge.js +464 -0
  202. package/dist/protocol-miner.js +343 -0
  203. package/dist/protocol-mining.js +207 -0
  204. package/dist/protocol-mining.test.js +37 -0
  205. package/dist/protocol-registry.js +1 -1
  206. package/dist/protocol-security-benchmark.js +222 -0
  207. package/dist/protocol-vulnerability.js +257 -0
  208. package/dist/protocol-vulnerability.test.js +60 -0
  209. package/dist/python-benchmark.js +120 -0
  210. package/dist/python-emitter.js +163 -45
  211. package/dist/python-protocol-extractor.js +187 -0
  212. package/dist/python-protocol-extractor.test.js +116 -0
  213. package/dist/realworld-benchmark.js +646 -0
  214. package/dist/realworld-benchmark.test.js +36 -0
  215. package/dist/repair-arch.test.js +411 -0
  216. package/dist/repair-evolution.test.js +454 -0
  217. package/dist/repair-executor.js +719 -0
  218. package/dist/repair-proposal.js +4 -4
  219. package/dist/repair-ranker.js +141 -0
  220. package/dist/repair-strategies.js +419 -0
  221. package/dist/repair-taxonomy.js +234 -0
  222. package/dist/repair-types.js +12 -0
  223. package/dist/repo-evaluator.js +250 -0
  224. package/dist/repo-evaluator.test.js +128 -0
  225. package/dist/resource-abstraction.js +242 -0
  226. package/dist/resource-detector.js +211 -0
  227. package/dist/result.test.js +43 -0
  228. package/dist/reward-system.js +411 -0
  229. package/dist/reward-system.test.js +175 -0
  230. package/dist/risk-model.js +215 -0
  231. package/dist/rule-miner.js +234 -7
  232. package/dist/rule-specificity.js +254 -0
  233. package/dist/runtime-types.js +27 -0
  234. package/dist/scaffold.js +208 -0
  235. package/dist/scale-collector.test.js +101 -0
  236. package/dist/scale-trajectory-collector.js +128 -0
  237. package/dist/sdk.js +250 -0
  238. package/dist/search-planner.js +4 -41
  239. package/dist/semantic-snapshot.js +1 -1
  240. package/dist/semantic-topology.js +121 -0
  241. package/dist/semantic-trace.js +310 -317
  242. package/dist/sequence-extractor.js +343 -0
  243. package/dist/skill-library.js +245 -0
  244. package/dist/skill-planner.test.js +189 -0
  245. package/dist/software-physics.js +291 -0
  246. package/dist/software-physics.test.js +81 -0
  247. package/dist/ssg-precision.js +478 -0
  248. package/dist/ssg-validator.js +71 -21
  249. package/dist/state-inference-doubleblind.test.js +160 -0
  250. package/dist/state-inference.js +516 -0
  251. package/dist/state-inference.test.js +115 -0
  252. package/dist/state-machine-fingerprint.js +345 -0
  253. package/dist/state-machine-fingerprint.test.js +120 -0
  254. package/dist/state-miner.js +386 -0
  255. package/dist/state-name-inference.js +213 -0
  256. package/dist/state-name-inference.test.js +69 -0
  257. package/dist/strategy-planner.js +262 -96
  258. package/dist/strategy-planner.test.js +135 -0
  259. package/dist/telemetry-analytics.test.js +402 -0
  260. package/dist/terminal-format.js +68 -0
  261. package/dist/terminal-format.test.js +83 -0
  262. package/dist/topology-factory.js +196 -0
  263. package/dist/topology-representation.js +242 -0
  264. package/dist/topology-representation.test.js +27 -0
  265. package/dist/trajectory-augmentation.js +254 -0
  266. package/dist/trajectory-augmentation.test.js +63 -0
  267. package/dist/trajectory-corpus.js +440 -0
  268. package/dist/trajectory-corpus.test.js +32 -0
  269. package/dist/trajectory-feedback.test.js +116 -0
  270. package/dist/transition-synthesizer.js +286 -0
  271. package/dist/transition-synthesizer.test.js +123 -0
  272. package/dist/trust/api-semantic-mapper.js +809 -0
  273. package/dist/trust/call-graph-propagator.js +225 -0
  274. package/dist/trust/cli.js +122 -0
  275. package/dist/trust/compliance-scorer.js +283 -0
  276. package/dist/trust/confidence-calculator.js +261 -0
  277. package/dist/trust/engine.js +1145 -0
  278. package/dist/trust/explainability.js +85 -0
  279. package/dist/trust/formatters/ci.js +42 -0
  280. package/dist/trust/formatters/json.js +11 -0
  281. package/dist/trust/formatters/terminal.js +152 -0
  282. package/dist/trust/index.js +39 -0
  283. package/dist/trust/phase1-verify.js +171 -0
  284. package/dist/trust/protocol-domain-validator.js +697 -0
  285. package/dist/trust/score-calculator.js +282 -0
  286. package/dist/trust/ssg-bridge.js +641 -0
  287. package/dist/trust/ssg-bridge.test.js +269 -0
  288. package/dist/trust/types.js +67 -0
  289. package/dist/trust/violation-trace.js +335 -0
  290. package/dist/trust-api.js +179 -0
  291. package/dist/trust-calibration.js +279 -0
  292. package/dist/unknown-protocol-discovery.js +339 -0
  293. package/dist/unknown-protocol-discovery.test.js +102 -0
  294. package/dist/unsupervised-physics.js +230 -0
  295. package/dist/unsupervised-physics.test.js +95 -0
  296. package/dist/utils.test.js +37 -0
  297. package/dist/validator.js +187 -10
  298. package/dist/verification-intelligence.js +475 -0
  299. package/dist/verify-api.js +432 -0
  300. package/dist/vi-impact-report.js +293 -0
  301. package/dist/wl-fingerprint.js +162 -0
  302. package/dist/wl-fingerprint.test.js +130 -0
  303. package/dist/zeroshot-strategy.js +139 -0
  304. package/docs/Progmune_/346/212/225/350/265/204/344/272/272/347/231/275/347/232/256/344/271/246_v2.0.html +576 -0
  305. package/docs/Progmune_/351/241/271/347/233/256/345/205/250/350/247/243.html +710 -0
  306. package/package.json +74 -7
  307. package/protocols.json +1956 -50
  308. package/.dockerignore +0 -14
  309. package/.mcp.json +0 -11
  310. package/.progmune_allowlist +0 -50
  311. package/.test_report/test_report.md +0 -87
  312. package/Dockerfile +0 -9
  313. package/FAQ.md +0 -167
  314. package/WHITEPAPER.md +0 -540
  315. package/demo-project/auth.ts +0 -55
  316. package/demo-project/tsconfig.json +0 -8
  317. package/dist/acl-breakdown.js +0 -13
  318. package/dist/all-sessions.js +0 -11
  319. package/dist/antibody-stats.js +0 -11
  320. package/dist/branch-tree-count.js +0 -14
  321. package/dist/common-fixpath.js +0 -12
  322. package/dist/constraint-types.js +0 -12
  323. package/dist/exec-metrics.js +0 -11
  324. package/dist/failure-report.js +0 -11
  325. package/dist/fast-path-hits.js +0 -13
  326. package/dist/fingerprint-list.js +0 -15
  327. package/dist/gen-history-log.js +0 -13
  328. package/dist/heatmap-data.js +0 -11
  329. package/dist/recent-session.js +0 -12
  330. package/dist/svl-distribution.js +0 -11
  331. package/dist/terminal-status.js +0 -11
  332. package/dist/token-savings.js +0 -11
  333. package/dist/total-repairs.js +0 -12
  334. package/dist/unresolved-count.js +0 -12
  335. package/dist/valid-fingerprints.js +0 -13
  336. package/dist/verify-ledgers.js +0 -11
  337. package/docs/whitepaper-style.css +0 -77
  338. package/docs/whitepaper-v2.1.md +0 -609
  339. package/docs/whitepaper-v2.2.md +0 -1064
  340. package/docs/whitepaper-v2.2.pdf +0 -0
  341. package/fly.toml +0 -31
  342. package/public/dashboard.html +0 -119
  343. package/server/hub.js +0 -116
  344. package/test/replay-golden/sess_1780063202050_mgeld.json +0 -9
  345. package/test/replay-golden/sess_1780064032560_gocld.json +0 -354
  346. package/test/replay-golden/sess_1780064413331_s2709.json +0 -606
  347. package/test/replay-golden/sess_1780064792710_y3avo.json +0 -614
  348. package/test/replay-golden.ts +0 -84
  349. package/test_benchmark.js +0 -165
  350. package/test_comprehensive.mjs +0 -638
  351. package/test_concurrency.js +0 -129
  352. package/test_ir_robustness.js +0 -85
  353. package/test_semantic_contracts.js +0 -269
  354. package/test_ssg_stress.js +0 -156
  355. package/test_svl3.js +0 -58
  356. package/tsconfig.json +0 -17
@@ -0,0 +1,809 @@
1
+ "use strict";
2
+ /**
3
+ * Phase 1: API → Protocol Semantic Mapper
4
+ *
5
+ * Maps concrete library API calls (curl, libssh, etc.) to abstract protocol
6
+ * semantic categories. LLM does NOT do verification — it only does "translation".
7
+ *
8
+ * Architecture:
9
+ * Call Sequence (raw API names)
10
+ * → Prefix-based lookup table (fast, deterministic)
11
+ * → LLM fallback for unknown APIs (cached)
12
+ * → SemanticCategory[]
13
+ *
14
+ * Categories are deliberately coarse-grained — just enough for the protocol
15
+ * domain validator to determine "is this a valid protocol operation?"
16
+ */
17
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ var desc = Object.getOwnPropertyDescriptor(m, k);
20
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
21
+ desc = { enumerable: true, get: function() { return m[k]; } };
22
+ }
23
+ Object.defineProperty(o, k2, desc);
24
+ }) : (function(o, m, k, k2) {
25
+ if (k2 === undefined) k2 = k;
26
+ o[k2] = m[k];
27
+ }));
28
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
29
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
30
+ }) : function(o, v) {
31
+ o["default"] = v;
32
+ });
33
+ var __importStar = (this && this.__importStar) || (function () {
34
+ var ownKeys = function(o) {
35
+ ownKeys = Object.getOwnPropertyNames || function (o) {
36
+ var ar = [];
37
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
38
+ return ar;
39
+ };
40
+ return ownKeys(o);
41
+ };
42
+ return function (mod) {
43
+ if (mod && mod.__esModule) return mod;
44
+ var result = {};
45
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
46
+ __setModuleDefault(result, mod);
47
+ return result;
48
+ };
49
+ })();
50
+ Object.defineProperty(exports, "__esModule", { value: true });
51
+ exports.mapApiToSemantic = mapApiToSemantic;
52
+ exports.mapSequenceToSemantic = mapSequenceToSemantic;
53
+ exports.llmMapApiToSemantic = llmMapApiToSemantic;
54
+ exports.llmBatchMapApis = llmBatchMapApis;
55
+ exports.mapSequenceToSemanticWithLLM = mapSequenceToSemanticWithLLM;
56
+ exports.isKnownProtocolDomain = isKnownProtocolDomain;
57
+ /**
58
+ * Mapping rules ordered by specificity (longer/more specific prefixes first).
59
+ * Covers curl, OpenSSL, wolfSSL, mbedTLS, GnuTLS, Rustls, Schannel,
60
+ * SecureTransport (Apple), libssh2, nghttp2, LDAP, SASL, SSPI, GSSAPI, etc.
61
+ */
62
+ const MAPPING_TABLE = [
63
+ // ── TLS Configuration ──
64
+ { prefix: "Curl_ssl_cf_get_primary_config", domain: "tls_config", description: "获取 TLS 主配置" },
65
+ { prefix: "Curl_ssl_cf_get_config", domain: "tls_config", description: "获取 TLS SSL 配置" },
66
+ { prefix: "Curl_ssl_cf_is_proxy", domain: "tls_config", description: "判断 TLS 是否为代理连接" },
67
+ { prefix: "Curl_ssl_cfilter_add", domain: "tls_config", description: "添加 SSL 过滤层到连接" },
68
+ { prefix: "Curl_conn_is_ssl", domain: "tls_config", description: "判断连接是否已 SSL" },
69
+ { prefix: "Curl_tls_keylog_enabled", domain: "tls_config", description: "TLS keylog 启用检查" },
70
+ { prefix: "Curl_ssl_scache_use", domain: "tls_session", description: "判断是否使用 SSL session cache" },
71
+ { prefix: "Curl_ssl_scache_lock", domain: "tls_session", description: "SSL session cache 加锁" },
72
+ { prefix: "Curl_ssl_scache_unlock", domain: "tls_session", description: "SSL session cache 解锁" },
73
+ { prefix: "Curl_ssl_scache_get_obj", domain: "tls_session", description: "从 cache 获取 SSL session 对象" },
74
+ { prefix: "Curl_ssl_scache_take", domain: "tls_session", description: "从 session cache 取出条目" },
75
+ // ── TLS ALPN ──
76
+ { prefix: "Curl_alpn_copy", domain: "tls_alpn", description: "ALPN 协议列表复制" },
77
+ { prefix: "Curl_alpn_contains_proto", domain: "tls_alpn", description: "检查 ALPN 是否包含某协议" },
78
+ { prefix: "Curl_alpn_restrict_to", domain: "tls_alpn", description: "限制 ALPN 协议范围" },
79
+ { prefix: "Curl_alpn_to_proto_buf", domain: "tls_alpn", description: "ALPN 转协议缓冲" },
80
+ { prefix: "Curl_str2alpnid", domain: "tls_alpn", description: "字符串转 ALPN ID" },
81
+ // ── TLS Handshake (OpenSSL) ──
82
+ { prefix: "SSL_CTX_set_default_passwd_cb", domain: "tls_cert", description: "SSL_CTX 设置密码回调" },
83
+ { prefix: "SSL_CTX_set_default_passwd_cb_userdata", domain: "tls_cert", description: "SSL_CTX 设置密码回调用户数据" },
84
+ { prefix: "SSL_CTX_use_certificate_chain_file", domain: "tls_cert", description: "SSL_CTX 加载证书链文件" },
85
+ { prefix: "SSL_CTX_use_certificate_file", domain: "tls_cert", description: "SSL_CTX 加载证书文件" },
86
+ { prefix: "SSL_CTX_get_cert_store", domain: "tls_cert", description: "SSL_CTX 获取证书存储" },
87
+ { prefix: "SSL_set_session", domain: "tls_session", description: "设置 SSL session" },
88
+ { prefix: "SSL_get_tlsext_status_ocsp_resp", domain: "tls_cert", description: "获取 OCSP stapling 响应" },
89
+ { prefix: "SSL_get_peer_cert_chain", domain: "tls_cert", description: "获取对端证书链" },
90
+ { prefix: "SSL_get1_peer_certificate", domain: "tls_cert", description: "获取对端证书" },
91
+ { prefix: "d2i_SSL_SESSION", domain: "tls_session", description: "DER 解码 SSL session" },
92
+ { prefix: "d2i_PKCS12_bio", domain: "tls_cert", description: "DER 解码 PKCS12 证书" },
93
+ { prefix: "d2i_OCSP_RESPONSE", domain: "tls_cert", description: "DER 解码 OCSP 响应" },
94
+ { prefix: "OCSP_response_status", domain: "tls_cert", description: "OCSP 响应状态" },
95
+ { prefix: "OCSP_response_status_str", domain: "tls_cert", description: "OCSP 响应状态字符串" },
96
+ { prefix: "OCSP_response_get1_basic", domain: "tls_cert", description: "OCSP 获取基本响应" },
97
+ { prefix: "OCSP_basic_verify", domain: "tls_cert", description: "OCSP 基本响应验证" },
98
+ { prefix: "ossl_do_file_type", domain: "tls_cert", description: "OpenSSL 文件类型处理" },
99
+ { prefix: "ossl_strerror", domain: "error_handle", description: "OpenSSL 错误信息" },
100
+ { prefix: "ERR_get_error", domain: "error_handle", description: "OpenSSL 获取错误码" },
101
+ { prefix: "BIO_new_mem_buf", domain: "tls_cert", description: "BIO 内存缓冲创建" },
102
+ { prefix: "BIO_new", domain: "tls_cert", description: "BIO 创建" },
103
+ { prefix: "BIO_s_file", domain: "tls_cert", description: "BIO 文件接口" },
104
+ { prefix: "BIO_read_filename", domain: "tls_cert", description: "BIO 读取文件名" },
105
+ { prefix: "BIO_free", domain: "tls_cert", description: "BIO 释放" },
106
+ { prefix: "X509_get_ext_d2i", domain: "tls_cert", description: "X509 扩展解码" },
107
+ { prefix: "sk_GENERAL_NAME_", domain: "tls_cert", description: "X509 SAN 扩展操作" },
108
+ { prefix: "ASN1_STRING_", domain: "tls_cert", description: "ASN1 字符串操作" },
109
+ { prefix: "STACK_OF", domain: "tls_cert", description: "OpenSSL STACK 类型" },
110
+ // ── TLS Handshake (wolfSSL) ──
111
+ { prefix: "wolfTLS_client_method", domain: "tls_handshake", description: "wolfSSL 客户端方法" },
112
+ { prefix: "wolfSSL_CTX_free", domain: "tls_handshake", description: "wolfSSL 释放 CTX" },
113
+ { prefix: "wolfSSL_CTX_new", domain: "tls_handshake", description: "wolfSSL 创建 CTX" },
114
+ { prefix: "wolfSSL_connect", domain: "tls_handshake", description: "wolfSSL TLS 连接" },
115
+ { prefix: "wolfSSL_ERR_clear_error", domain: "error_handle", description: "wolfSSL 清除错误" },
116
+ { prefix: "wolfSSL_want_read", domain: "tls_handshake", description: "wolfSSL 读就绪检查" },
117
+ { prefix: "wssl_send_earlydata", domain: "tls_handshake", description: "wolfSSL TLS 1.3 early data" },
118
+ { prefix: "wssl_init_ciphers", domain: "tls_config", description: "wolfSSL 初始化密码套件" },
119
+ { prefix: "wssl_init_curves", domain: "tls_config", description: "wolfSSL 初始化椭圆曲线" },
120
+ { prefix: "Curl_wssl_setup_x509_store", domain: "tls_cert", description: "wolfSSL 设置 X509 证书存储" },
121
+ // ── TLS Handshake (mbedTLS) ──
122
+ { prefix: "mbedtls_ssl_handshake", domain: "tls_handshake", description: "mbedTLS SSL 握手" },
123
+ { prefix: "mbedtls_ssl_get_version_number", domain: "tls_handshake", description: "mbedTLS 获取 TLS 版本号" },
124
+ { prefix: "mbedtls_ssl_get_version", domain: "tls_handshake", description: "mbedTLS 获取 TLS 版本字符串" },
125
+ { prefix: "mbedtls_ssl_get_ciphersuite_id_from_ssl", domain: "tls_handshake", description: "mbedTLS 获取密码套件 ID" },
126
+ { prefix: "mbedtls_ssl_get_peer_cert", domain: "tls_cert", description: "mbedTLS 获取对端证书" },
127
+ { prefix: "mbedtls_strerror", domain: "error_handle", description: "mbedTLS 错误信息" },
128
+ { prefix: "mbed_cipher_suite_get_str", domain: "tls_handshake", description: "mbedTLS 密码套件名称" },
129
+ // ── TLS Handshake (GnuTLS) ──
130
+ { prefix: "gtls_client_init", domain: "tls_handshake", description: "GnuTLS 客户端初始化" },
131
+ { prefix: "gnutls_session_set_data", domain: "tls_session", description: "GnuTLS 设置 session 数据" },
132
+ { prefix: "gnutls_session_set_ptr", domain: "tls_session", description: "GnuTLS 设置 session 指针" },
133
+ { prefix: "gnutls_srp_allocate_client_credentials", domain: "auth_cred", description: "GnuTLS SRP 凭证分配" },
134
+ { prefix: "gnutls_srp_allocate_client_cred", domain: "auth_cred", description: "GnuTLS SRP 凭证分配" },
135
+ { prefix: "gnutls_srp_set_client_credentials", domain: "auth_cred", description: "GnuTLS SRP 设置凭证" },
136
+ { prefix: "gnutls_srp_set_client_cred", domain: "auth_cred", description: "GnuTLS SRP 设置凭证" },
137
+ { prefix: "gnutls_strerror", domain: "error_handle", description: "GnuTLS 错误信息" },
138
+ // ── TLS Handshake (Rustls) ──
139
+ { prefix: "cr_ech_need_httpsrr", domain: "tls_config", description: "Rustls ECH 检查" },
140
+ { prefix: "cr_init_backend", domain: "tls_handshake", description: "Rustls 后端初始化" },
141
+ { prefix: "cr_set_negotiated_alpn", domain: "tls_alpn", description: "Rustls 设置协商 ALPN" },
142
+ { prefix: "cr_send", domain: "tls_handshake", description: "Rustls 发送数据" },
143
+ { prefix: "rustls_connection_is_handshaking", domain: "tls_handshake", description: "Rustls 握手状态检查" },
144
+ { prefix: "rustls_connection_get_protocol_version", domain: "tls_handshake", description: "Rustls 获取协议版本" },
145
+ { prefix: "rustls_connection_get_negotiated_ciphersuite_name", domain: "tls_handshake", description: "Rustls 获取密码套件" },
146
+ { prefix: "rustls_connection_get_negotiated_key_exchange_group_name", domain: "tls_handshake", description: "Rustls 获取密钥交换组" },
147
+ // ── TLS Handshake (Schannel / Windows) ──
148
+ { prefix: "schannel_acquire_credential_handle", domain: "tls_handshake", description: "Schannel 获取凭证句柄" },
149
+ { prefix: "Curl_schannel_get_cached_cert_store", domain: "tls_cert", description: "Schannel 获取缓存证书存储" },
150
+ { prefix: "Curl_sspi_strerror", domain: "error_handle", description: "SSPI 错误信息" },
151
+ // ── TLS Handshake (Apple SecureTransport) ──
152
+ { prefix: "SecPolicyCreateSSL", domain: "tls_config", description: "Apple: 创建 SSL 安全策略" },
153
+ { prefix: "CFStringCreateWithCString", domain: "platform_util", description: "Apple CF 字符串创建" },
154
+ { prefix: "CFArrayCreateMutable", domain: "platform_util", description: "Apple CF 数组创建" },
155
+ { prefix: "CFArrayAppendValue", domain: "platform_util", description: "Apple CF 数组追加" },
156
+ { prefix: "CFRelease", domain: "platform_util", description: "Apple CF 对象释放" },
157
+ // ── TLS Session Cache ──
158
+ { prefix: "cf_ssl_scache_get", domain: "tls_session", description: "SSL session cache 获取" },
159
+ { prefix: "cf_ssl_scache_peer_set_hmac", domain: "tls_session", description: "SSL session cache HMAC 设置" },
160
+ { prefix: "cf_scache_peer_remove_expired", domain: "tls_session", description: "SSL session cache 清理过期" },
161
+ // ── Auth: Credentials ──
162
+ { prefix: "Curl_creds_has_user", domain: "auth_cred", description: "认证: 检查是否有用户名" },
163
+ { prefix: "Curl_creds_has_passwd", domain: "auth_cred", description: "认证: 检查是否有密码" },
164
+ { prefix: "Curl_creds_has_sasl_service", domain: "auth_mech", description: "SASL: 检查是否有服务名" },
165
+ { prefix: "Curl_creds_user", domain: "auth_cred", description: "认证: 获取用户名" },
166
+ { prefix: "Curl_creds_passwd", domain: "auth_cred", description: "认证: 获取密码" },
167
+ { prefix: "Curl_creds_sasl_service", domain: "auth_mech", description: "SASL: 获取服务名" },
168
+ // ── Auth: SASL ──
169
+ { prefix: "Curl_sasl_init", domain: "auth_mech", description: "SASL 初始化" },
170
+ { prefix: "sasl_choose_", domain: "auth_mech", description: "SASL 机制选择" },
171
+ { prefix: "Curl_auth_create_plain_message", domain: "auth_mech", description: "SASL PLAIN 消息创建" },
172
+ { prefix: "Curl_auth_create_login_message", domain: "auth_mech", description: "SASL LOGIN 消息创建" },
173
+ { prefix: "Curl_auth_create_external_message", domain: "auth_mech", description: "SASL EXTERNAL 消息创建" },
174
+ { prefix: "Curl_auth_allowed_to_host", domain: "auth_mech", description: "检查认证是否允许到此主机" },
175
+ { prefix: "Curl_auth_build_spn", domain: "auth_spn", description: "构建 Kerberos SPN" },
176
+ { prefix: "Curl_auth_gsasl_get", domain: "auth_mech", description: "GSASL 认证获取" },
177
+ { prefix: "sasl_state", domain: "auth_mech", description: "SASL 状态" },
178
+ // ── Auth: NTLM ──
179
+ { prefix: "Curl_ntlm_core_mk_nt_hash", domain: "auth_hash", description: "NTLM NT 哈希生成" },
180
+ // ── Auth: DIGEST-MD5 ──
181
+ { prefix: "auth_decode_digest_md5_message", domain: "auth_mech", description: "DIGEST-MD5 解码 challenge" },
182
+ { prefix: "auth_digest_get_qop_values", domain: "auth_mech", description: "DIGEST-MD5 获取 QOP 值" },
183
+ // ── Auth: GSSAPI/Kerberos ──
184
+ { prefix: "gss_seal", domain: "auth_gssapi", description: "GSSAPI 封装消息" },
185
+ { prefix: "gss_wrap", domain: "auth_gssapi", description: "GSSAPI 包装消息" },
186
+ { prefix: "gss_unseal", domain: "auth_gssapi", description: "GSSAPI 解封消息" },
187
+ { prefix: "gss_unwrap", domain: "auth_gssapi", description: "GSSAPI 解包消息" },
188
+ { prefix: "Curl_gss_delete_sec_context", domain: "auth_gssapi", description: "GSSAPI 删除安全上下文" },
189
+ { prefix: "check_gss_err", domain: "auth_gssapi", description: "GSSAPI 错误检查" },
190
+ { prefix: "gss_indicate_mechs", domain: "auth_gssapi", description: "GSSAPI 指示可用机制" },
191
+ { prefix: "gss_create_empty_oid_set", domain: "auth_gssapi", description: "GSSAPI 创建空 OID 集合" },
192
+ { prefix: "gss_add_oid_set_member", domain: "auth_gssapi", description: "GSSAPI 添加 OID 成员" },
193
+ { prefix: "gss_import_name", domain: "auth_gssapi", description: "GSSAPI 导入名称" },
194
+ { prefix: "gss_acquire_cred", domain: "auth_gssapi", description: "GSSAPI 获取凭证" },
195
+ { prefix: "gss_inquire_cred", domain: "auth_gssapi", description: "GSSAPI 查询凭证" },
196
+ { prefix: "gss_inquire_cred_by_mech", domain: "auth_gssapi", description: "GSSAPI 按机制查询凭证" },
197
+ { prefix: "GSS_ERROR", domain: "auth_gssapi", description: "GSSAPI 错误宏" },
198
+ { prefix: "ssh_gssapi_", domain: "auth_gssapi", description: "SSH GSSAPI 操作" },
199
+ // ── Auth: SSPI (Windows) ──
200
+ { prefix: "QuerySecurityPackageInfo", domain: "auth_mech", description: "SSPI 查询安全包信息" },
201
+ { prefix: "QueryContextAttributes", domain: "auth_mech", description: "SSPI 查询上下文属性" },
202
+ { prefix: "FreeContextBuffer", domain: "mem_free", description: "SSPI 释放上下文缓冲" },
203
+ { prefix: "Curl_create_sspi_identity", domain: "auth_mech", description: "SSPI 创建安全身份" },
204
+ { prefix: "Curl_sspi_", domain: "auth_mech", description: "SSPI 操作" },
205
+ // ── Auth: Hash/Crypto ──
206
+ { prefix: "Curl_rand", domain: "auth_hash", description: "随机数生成 (auth nonce)" },
207
+ { prefix: "Curl_rand_bytes", domain: "auth_hash", description: "随机字节生成" },
208
+ { prefix: "Curl_rand_hex", domain: "auth_hash", description: "随机十六进制字符串" },
209
+ { prefix: "Curl_MD5_init", domain: "auth_hash", description: "MD5 初始化" },
210
+ { prefix: "Curl_MD5_update", domain: "auth_hash", description: "MD5 更新" },
211
+ { prefix: "curlx_base64_encode", domain: "auth_hash", description: "Base64 编码 (凭证)" },
212
+ // ── LDAP ──
213
+ { prefix: "ldap_url_parse", domain: "ldap_ops", description: "LDAP URL 解析" },
214
+ { prefix: "ldap_url_parse_low", domain: "ldap_ops", description: "LDAP URL 底层解析" },
215
+ { prefix: "ldap_pvt_url_scheme2proto", domain: "ldap_ops", description: "LDAP URL scheme→协议" },
216
+ { prefix: "ldap_result", domain: "ldap_ops", description: "LDAP 获取结果" },
217
+ { prefix: "ldap_err2string", domain: "ldap_ops", description: "LDAP 错误码→字符串" },
218
+ { prefix: "ldap_parse_result", domain: "ldap_ops", description: "LDAP 解析结果" },
219
+ { prefix: "ldap_msgtype", domain: "ldap_ops", description: "LDAP 消息类型" },
220
+ { prefix: "ldap_msgfree", domain: "ldap_ops", description: "LDAP 释放消息" },
221
+ { prefix: "ldap_memfree", domain: "ldap_ops", description: "LDAP 释放内存" },
222
+ { prefix: "ldap_set_option", domain: "ldap_ops", description: "LDAP 设置选项" },
223
+ { prefix: "ldap_init_fd", domain: "ldap_ops", description: "LDAP 文件描述符初始化" },
224
+ { prefix: "ldap_get_dn_ber", domain: "ldap_ops", description: "LDAP 获取 DN BER 编码" },
225
+ { prefix: "oldap_parse_login_options", domain: "ldap_ops", description: "LDAP 解析登录选项" },
226
+ { prefix: "oldap_map_error", domain: "ldap_ops", description: "LDAP 映射错误码" },
227
+ { prefix: "oldap_perform_bind", domain: "ldap_ops", description: "LDAP 执行绑定" },
228
+ // ── FTP ──
229
+ { prefix: "ftp_readresp", domain: "ftp_ops", description: "FTP 读取响应" },
230
+ { prefix: "ftp_wait_resp", domain: "ftp_ops", description: "FTP 等待响应" },
231
+ // ── SMTP ──
232
+ { prefix: "smtp_perform_upgrade_tls", domain: "smtp_ops", description: "SMTP 升级到 TLS" },
233
+ { prefix: "smtp_state_", domain: "smtp_ops", description: "SMTP 协议状态" },
234
+ // ── IMAP ──
235
+ { prefix: "imap_perform_upgrade_tls", domain: "imap_ops", description: "IMAP 升级到 TLS" },
236
+ { prefix: "imap_state_", domain: "imap_ops", description: "IMAP 协议状态" },
237
+ { prefix: "imap_find_literal", domain: "imap_ops", description: "IMAP 查找 literal 边界" },
238
+ { prefix: "imap_atom", domain: "imap_ops", description: "IMAP atom 令牌" },
239
+ { prefix: "is_custom_fetch_listing", domain: "imap_ops", description: "IMAP 自定义 FETCH 列表" },
240
+ // ── MQTT ──
241
+ { prefix: "mqtt_send", domain: "mqtt_ops", description: "MQTT 发送消息" },
242
+ { prefix: "mqtt_ping", domain: "mqtt_ops", description: "MQTT 心跳 PING" },
243
+ { prefix: "mqstate", domain: "mqtt_ops", description: "MQTT 状态" },
244
+ // ── SMB ──
245
+ { prefix: "smb_send_tree_connect", domain: "smb_ops", description: "SMB 发送树连接" },
246
+ { prefix: "smb_send_and_recv", domain: "smb_ops", description: "SMB 发送并接收" },
247
+ { prefix: "smb_swap", domain: "smb_ops", description: "SMB 字节序转换" },
248
+ // ── SSH/SFTP (libssh2) ──
249
+ { prefix: "libssh2_crypto_engine", domain: "ssh_ops", description: "libssh2 加密引擎" },
250
+ { prefix: "libssh2_session_init_ex", domain: "ssh_ops", description: "libssh2 会话初始化" },
251
+ { prefix: "libssh2_session_set_read_timeout", domain: "ssh_ops", description: "libssh2 设置读超时" },
252
+ { prefix: "libssh2_session_callback_set2", domain: "ssh_ops", description: "libssh2 设置回调" },
253
+ { prefix: "recvcb", domain: "ssh_ops", description: "SSH 接收回调" },
254
+ { prefix: "sendcb", domain: "ssh_ops", description: "SSH 发送回调" },
255
+ { prefix: "libssh2_session_last_errno", domain: "ssh_ops", description: "libssh2 最后错误" },
256
+ { prefix: "libssh2_sftp_", domain: "ssh_ops", description: "libssh2 SFTP 操作" },
257
+ { prefix: "sftp_stat", domain: "ssh_ops", description: "SFTP 文件状态" },
258
+ { prefix: "sftp_attributes_free", domain: "ssh_ops", description: "SFTP 释放属性" },
259
+ { prefix: "sftp_open", domain: "ssh_ops", description: "SFTP 打开文件" },
260
+ { prefix: "sftp_close", domain: "ssh_ops", description: "SFTP 关闭文件" },
261
+ { prefix: "sftp_get_error", domain: "ssh_ops", description: "SFTP 获取错误" },
262
+ { prefix: "myssh_to_ERROR", domain: "ssh_ops", description: "SSH 错误码映射" },
263
+ { prefix: "myssh_to", domain: "ssh_ops", description: "SSH 错误码映射" },
264
+ { prefix: "ssh_state_", domain: "ssh_ops", description: "SSH 协议状态" },
265
+ { prefix: "ssh_agent_new", domain: "ssh_ops", description: "SSH agent 创建" },
266
+ { prefix: "ssh_socket_new", domain: "ssh_ops", description: "SSH socket 创建" },
267
+ { prefix: "ssh_channel_", domain: "ssh_ops", description: "SSH channel 操作" },
268
+ // ── Telnet ──
269
+ { prefix: "init_telnet", domain: "telnet_ops", description: "Telnet 初始化" },
270
+ { prefix: "check_telnet_options", domain: "telnet_ops", description: "Telnet 选项检查" },
271
+ // ── DNS/DoH ──
272
+ { prefix: "doh_close", domain: "dns_ops", description: "DoH 关闭" },
273
+ { prefix: "doh_resp_decode", domain: "dns_ops", description: "DoH 响应解码" },
274
+ { prefix: "doh_strerror", domain: "dns_ops", description: "DoH 错误信息" },
275
+ { prefix: "doh_type2name", domain: "dns_ops", description: "DoH 类型→名称" },
276
+ { prefix: "de_init", domain: "dns_ops", description: "DoH 引擎初始化" },
277
+ { prefix: "Curl_doh", domain: "dns_ops", description: "DoH 入口" },
278
+ { prefix: "Curl_resolv_", domain: "dns_ops", description: "DNS 解析" },
279
+ { prefix: "Curl_is_ipaddr", domain: "dns_ops", description: "判断是否 IP 地址" },
280
+ { prefix: "Curl_str2addr", domain: "dns_ops", description: "字符串转地址" },
281
+ { prefix: "get_localhost", domain: "dns_ops", description: "获取 localhost 地址" },
282
+ { prefix: "hostip_async_new", domain: "dns_ops", description: "异步 DNS 查询" },
283
+ { prefix: "Curl_host_is_ipnum", domain: "dns_ops", description: "判断主机名是否为 IP" },
284
+ // ── HTTP ──
285
+ { prefix: "Curl_http_neg_init", domain: "http_ops", description: "HTTP 协商初始化" },
286
+ { prefix: "Curl_http_req_to_h2", domain: "http_ops", description: "HTTP/1→HTTP/2 请求转换" },
287
+ { prefix: "Curl_h1_req_parse_read", domain: "http_ops", description: "HTTP/1 请求解析" },
288
+ { prefix: "Curl_h1_req_parse_free", domain: "http_ops", description: "HTTP/1 请求解析释放" },
289
+ { prefix: "Curl_checkheaders", domain: "http_ops", description: "HTTP 检查已有 headers" },
290
+ { prefix: "Curl_checkProxyheaders", domain: "http_ops", description: "HTTP 检查代理 headers" },
291
+ { prefix: "http_on_response", domain: "http_ops", description: "HTTP 响应回调" },
292
+ { prefix: "http_target", domain: "http_ops", description: "HTTP 请求目标" },
293
+ { prefix: "get_http_string", domain: "http_ops", description: "HTTP 字符串获取" },
294
+ { prefix: "http2_data_setup", domain: "http2_ops", description: "HTTP/2 数据设置" },
295
+ { prefix: "Curl_dynhds_init", domain: "http_ops", description: "HTTP headers 动态初始化" },
296
+ { prefix: "Curl_dynhds_to_nva", domain: "http2_ops", description: "HTTP headers 转 nghttp2 nva" },
297
+ { prefix: "h2_pri_spec", domain: "http2_ops", description: "HTTP/2 优先级" },
298
+ { prefix: "nghttp2_session_", domain: "http2_ops", description: "nghttp2 session 操作" },
299
+ { prefix: "nghttp2_session_check_request_allowed", domain: "http2_ops", description: "nghttp2 请求允许检查" },
300
+ { prefix: "tunnel_stream_init", domain: "http2_ops", description: "HTTP/2 tunnel 流初始化" },
301
+ // ── MIME ──
302
+ { prefix: "IS_MIME_POST", domain: "http_ops", description: "MIME POST 判断" },
303
+ { prefix: "curl_mime_headers", domain: "http_ops", description: "MIME headers 获取" },
304
+ { prefix: "Curl_mime_prepare_headers", domain: "http_ops", description: "MIME headers 准备" },
305
+ { prefix: "Curl_mime_add_header", domain: "http_ops", description: "MIME header 添加" },
306
+ // ── Connection Management ──
307
+ { prefix: "Curl_conn_meta_get", domain: "conn_mgmt", description: "连接元数据获取" },
308
+ { prefix: "Curl_conn_meta_set", domain: "conn_mgmt", description: "连接元数据设置" },
309
+ { prefix: "Curl_conn_get_origin", domain: "conn_mgmt", description: "获取连接原始地址" },
310
+ { prefix: "Curl_conn_get_ip_info", domain: "conn_mgmt", description: "获取连接 IP 信息" },
311
+ { prefix: "Curl_conn_get_current_host", domain: "conn_mgmt", description: "获取当前主机" },
312
+ { prefix: "Curl_conn_connect", domain: "conn_mgmt", description: "建立连接" },
313
+ { prefix: "do_connect", domain: "conn_mgmt", description: "执行连接 (含 TLS 握手)" },
314
+ { prefix: "Curl_conn_is_ssl", domain: "conn_mgmt", description: "判断是否 SSL 连接" },
315
+ { prefix: "Curl_conn_cf_get_transport", domain: "conn_mgmt", description: "获取传输层" },
316
+ { prefix: "Curl_conn_needs_flush", domain: "conn_mgmt", description: "连接刷新检查" },
317
+ { prefix: "Curl_conn_flush", domain: "conn_mgmt", description: "连接刷新" },
318
+ { prefix: "Curl_conn_cntrl_update_info", domain: "conn_mgmt", description: "连接控制信息更新" },
319
+ { prefix: "Curl_conn_dns_resolved_https", domain: "conn_mgmt", description: "DNS 已解析 HTTPS 记录" },
320
+ { prefix: "Curl_detach_connection", domain: "conn_mgmt", description: "分离连接" },
321
+ // ── Connection Poll/Event ──
322
+ { prefix: "Curl_pollset_", domain: "conn_poll", description: "连接轮询集操作" },
323
+ { prefix: "Curl_pollfds_init", domain: "conn_poll", description: "pollfd 初始化" },
324
+ { prefix: "multi_now", domain: "conn_poll", description: "multi 当前时间" },
325
+ { prefix: "multi_perform", domain: "conn_poll", description: "multi 执行" },
326
+ { prefix: "multi_runsingle", domain: "conn_poll", description: "multi 单次运行" },
327
+ { prefix: "multi_done", domain: "conn_poll", description: "multi 完成" },
328
+ { prefix: "multi_assess_wakeup", domain: "conn_poll", description: "multi 唤醒评估" },
329
+ { prefix: "Curl_multi_ev_assess", domain: "conn_poll", description: "multi 事件评估" },
330
+ { prefix: "Curl_multi_ev_", domain: "conn_poll", description: "multi 事件操作" },
331
+ { prefix: "Curl_multi_get_easy", domain: "conn_poll", description: "multi 获取 easy handle" },
332
+ { prefix: "Curl_multi_xfers_running", domain: "conn_poll", description: "multi 活跃传输计数" },
333
+ { prefix: "Curl_update_timer", domain: "conn_poll", description: "更新定时器" },
334
+ { prefix: "curl_multi_socket_action", domain: "conn_poll", description: "multi socket 动作" },
335
+ { prefix: "curl_multi_remove_handle", domain: "conn_poll", description: "multi 移除 handle" },
336
+ { prefix: "curl_multi_cleanup", domain: "conn_poll", description: "multi 清理" },
337
+ { prefix: "curl_easy_perform", domain: "conn_poll", description: "easy 执行" },
338
+ { prefix: "sigpipe_init", domain: "conn_poll", description: "SIGPIPE 初始化" },
339
+ { prefix: "sigpipe_restore", domain: "conn_poll", description: "SIGPIPE 恢复" },
340
+ { prefix: "Curl_expire", domain: "conn_poll", description: "设置超时" },
341
+ { prefix: "Curl_expire_clear", domain: "conn_poll", description: "清除超时" },
342
+ { prefix: "conn_report_connect_stats", domain: "conn_poll", description: "连接统计报告" },
343
+ // ── Transfer/Reader ──
344
+ { prefix: "Curl_xfer_recv", domain: "conn_mgmt", description: "传输层接收" },
345
+ { prefix: "Curl_client_write", domain: "conn_mgmt", description: "客户端写入" },
346
+ { prefix: "client_write", domain: "conn_mgmt", description: "客户端写入 (协议层)" },
347
+ { prefix: "Curl_creader_set_mime", domain: "http_ops", description: "读取器设置 MIME" },
348
+ { prefix: "Curl_creader_client_length", domain: "http_ops", description: "读取器客户端长度" },
349
+ { prefix: "Curl_creader_set_fread", domain: "http_ops", description: "读取器设置文件读取" },
350
+ { prefix: "Curl_pp_flushsend", domain: "conn_mgmt", description: "协议层刷新发送缓冲" },
351
+ { prefix: "Curl_pp_readresp", domain: "conn_mgmt", description: "协议层读取响应" },
352
+ { prefix: "Curl_pgrs_now", domain: "conn_mgmt", description: "进度当前时间" },
353
+ { prefix: "Curl_pgrsSetUploadSize", domain: "conn_mgmt", description: "进度设置上传大小" },
354
+ // ── Memory Operations ──
355
+ { prefix: "curlx_malloc", domain: "mem_alloc", description: "curl 内存分配" },
356
+ { prefix: "curlx_calloc", domain: "mem_alloc", description: "curl 零初始化分配" },
357
+ { prefix: "curlx_free", domain: "mem_free", description: "curl 内存释放" },
358
+ { prefix: "curlx_safefree", domain: "mem_free", description: "curl 安全释放" },
359
+ { prefix: "curlx_memdup", domain: "mem_util", description: "curl 内存复制" },
360
+ { prefix: "curlx_memdup0", domain: "mem_util", description: "curl 内存复制+零终止" },
361
+ { prefix: "memset", domain: "mem_util", description: "内存设置" },
362
+ { prefix: "memcpy", domain: "mem_util", description: "内存复制" },
363
+ { prefix: "memcmp", domain: "mem_util", description: "内存比较" },
364
+ { prefix: "memchr", domain: "mem_util", description: "内存字符查找" },
365
+ { prefix: "calloc", domain: "mem_alloc", description: "标准零初始化分配" },
366
+ { prefix: "malloc", domain: "mem_alloc", description: "标准内存分配" },
367
+ // ── String Operations ──
368
+ { prefix: "strlen", domain: "str_util", description: "字符串长度" },
369
+ { prefix: "strcmp", domain: "str_util", description: "字符串比较" },
370
+ { prefix: "strcasecmp", domain: "str_util", description: "字符串忽略大小写比较" },
371
+ { prefix: "strncmp", domain: "str_util", description: "字符串定长比较" },
372
+ { prefix: "strchr", domain: "str_util", description: "字符串字符查找" },
373
+ { prefix: "strcspn", domain: "str_util", description: "字符串跨度" },
374
+ { prefix: "strrchr", domain: "str_util", description: "字符串反向字符查找" },
375
+ { prefix: "strstr", domain: "str_util", description: "字符串子串查找" },
376
+ { prefix: "curl_strequal", domain: "str_util", description: "curl 字符串相等" },
377
+ { prefix: "curlx_str_", domain: "str_util", description: "curl 字符串工具" },
378
+ { prefix: "curlx_dyn_init", domain: "buf_util", description: "动态缓冲初始化" },
379
+ { prefix: "curlx_dyn_free", domain: "buf_util", description: "动态缓冲释放" },
380
+ { prefix: "curlx_dyn_add", domain: "buf_util", description: "动态缓冲追加" },
381
+ { prefix: "curlx_dyn_addn", domain: "buf_util", description: "动态缓冲追加 n 字节" },
382
+ { prefix: "curlx_dyn_addf", domain: "buf_util", description: "动态缓冲格式化追加" },
383
+ { prefix: "curlx_dyn_reset", domain: "buf_util", description: "动态缓冲重置" },
384
+ { prefix: "curlx_dyn_ptr", domain: "buf_util", description: "动态缓冲获取指针" },
385
+ { prefix: "curlx_dyn_len", domain: "buf_util", description: "动态缓冲获取长度" },
386
+ { prefix: "curlx_dyn_uptr", domain: "buf_util", description: "动态缓冲获取无符号指针" },
387
+ { prefix: "curl_msnprintf", domain: "str_format", description: "curl 格式化输出" },
388
+ { prefix: "curl_maprintf", domain: "str_format", description: "curl 格式化分配" },
389
+ { prefix: "curlx_convert_UTF8_to_tchar", domain: "platform_util", description: "UTF8→TCHAR 编码转换" },
390
+ // ── Buffer/URL ──
391
+ { prefix: "Curl_bufref_ptr", domain: "buf_util", description: "缓冲引用获取指针" },
392
+ { prefix: "Curl_bufref_set", domain: "buf_util", description: "缓冲引用设置" },
393
+ { prefix: "Curl_bufref_free", domain: "buf_util", description: "缓冲引用释放" },
394
+ { prefix: "Curl_bufref_init", domain: "buf_util", description: "缓冲引用初始化" },
395
+ { prefix: "Curl_bufq_init", domain: "buf_util", description: "缓冲队列初始化" },
396
+ { prefix: "curl_url", domain: "buf_util", description: "URL 对象创建" },
397
+ { prefix: "curl_url_set", domain: "buf_util", description: "URL 设置" },
398
+ { prefix: "curl_url_get", domain: "buf_util", description: "URL 获取" },
399
+ { prefix: "curl_url_cleanup", domain: "buf_util", description: "URL 清理" },
400
+ { prefix: "curl_url_strerror", domain: "buf_util", description: "URL 错误信息" },
401
+ { prefix: "Curl_is_absolute_url", domain: "buf_util", description: "URL 绝对路径判断" },
402
+ { prefix: "Curl_uc_to_curlcode", domain: "buf_util", description: "URL 错误码转换" },
403
+ // ── Network Utilities ──
404
+ { prefix: "htonl", domain: "net_util", description: "主机→网络字节序 (32-bit)" },
405
+ { prefix: "htons", domain: "net_util", description: "主机→网络字节序 (16-bit)" },
406
+ { prefix: "ntohl", domain: "net_util", description: "网络→主机字节序 (32-bit)" },
407
+ { prefix: "ntohs", domain: "net_util", description: "网络→主机字节序 (16-bit)" },
408
+ { prefix: "setsockopt", domain: "net_util", description: "socket 选项设置" },
409
+ { prefix: "getsockname", domain: "net_util", description: "获取 socket 名称" },
410
+ { prefix: "curlx_nonblock", domain: "net_util", description: "设置非阻塞" },
411
+ { prefix: "curlx_inet_pton", domain: "net_util", description: "IP 地址转换" },
412
+ // ── Platform Utilities ──
413
+ { prefix: "curlx_verify_windows_version", domain: "platform_util", description: "Windows 版本检查" },
414
+ { prefix: "curlx_winapi_strerror", domain: "error_handle", description: "Windows API 错误信息" },
415
+ { prefix: "GetLastError", domain: "error_handle", description: "Windows 最后错误" },
416
+ { prefix: "GetStdHandle", domain: "platform_util", description: "Windows 标准句柄" },
417
+ { prefix: "GetSystemTimeAsFileTime", domain: "platform_util", description: "Windows 系统时间" },
418
+ { prefix: "CompareFileTime", domain: "platform_util", description: "Windows 文件时间比较" },
419
+ { prefix: "CertOpenSystemStoreA", domain: "tls_cert", description: "Windows 打开系统证书存储" },
420
+ { prefix: "CertOpenStore", domain: "tls_cert", description: "Windows 打开证书存储" },
421
+ { prefix: "CertEnumCertificatesInStore", domain: "tls_cert", description: "Windows 枚举证书" },
422
+ { prefix: "CertGetNameStringA", domain: "tls_cert", description: "Windows 获取证书名称" },
423
+ { prefix: "CertGetNameString", domain: "tls_cert", description: "Windows 获取证书名称" },
424
+ { prefix: "CertGetIntendedKeyUsage", domain: "tls_cert", description: "Windows 获取证书密钥用途" },
425
+ { prefix: "WSACreateEvent", domain: "platform_util", description: "Windows WSA 事件创建" },
426
+ { prefix: "WSAEventSelect", domain: "platform_util", description: "Windows WSA 事件选择" },
427
+ { prefix: "WSACloseEvent", domain: "platform_util", description: "Windows WSA 事件关闭" },
428
+ { prefix: "WaitForMultipleObjects", domain: "platform_util", description: "Windows 等待多个对象" },
429
+ { prefix: "__builtin_available", domain: "platform_util", description: "macOS 版本检查" },
430
+ // ── Debug/Trace ──
431
+ { prefix: "CURL_TRC_CF", domain: "debug_trace", description: "连接过滤层跟踪" },
432
+ { prefix: "CURL_TRC_M", domain: "debug_trace", description: "multi 跟踪" },
433
+ { prefix: "CURL_TRC_DNS", domain: "debug_trace", description: "DNS 跟踪" },
434
+ { prefix: "Curl_debug", domain: "debug_trace", description: "调试输出" },
435
+ { prefix: "Curl_trc_ft_is_verbose", domain: "debug_trace", description: "跟踪详细检查" },
436
+ { prefix: "VERBOSE", domain: "debug_trace", description: "详细日志宏" },
437
+ { prefix: "infof", domain: "debug_trace", description: "信息日志" },
438
+ // ── Meta/Generic ──
439
+ { prefix: "Curl_meta_get", domain: "conn_mgmt", description: "元数据获取" },
440
+ { prefix: "Curl_uint32_tbl_", domain: "util", description: "uint32 表操作" },
441
+ { prefix: "Curl_uint32_bset_", domain: "util", description: "uint32 位集操作" },
442
+ { prefix: "Curl_llist_init", domain: "util", description: "链表初始化" },
443
+ { prefix: "Curl_llist_count", domain: "util", description: "链表计数" },
444
+ { prefix: "Curl_llist_head", domain: "util", description: "链表头" },
445
+ { prefix: "Curl_node_next", domain: "util", description: "链表下一节点" },
446
+ { prefix: "Curl_node_elem", domain: "util", description: "链表节点元素" },
447
+ { prefix: "GOOD_MULTI_HANDLE", domain: "util", description: "multi handle 断言" },
448
+ { prefix: "GOOD_EASY_HANDLE", domain: "util", description: "easy handle 断言" },
449
+ { prefix: "Curl_slist_append_nodup", domain: "util", description: "slist 去重追加" },
450
+ { prefix: "Curl_secure_context", domain: "util", description: "安全上下文" },
451
+ // ── Rfc/Conditional/Generic ──
452
+ { prefix: "RFC2228", domain: "ftp_ops", description: "FTP 安全扩展 RFC2228" },
453
+ { prefix: "USE_SSL", domain: "tls_config", description: "SSL 编译选项" },
454
+ { prefix: "CURL_UNCONST", domain: "util", description: "const 转换宏" },
455
+ { prefix: "STRCONST", domain: "util", description: "字符串常量宏" },
456
+ { prefix: "TEXT", domain: "util", description: "Windows 宽字符宏" },
457
+ { prefix: "FALLTHROUGH", domain: "util", description: "switch 穿透标记" },
458
+ { prefix: "UNUSED", domain: "util", description: "未使用参数标记" },
459
+ { prefix: "defined", domain: "util", description: "条件编译检查" },
460
+ { prefix: "endif", domain: "util", description: "预处理结束" },
461
+ { prefix: "CURL_SOCKET", domain: "net_util", description: "Socket 类型" },
462
+ // ── File I/O ──
463
+ { prefix: "curlx_fopen", domain: "util", description: "curl 文件打开" },
464
+ { prefix: "curlx_fclose", domain: "util", description: "curl 文件关闭" },
465
+ { prefix: "curlx_fstat", domain: "util", description: "curl 文件状态" },
466
+ { prefix: "fopen", domain: "util", description: "文件打开" },
467
+ { prefix: "fclose", domain: "util", description: "文件关闭" },
468
+ { prefix: "fseek", domain: "util", description: "文件定位" },
469
+ { prefix: "ftell", domain: "util", description: "文件位置" },
470
+ { prefix: "fread", domain: "util", description: "文件读取" },
471
+ { prefix: "fileno", domain: "util", description: "文件描述符" },
472
+ // ── Time/Cookie/Etc ──
473
+ { prefix: "Curl_meets_timecondition", domain: "util", description: "时间条件检查" },
474
+ { prefix: "curlx_gmtime", domain: "util", description: "GMT 时间" },
475
+ { prefix: "curlx_ptimediff_ms", domain: "util", description: "时间差毫秒" },
476
+ { prefix: "time", domain: "util", description: "系统时间" },
477
+ { prefix: "getenv", domain: "platform_util", description: "获取环境变量" },
478
+ { prefix: "cookiehash", domain: "util", description: "Cookie 哈希" },
479
+ { prefix: "cookie_tailmatch", domain: "util", description: "Cookie 尾部匹配" },
480
+ { prefix: "remove_expired", domain: "util", description: "移除过期条目" },
481
+ { prefix: "Curl_junkscan", domain: "buf_util", description: "URL junk 扫描" },
482
+ { prefix: "guess_scheme", domain: "buf_util", description: "猜测 URL scheme" },
483
+ { prefix: "parse_file", domain: "buf_util", description: "解析文件 URL" },
484
+ { prefix: "parse_scheme", domain: "buf_util", description: "解析 scheme" },
485
+ { prefix: "parse_authority", domain: "buf_util", description: "解析 authority" },
486
+ { prefix: "tailmatch", domain: "str_util", description: "尾部匹配" },
487
+ { prefix: "Curl_cert_hostcheck", domain: "tls_cert", description: "证书主机名验证" },
488
+ { prefix: "cert_get_name_string", domain: "tls_cert", description: "证书名称获取" },
489
+ { prefix: "get_cert_location", domain: "tls_cert", description: "证书位置获取" },
490
+ { prefix: "get_num_host_info", domain: "tls_cert", description: "主机信息数量" },
491
+ { prefix: "get_alt_name_info", domain: "tls_cert", description: "SAN 信息获取" },
492
+ { prefix: "add_certs_data_to_store", domain: "tls_cert", description: "证书添加到存储" },
493
+ { prefix: "ssl_installed", domain: "tls_config", description: "SSL 是否已安装" },
494
+ { prefix: "ssl_version", domain: "tls_config", description: "SSL 版本" },
495
+ { prefix: "engineload", domain: "tls_config", description: "OpenSSL 引擎加载" },
496
+ { prefix: "use_certificate_chain_blob", domain: "tls_cert", description: "证书链 blob 加载" },
497
+ { prefix: "use_certificate_blob", domain: "tls_cert", description: "证书 blob 加载" },
498
+ { prefix: "sess_reuse_cb", domain: "tls_session", description: "Session 复用回调" },
499
+ { prefix: "secrets", domain: "tls_handshake", description: "TLS 密钥材料" },
500
+ { prefix: "handshake", domain: "tls_handshake", description: "TLS 握手标记" },
501
+ // ── File upload ──
502
+ { prefix: "file_upload", domain: "util", description: "文件上传" },
503
+ { prefix: "S_ISDIR", domain: "util", description: "目录判断宏" },
504
+ // ── Catch-all for unmapped but common patterns ──
505
+ { prefix: "Curl_resolv_destroy_all", domain: "dns_ops", description: "DNS 解析器销毁" },
506
+ { prefix: "Curl_req_free", domain: "http_ops", description: "HTTP 请求释放" },
507
+ { prefix: "Curl_ssl_close_all", domain: "tls_config", description: "SSL 全部关闭" },
508
+ { prefix: "Curl_wildcard_dtor", domain: "conn_mgmt", description: "通配符析构" },
509
+ { prefix: "Curl_peer_unlink", domain: "conn_mgmt", description: "对端连接断开" },
510
+ { prefix: "Curl_data_priority_clear_state", domain: "http_ops", description: "HTTP 数据优先级清理" },
511
+ { prefix: "cf_ip_attempt_connect", domain: "conn_mgmt", description: "IP 连接尝试" },
512
+ { prefix: "cf_ip_attempt_free", domain: "conn_mgmt", description: "IP 连接尝试释放" },
513
+ { prefix: "cf_ai_iter_has_more", domain: "conn_mgmt", description: "地址迭代检查" },
514
+ { prefix: "cf_ai_iter_next", domain: "conn_mgmt", description: "地址迭代下一个" },
515
+ { prefix: "Curl_reset_fail", domain: "conn_mgmt", description: "连接失败重置" },
516
+ { prefix: "multi_xfers_add", domain: "conn_poll", description: "multi 传输添加" },
517
+ { prefix: "multi_mark_expired_as_dirty", domain: "conn_poll", description: "multi 过期标记" },
518
+ { prefix: "connclose", domain: "conn_mgmt", description: "连接关闭标记" },
519
+ { prefix: "streamclose", domain: "conn_mgmt", description: "流关闭" },
520
+ { prefix: "request_state", domain: "conn_mgmt", description: "请求状态" },
521
+ { prefix: "select", domain: "net_util", description: "I/O 多路复用" },
522
+ { prefix: "altsvc_flush", domain: "http_ops", description: "Alt-Svc 刷新" },
523
+ { prefix: "Curl_strntolower", domain: "str_util", description: "字符串转小写" },
524
+ { prefix: "Curl_raw_toupper", domain: "str_util", description: "字符转大写" },
525
+ { prefix: "Curl_ssl_cf_get_primary_config", domain: "tls_config", description: "获取 TLS 主配置" }, // duplicate guard
526
+ ];
527
+ // Deduplicate: keep first (most specific) match
528
+ const seen = new Set();
529
+ const DEDUPED_TABLE = MAPPING_TABLE.filter(rule => {
530
+ if (seen.has(rule.prefix))
531
+ return false;
532
+ seen.add(rule.prefix);
533
+ return true;
534
+ });
535
+ // ═══════════════════════════════════════════════════════════════
536
+ // Core Mapping Functions
537
+ // ═══════════════════════════════════════════════════════════════
538
+ /**
539
+ * Map a single API name to its semantic category.
540
+ * Uses prefix-based lookup (O(n) over ~300 rules, fast enough).
541
+ * Falls back to "util" for unknown APIs.
542
+ */
543
+ function mapApiToSemantic(apiName) {
544
+ const lower = apiName.toLowerCase();
545
+ for (const rule of DEDUPED_TABLE) {
546
+ if (lower.startsWith(rule.prefix.toLowerCase())) {
547
+ return {
548
+ api: apiName,
549
+ domain: rule.domain,
550
+ description: rule.description,
551
+ source: "lookup",
552
+ };
553
+ }
554
+ }
555
+ // Fallback: unknown API
556
+ return {
557
+ api: apiName,
558
+ domain: "util",
559
+ description: `未知 API: ${apiName}`,
560
+ source: "lookup", // will be "llm" when LLM fallback is implemented
561
+ };
562
+ }
563
+ /**
564
+ * Map a call sequence to a semantic sequence.
565
+ */
566
+ function mapSequenceToSemantic(calls) {
567
+ const steps = calls.map(mapApiToSemantic);
568
+ const domainSet = new Set();
569
+ const domainCounts = new Map();
570
+ for (const step of steps) {
571
+ domainSet.add(step.domain);
572
+ domainCounts.set(step.domain, (domainCounts.get(step.domain) || 0) + 1);
573
+ }
574
+ // Determine primary domain (most frequent, excluding util/mem/str/platform)
575
+ let primaryDomain = null;
576
+ let maxCount = 0;
577
+ const noiseDomains = ["util", "mem_alloc", "mem_free", "mem_util", "str_util", "str_format", "buf_util", "net_util", "platform_util", "debug_trace", "error_handle"];
578
+ for (const [domain, count] of domainCounts) {
579
+ if (!noiseDomains.includes(domain) && count > maxCount) {
580
+ maxCount = count;
581
+ primaryDomain = domain;
582
+ }
583
+ }
584
+ return {
585
+ steps,
586
+ domains: [...domainSet],
587
+ primaryDomain,
588
+ };
589
+ }
590
+ // ═══════════════════════════════════════════════════════════════
591
+ // Phase 4: LLM Fallback + Persistent Cache
592
+ // ═══════════════════════════════════════════════════════════════
593
+ const fs = __importStar(require("fs"));
594
+ const path = __importStar(require("path"));
595
+ const CACHE_FILE = path.resolve(__dirname, "../../.progmune_generated/api-semantic-cache.json");
596
+ /** In-memory LLM result cache: apiName → SemanticStep */
597
+ const llmCache = new Map();
598
+ /** Load persisted cache from disk */
599
+ function loadLlmCache() {
600
+ try {
601
+ if (fs.existsSync(CACHE_FILE)) {
602
+ const raw = JSON.parse(fs.readFileSync(CACHE_FILE, "utf-8"));
603
+ for (const [key, value] of Object.entries(raw)) {
604
+ llmCache.set(key, value);
605
+ }
606
+ }
607
+ }
608
+ catch { /* best-effort */ }
609
+ }
610
+ /** Persist in-memory cache to disk */
611
+ function saveLlmCache() {
612
+ try {
613
+ const dir = path.dirname(CACHE_FILE);
614
+ if (!fs.existsSync(dir))
615
+ fs.mkdirSync(dir, { recursive: true });
616
+ const obj = {};
617
+ for (const [key, value] of llmCache) {
618
+ obj[key] = value;
619
+ }
620
+ fs.writeFileSync(CACHE_FILE, JSON.stringify(obj, null, 2), "utf-8");
621
+ }
622
+ catch { /* best-effort */ }
623
+ }
624
+ // Load cache on module init
625
+ loadLlmCache();
626
+ /** All valid protocol domains for the LLM prompt */
627
+ const ALL_DOMAINS = [
628
+ "tls_config", "tls_handshake", "tls_cert", "tls_session", "tls_alpn",
629
+ "auth_cred", "auth_mech", "auth_hash", "auth_spn", "auth_gssapi",
630
+ "ldap_ops", "ftp_ops", "smtp_ops", "imap_ops", "mqtt_ops", "smb_ops",
631
+ "ssh_ops", "telnet_ops", "dns_ops", "http_ops", "http2_ops",
632
+ "conn_mgmt", "conn_poll",
633
+ "mem_alloc", "mem_free", "mem_util",
634
+ "str_util", "str_format", "buf_util",
635
+ "net_util", "platform_util", "debug_trace", "error_handle",
636
+ "util",
637
+ ];
638
+ const LLM_SYSTEM_PROMPT = `You are an API semantic classifier. Your ONLY job is to map function names to protocol domains.
639
+
640
+ Rules:
641
+ 1. Output ONLY the domain name, nothing else. No explanation, no punctuation.
642
+ 2. Choose from these domains: ${ALL_DOMAINS.join(", ")}
643
+ 3. If unsure, output "util".
644
+ 4. Use context clues: function name prefixes, library conventions, common patterns.
645
+ 5. Examples:
646
+ - axios.post → http_ops
647
+ - bcrypt.hash → auth_hash
648
+ - pg.connect → conn_mgmt
649
+ - os.open → util
650
+ - flask.route → http_ops
651
+ - mysql.query → conn_mgmt
652
+ - jwt.sign → auth_mech
653
+ - socket.send → conn_mgmt
654
+ - redis.get → conn_mgmt`;
655
+ /**
656
+ * LLM fallback for unknown APIs.
657
+ * Sends API name to LLM for semantic classification, caches result.
658
+ */
659
+ async function llmMapApiToSemantic(apiName, _context) {
660
+ // Check cache first (in-memory)
661
+ const cacheKey = apiName.toLowerCase();
662
+ const cached = llmCache.get(cacheKey);
663
+ if (cached)
664
+ return { ...cached, api: apiName };
665
+ try {
666
+ const { chat } = require("../llm");
667
+ const result = await chat(LLM_SYSTEM_PROMPT, `Map this function to a protocol domain: ${apiName}`);
668
+ // Parse: take first line, trim, lowercase, validate
669
+ const rawDomain = result.trim().split("\n")[0].toLowerCase().replace(/[^a-z_]/g, "");
670
+ const domain = ALL_DOMAINS.includes(rawDomain)
671
+ ? rawDomain
672
+ : "util";
673
+ const step = {
674
+ api: apiName,
675
+ domain,
676
+ description: `LLM: ${apiName} → ${domain}`,
677
+ source: "llm",
678
+ };
679
+ // Cache and persist
680
+ llmCache.set(cacheKey, step);
681
+ saveLlmCache();
682
+ return step;
683
+ }
684
+ catch {
685
+ // LLM unavailable — fall back to util
686
+ return {
687
+ api: apiName,
688
+ domain: "util",
689
+ description: `LLM unavailable: ${apiName}`,
690
+ source: "lookup",
691
+ };
692
+ }
693
+ }
694
+ /**
695
+ * Batch LLM mapping for multiple unknown APIs in one call.
696
+ * Minimizes LLM round-trips.
697
+ */
698
+ async function llmBatchMapApis(apiNames) {
699
+ const results = new Map();
700
+ // Filter out already-cached
701
+ const unknowns = apiNames.filter((name) => {
702
+ const cached = llmCache.get(name.toLowerCase());
703
+ if (cached) {
704
+ results.set(name, { ...cached, api: name });
705
+ return false;
706
+ }
707
+ return true;
708
+ });
709
+ if (unknowns.length === 0)
710
+ return results;
711
+ try {
712
+ const { chat } = require("../llm");
713
+ const prompt = unknowns.map((n, i) => `${i + 1}. ${n}`).join("\n");
714
+ const response = await chat(LLM_SYSTEM_PROMPT + "\n\nOutput one domain per line, matching the input order. No numbering, no explanation.", `Map each function to ONE protocol domain:\n${prompt}`);
715
+ const lines = response.trim().split("\n");
716
+ for (let i = 0; i < unknowns.length; i++) {
717
+ const rawDomain = (lines[i] || "util").trim().toLowerCase().replace(/[^a-z_]/g, "");
718
+ const domain = ALL_DOMAINS.includes(rawDomain)
719
+ ? rawDomain
720
+ : "util";
721
+ const step = {
722
+ api: unknowns[i],
723
+ domain,
724
+ description: `LLM: ${unknowns[i]} → ${domain}`,
725
+ source: "llm",
726
+ };
727
+ const cacheKey = unknowns[i].toLowerCase();
728
+ llmCache.set(cacheKey, step);
729
+ results.set(unknowns[i], step);
730
+ }
731
+ saveLlmCache();
732
+ }
733
+ catch {
734
+ // LLM unavailable — all unknowns → util
735
+ for (const name of unknowns) {
736
+ const step = {
737
+ api: name,
738
+ domain: "util",
739
+ description: `LLM unavailable: ${name}`,
740
+ source: "lookup",
741
+ };
742
+ results.set(name, step);
743
+ }
744
+ }
745
+ return results;
746
+ }
747
+ /**
748
+ * Map a call sequence to semantic categories, using LLM fallback
749
+ * for APIs not found in the lookup table.
750
+ */
751
+ async function mapSequenceToSemanticWithLLM(calls) {
752
+ // First pass: lookup table
753
+ const steps = calls.map(mapApiToSemantic);
754
+ // Identify unknowns (mapped to "util" by lookup)
755
+ const unknownIndices = [];
756
+ const unknownApis = [];
757
+ steps.forEach((s, i) => {
758
+ if (s.domain === "util" && s.source === "lookup") {
759
+ // Check if it's a common word that genuinely is util
760
+ const isCommonWord = /^(buffer|bytes|block|files|directories|size|seek|writing|secrets|handshake|allowed|conditions|status|keys|accessed|delay|secret|startup|argument|info|time|proc|set|get|part|chars|name|type|state|data|list|are|hostname|scheme|literal|failed|defined|endif|VERBOSE|TEXT|STRCONST|CURL_UNCONST|FALLTHROUGH|UNUSED)$/i.test(s.api);
761
+ if (!isCommonWord && s.api.length > 3) {
762
+ unknownIndices.push(i);
763
+ unknownApis.push(s.api);
764
+ }
765
+ }
766
+ });
767
+ // Second pass: LLM batch mapping for unknowns
768
+ if (unknownApis.length > 0) {
769
+ try {
770
+ const llmResults = await llmBatchMapApis(unknownApis);
771
+ for (let i = 0; i < unknownIndices.length; i++) {
772
+ const apiName = unknownApis[i];
773
+ const llmStep = llmResults.get(apiName);
774
+ if (llmStep && llmStep.domain !== "util") {
775
+ steps[unknownIndices[i]] = llmStep;
776
+ }
777
+ }
778
+ }
779
+ catch { /* LLM failed — keep lookup results */ }
780
+ }
781
+ // Compute domains and primary domain (same as sync version)
782
+ const domainSet = new Set();
783
+ const domainCounts = new Map();
784
+ for (const step of steps) {
785
+ domainSet.add(step.domain);
786
+ domainCounts.set(step.domain, (domainCounts.get(step.domain) || 0) + 1);
787
+ }
788
+ let primaryDomain = null;
789
+ let maxCount = 0;
790
+ const noiseDomains = [
791
+ "util", "mem_alloc", "mem_free", "mem_util",
792
+ "str_util", "str_format", "buf_util", "net_util",
793
+ "platform_util", "debug_trace", "error_handle",
794
+ ];
795
+ for (const [domain, count] of domainCounts) {
796
+ if (!noiseDomains.includes(domain) && count > maxCount) {
797
+ maxCount = count;
798
+ primaryDomain = domain;
799
+ }
800
+ }
801
+ return { steps, domains: [...domainSet], primaryDomain };
802
+ }
803
+ /**
804
+ * Check if a semantic sequence belongs to a known protocol domain
805
+ * (i.e., it has a clear primary domain that is not "util")
806
+ */
807
+ function isKnownProtocolDomain(seq) {
808
+ return seq.primaryDomain !== null && seq.primaryDomain !== "util";
809
+ }