@hybridlabor-api/aos 4.4.0 → 4.4.2-beta.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 (306) hide show
  1. package/.agents/skills/firecrawl/SKILL.md +149 -0
  2. package/.agents/skills/firecrawl/rules/install.md +82 -0
  3. package/.agents/skills/firecrawl/rules/security.md +26 -0
  4. package/.agents/skills/firecrawl-agent/SKILL.md +58 -0
  5. package/.agents/skills/firecrawl-build/SKILL.md +39 -0
  6. package/.agents/skills/firecrawl-build-interact/SKILL.md +68 -0
  7. package/.agents/skills/firecrawl-build-onboarding/SKILL.md +103 -0
  8. package/.agents/skills/firecrawl-build-onboarding/references/auth-flow.md +39 -0
  9. package/.agents/skills/firecrawl-build-onboarding/references/project-setup.md +20 -0
  10. package/.agents/skills/firecrawl-build-onboarding/references/sdk-installation.md +17 -0
  11. package/.agents/skills/firecrawl-build-scrape/SKILL.md +69 -0
  12. package/.agents/skills/firecrawl-build-search/SKILL.md +69 -0
  13. package/.agents/skills/firecrawl-crawl/SKILL.md +59 -0
  14. package/.agents/skills/firecrawl-download/SKILL.md +70 -0
  15. package/.agents/skills/firecrawl-interact/SKILL.md +84 -0
  16. package/.agents/skills/firecrawl-map/SKILL.md +51 -0
  17. package/.agents/skills/firecrawl-scrape/SKILL.md +69 -0
  18. package/.agents/skills/firecrawl-search/SKILL.md +60 -0
  19. package/.claude/hooks/memb-inject.mjs +6 -0
  20. package/CLAUDE.md +573 -0
  21. package/README.de.md +0 -8
  22. package/README.md +0 -8
  23. package/README.pt.md +0 -8
  24. package/assets/brand/ao-ant-mark.svg +91 -0
  25. package/assets/brand/bdb-core-mark.svg +34 -0
  26. package/assets/brand/heimdall-guardian-mark.svg +16 -0
  27. package/assets/brand/memb-crystal-mark.svg +18 -0
  28. package/bin/aos-config.mjs +89 -0
  29. package/bin/aos-dashboard.mjs +608 -0
  30. package/bin/aos-uninstall.mjs +227 -0
  31. package/docs/sessions/audit-2026-09-14-silent-failures.md +114 -0
  32. package/docs/skills_table.md +0 -3
  33. package/installer.js +428 -237
  34. package/mcps/RhinoMCP/cc-plugin/.claude/settings.json +10 -0
  35. package/mcps/after-effects-mcp/build/index.js +840 -0
  36. package/mcps/after-effects-mcp/build/scripts/applyEffect.jsx +153 -0
  37. package/mcps/after-effects-mcp/build/scripts/applyEffectTemplate.jsx +218 -0
  38. package/mcps/after-effects-mcp/build/scripts/createComposition.jsx +71 -0
  39. package/mcps/after-effects-mcp/build/scripts/createShapeLayer.jsx +147 -0
  40. package/mcps/after-effects-mcp/build/scripts/createSolidLayer.jsx +114 -0
  41. package/mcps/after-effects-mcp/build/scripts/createTextLayer.jsx +115 -0
  42. package/mcps/after-effects-mcp/build/scripts/getLayerInfo.jsx +192 -0
  43. package/mcps/after-effects-mcp/build/scripts/getProjectInfo.jsx +90 -0
  44. package/mcps/after-effects-mcp/build/scripts/listCompositions.jsx +50 -0
  45. package/mcps/after-effects-mcp/build/scripts/mcp-bridge-auto.jsx +1773 -0
  46. package/mcps/after-effects-mcp/build/scripts/setLayerProperties.jsx +160 -0
  47. package/mcps/computer-use-mcp/dist/client.d.ts +150 -0
  48. package/mcps/computer-use-mcp/dist/client.js +136 -0
  49. package/mcps/computer-use-mcp/dist/entrypoint.d.ts +16 -0
  50. package/mcps/computer-use-mcp/dist/entrypoint.js +26 -0
  51. package/mcps/computer-use-mcp/dist/native.d.ts +212 -0
  52. package/mcps/computer-use-mcp/dist/native.js +50 -0
  53. package/mcps/computer-use-mcp/dist/server.d.ts +32 -0
  54. package/mcps/computer-use-mcp/dist/server.js +342 -0
  55. package/mcps/computer-use-mcp/dist/session.d.ts +101 -0
  56. package/mcps/computer-use-mcp/dist/session.js +2372 -0
  57. package/package.json +13 -4
  58. package/skills/global_config/aos-project-init/SKILL.md +97 -130
  59. package/skills/global_config/aos-project-init/assets/openwikiignore.template +62 -0
  60. package/skills/global_config/aos-project-init/scripts/aos-project-doctor.mjs +38 -1
  61. package/skills/global_config/aos-setup/SKILL.md +110 -11
  62. package/skills/global_config/aos-setup/scripts/aos-doctor.mjs +48 -4
  63. package/skills/global_config/ask-tim/SKILL.md +2 -7
  64. package/skills/global_config/openwiki-skill/scripts/openwiki_daemon.py +65 -12
  65. package/bin/setup-saas.mjs +0 -792
  66. package/mcps/blender-mcp-server/.dockerignore +0 -19
  67. package/mcps/blender-mcp-server/.github/workflows/ci.yml +0 -67
  68. package/mcps/blender-mcp-server/.github/workflows/publish-pypi.yml +0 -54
  69. package/mcps/blender-mcp-server/CHANGELOG.md +0 -64
  70. package/mcps/blender-mcp-server/CONTRIBUTING.md +0 -107
  71. package/mcps/blender-mcp-server/Dockerfile +0 -19
  72. package/mcps/blender-mcp-server/LICENSE +0 -21
  73. package/mcps/blender-mcp-server/README.md +0 -409
  74. package/mcps/blender-mcp-server/addon/__init__.py +0 -1440
  75. package/mcps/blender-mcp-server/addon/models.py +0 -223
  76. package/mcps/blender-mcp-server/pyproject.toml +0 -120
  77. package/mcps/blender-mcp-server/scripts/blender_bridge_request.py +0 -71
  78. package/mcps/blender-mcp-server/scripts/blender_create_test_cube.py +0 -49
  79. package/mcps/blender-mcp-server/scripts/blender_scene_info.py +0 -38
  80. package/mcps/blender-mcp-server/scripts/build_addon_zip.sh +0 -29
  81. package/mcps/blender-mcp-server/scripts/demos/README.md +0 -186
  82. package/mcps/blender-mcp-server/scripts/demos/dam_break_scene.py +0 -276
  83. package/mcps/blender-mcp-server/scripts/demos/open_dam_break_gui.py +0 -33
  84. package/mcps/blender-mcp-server/scripts/demos/pipe_movement_study.py +0 -518
  85. package/mcps/blender-mcp-server/scripts/demos/pipe_pressure_failure_scene.py +0 -806
  86. package/mcps/blender-mcp-server/scripts/demos/procedural_dam_break_scene.py +0 -600
  87. package/mcps/blender-mcp-server/scripts/demos/run_dam_break.py +0 -510
  88. package/mcps/blender-mcp-server/scripts/launch_blender_gui.py +0 -41
  89. package/mcps/blender-mcp-server/scripts/library/README.md +0 -64
  90. package/mcps/blender-mcp-server/scripts/library/apply_transforms.py +0 -46
  91. package/mcps/blender-mcp-server/scripts/library/camera.py +0 -51
  92. package/mcps/blender-mcp-server/scripts/library/collections.py +0 -65
  93. package/mcps/blender-mcp-server/scripts/library/create_mesh.py +0 -41
  94. package/mcps/blender-mcp-server/scripts/library/effector.py +0 -48
  95. package/mcps/blender-mcp-server/scripts/library/fluid_domain.py +0 -80
  96. package/mcps/blender-mcp-server/scripts/library/fluid_inflow.py +0 -98
  97. package/mcps/blender-mcp-server/scripts/library/frame_range.py +0 -35
  98. package/mcps/blender-mcp-server/scripts/library/keyframes.py +0 -59
  99. package/mcps/blender-mcp-server/scripts/library/rigid_body.py +0 -52
  100. package/mcps/blender-mcp-server/scripts/library/save_blend.py +0 -40
  101. package/mcps/blender-mcp-server/scripts/server_start.sh +0 -26
  102. package/mcps/blender-mcp-server/src/blender_mcp_server/__init__.py +0 -3
  103. package/mcps/blender-mcp-server/src/blender_mcp_server/headless.py +0 -330
  104. package/mcps/blender-mcp-server/src/blender_mcp_server/server.py +0 -606
  105. package/mcps/davinci-mcp-professional/.bandit +0 -35
  106. package/mcps/davinci-mcp-professional/.claude/commands/security-review.md +0 -191
  107. package/mcps/davinci-mcp-professional/.claude/settings.json +0 -1
  108. package/mcps/davinci-mcp-professional/.editorconfig +0 -27
  109. package/mcps/davinci-mcp-professional/.gitattributes +0 -207
  110. package/mcps/davinci-mcp-professional/.github/CODEOWNERS +0 -2
  111. package/mcps/davinci-mcp-professional/.github/ISSUE_TEMPLATE/bug_report.md +0 -33
  112. package/mcps/davinci-mcp-professional/.github/ISSUE_TEMPLATE/feature_request.md +0 -19
  113. package/mcps/davinci-mcp-professional/.github/PULL_REQUEST_TEMPLATE.md +0 -20
  114. package/mcps/davinci-mcp-professional/.github/SECURITY.md +0 -97
  115. package/mcps/davinci-mcp-professional/.github/dependabot.yml +0 -27
  116. package/mcps/davinci-mcp-professional/.github/workflows/ci.yml +0 -39
  117. package/mcps/davinci-mcp-professional/ATTRIBUTION.md +0 -4
  118. package/mcps/davinci-mcp-professional/AUTHORS.md +0 -9
  119. package/mcps/davinci-mcp-professional/BUGS.md +0 -55
  120. package/mcps/davinci-mcp-professional/CLAUDE.md +0 -229
  121. package/mcps/davinci-mcp-professional/CONTRIBUTING.md +0 -51
  122. package/mcps/davinci-mcp-professional/COPYING.md +0 -228
  123. package/mcps/davinci-mcp-professional/Doxyfile +0 -379
  124. package/mcps/davinci-mcp-professional/README.md +0 -143
  125. package/mcps/davinci-mcp-professional/SECURITY.md +0 -40
  126. package/mcps/davinci-mcp-professional/USING.md +0 -301
  127. package/mcps/davinci-mcp-professional/VERSION.md +0 -13
  128. package/mcps/davinci-mcp-professional/build.py +0 -169
  129. package/mcps/davinci-mcp-professional/claude_desktop_config_template.json +0 -11
  130. package/mcps/davinci-mcp-professional/hooks/ci-check.sh +0 -29
  131. package/mcps/davinci-mcp-professional/hooks/pre-push +0 -46
  132. package/mcps/davinci-mcp-professional/main.py +0 -40
  133. package/mcps/davinci-mcp-professional/mcp_server.py +0 -30
  134. package/mcps/davinci-mcp-professional/pyproject.toml +0 -115
  135. package/mcps/davinci-mcp-professional/security_audit.py +0 -379
  136. package/mcps/davinci-mcp-professional/src/davinci_mcp/__init__.py +0 -19
  137. package/mcps/davinci-mcp-professional/src/davinci_mcp/cli.py +0 -138
  138. package/mcps/davinci-mcp-professional/src/davinci_mcp/resolve_client.py +0 -342
  139. package/mcps/davinci-mcp-professional/src/davinci_mcp/resources/__init__.py +0 -60
  140. package/mcps/davinci-mcp-professional/src/davinci_mcp/server.py +0 -185
  141. package/mcps/davinci-mcp-professional/src/davinci_mcp/tools/__init__.py +0 -146
  142. package/mcps/davinci-mcp-professional/src/davinci_mcp/types.py +0 -125
  143. package/mcps/davinci-mcp-professional/src/davinci_mcp/utils/__init__.py +0 -19
  144. package/mcps/davinci-mcp-professional/src/davinci_mcp/utils/platform.py +0 -239
  145. package/mcps/davinci-mcp-professional/test.py +0 -186
  146. package/mcps/davinci-mcp-professional/uv.lock +0 -2073
  147. package/mcps/davinci-resolve-mcp/.claude/skills/media-analysis.md +0 -44
  148. package/mcps/davinci-resolve-mcp/.clinerules +0 -17
  149. package/mcps/davinci-resolve-mcp/.cursorrules +0 -17
  150. package/mcps/davinci-resolve-mcp/.github/copilot-instructions.md +0 -17
  151. package/mcps/davinci-resolve-mcp/.github/workflows/npm-publish.yml +0 -109
  152. package/mcps/davinci-resolve-mcp/.windsurfrules +0 -17
  153. package/mcps/davinci-resolve-mcp/AGENTS.md +0 -114
  154. package/mcps/davinci-resolve-mcp/CHANGELOG.md +0 -2648
  155. package/mcps/davinci-resolve-mcp/CLAUDE.md +0 -15
  156. package/mcps/davinci-resolve-mcp/LICENSE +0 -21
  157. package/mcps/davinci-resolve-mcp/README.md +0 -173
  158. package/mcps/davinci-resolve-mcp/SECURITY.md +0 -53
  159. package/mcps/davinci-resolve-mcp/bin/davinci-resolve-mcp.mjs +0 -450
  160. package/mcps/davinci-resolve-mcp/examples/README.md +0 -53
  161. package/mcps/davinci-resolve-mcp/examples/markers/README.md +0 -81
  162. package/mcps/davinci-resolve-mcp/examples/media/README.md +0 -94
  163. package/mcps/davinci-resolve-mcp/examples/timeline/README.md +0 -98
  164. package/mcps/davinci-resolve-mcp/install.py +0 -1687
  165. package/mcps/davinci-resolve-mcp/package.json +0 -52
  166. package/mcps/davinci-resolve-mcp/release-notes/v2.22.0.md +0 -51
  167. package/mcps/davinci-resolve-mcp/release-notes/v2.23.0.md +0 -51
  168. package/mcps/davinci-resolve-mcp/release-notes/v2.23.1.md +0 -35
  169. package/mcps/davinci-resolve-mcp/release-notes/v2.24.1.md +0 -32
  170. package/mcps/davinci-resolve-mcp/scripts/audit_api_parity.py +0 -275
  171. package/mcps/davinci-resolve-mcp/scripts/audit_readwrite_symmetry.py +0 -80
  172. package/mcps/davinci-resolve-mcp/scripts/doctor.py +0 -227
  173. package/mcps/davinci-resolve-mcp/scripts/gen_api_limitations.py +0 -144
  174. package/mcps/davinci-resolve-mcp/scripts/live_media_analysis_polish_probe.py +0 -65
  175. package/mcps/davinci-resolve-mcp/scripts/measure_bridge_cost.py +0 -65
  176. package/mcps/davinci-resolve-mcp/scripts/regen_panel_screenshots.py +0 -76
  177. package/mcps/davinci-resolve-mcp/src/__init__.py +0 -3
  178. package/mcps/davinci-resolve-mcp/src/analysis_dashboard.py +0 -15505
  179. package/mcps/davinci-resolve-mcp/src/batch_cli.py +0 -540
  180. package/mcps/davinci-resolve-mcp/src/control_panel.py +0 -13
  181. package/mcps/davinci-resolve-mcp/src/granular/__init__.py +0 -17
  182. package/mcps/davinci-resolve-mcp/src/granular/common.py +0 -741
  183. package/mcps/davinci-resolve-mcp/src/granular/folder.py +0 -420
  184. package/mcps/davinci-resolve-mcp/src/granular/gallery.py +0 -306
  185. package/mcps/davinci-resolve-mcp/src/granular/graph.py +0 -309
  186. package/mcps/davinci-resolve-mcp/src/granular/media_pool.py +0 -679
  187. package/mcps/davinci-resolve-mcp/src/granular/media_pool_item.py +0 -1020
  188. package/mcps/davinci-resolve-mcp/src/granular/media_storage.py +0 -179
  189. package/mcps/davinci-resolve-mcp/src/granular/project.py +0 -1654
  190. package/mcps/davinci-resolve-mcp/src/granular/resolve_control.py +0 -538
  191. package/mcps/davinci-resolve-mcp/src/granular/timeline.py +0 -1075
  192. package/mcps/davinci-resolve-mcp/src/granular/timeline_item.py +0 -2251
  193. package/mcps/davinci-resolve-mcp/src/resolve_mcp_server.py +0 -43
  194. package/mcps/davinci-resolve-mcp/src/server.py +0 -24116
  195. package/mcps/davinci-resolve-mcp/src/utils/__init__.py +0 -3
  196. package/mcps/davinci-resolve-mcp/src/utils/actor_identity.py +0 -46
  197. package/mcps/davinci-resolve-mcp/src/utils/analysis_caps.py +0 -678
  198. package/mcps/davinci-resolve-mcp/src/utils/analysis_memory.py +0 -755
  199. package/mcps/davinci-resolve-mcp/src/utils/analysis_runs.py +0 -307
  200. package/mcps/davinci-resolve-mcp/src/utils/analysis_store.py +0 -945
  201. package/mcps/davinci-resolve-mcp/src/utils/api_truth.py +0 -525
  202. package/mcps/davinci-resolve-mcp/src/utils/app_control.py +0 -319
  203. package/mcps/davinci-resolve-mcp/src/utils/audio_fairlight_live_probe.py +0 -263
  204. package/mcps/davinci-resolve-mcp/src/utils/brain_edits.py +0 -387
  205. package/mcps/davinci-resolve-mcp/src/utils/bridge_metrics.py +0 -76
  206. package/mcps/davinci-resolve-mcp/src/utils/cdl.py +0 -20
  207. package/mcps/davinci-resolve-mcp/src/utils/clip_query.py +0 -85
  208. package/mcps/davinci-resolve-mcp/src/utils/cloud_operations.py +0 -192
  209. package/mcps/davinci-resolve-mcp/src/utils/color_grade_live_probe.py +0 -444
  210. package/mcps/davinci-resolve-mcp/src/utils/contracts.py +0 -102
  211. package/mcps/davinci-resolve-mcp/src/utils/cut_ir.py +0 -115
  212. package/mcps/davinci-resolve-mcp/src/utils/dctl_templates.py +0 -368
  213. package/mcps/davinci-resolve-mcp/src/utils/deep_vision.py +0 -643
  214. package/mcps/davinci-resolve-mcp/src/utils/destructive_hook.py +0 -606
  215. package/mcps/davinci-resolve-mcp/src/utils/edit_engine.py +0 -737
  216. package/mcps/davinci-resolve-mcp/src/utils/embeddings.py +0 -922
  217. package/mcps/davinci-resolve-mcp/src/utils/entities.py +0 -579
  218. package/mcps/davinci-resolve-mcp/src/utils/extension_authoring_live_probe.py +0 -292
  219. package/mcps/davinci-resolve-mcp/src/utils/failure_tracker.py +0 -119
  220. package/mcps/davinci-resolve-mcp/src/utils/fuse_templates.py +0 -1968
  221. package/mcps/davinci-resolve-mcp/src/utils/fusion_composition_live_probe.py +0 -284
  222. package/mcps/davinci-resolve-mcp/src/utils/fusion_group_settings.py +0 -334
  223. package/mcps/davinci-resolve-mcp/src/utils/layout_presets.py +0 -333
  224. package/mcps/davinci-resolve-mcp/src/utils/mcp_stdio.py +0 -32
  225. package/mcps/davinci-resolve-mcp/src/utils/mcp_transport.py +0 -128
  226. package/mcps/davinci-resolve-mcp/src/utils/media_analysis.py +0 -7690
  227. package/mcps/davinci-resolve-mcp/src/utils/media_analysis_jobs.py +0 -805
  228. package/mcps/davinci-resolve-mcp/src/utils/media_pool_changes.py +0 -121
  229. package/mcps/davinci-resolve-mcp/src/utils/media_pool_ingest_live_probe.py +0 -592
  230. package/mcps/davinci-resolve-mcp/src/utils/multicam.py +0 -393
  231. package/mcps/davinci-resolve-mcp/src/utils/object_inspection.py +0 -301
  232. package/mcps/davinci-resolve-mcp/src/utils/page_lock.py +0 -75
  233. package/mcps/davinci-resolve-mcp/src/utils/platform.py +0 -157
  234. package/mcps/davinci-resolve-mcp/src/utils/proc.py +0 -26
  235. package/mcps/davinci-resolve-mcp/src/utils/project_cleanup.py +0 -73
  236. package/mcps/davinci-resolve-mcp/src/utils/project_lifecycle_live_probe.py +0 -376
  237. package/mcps/davinci-resolve-mcp/src/utils/project_lint.py +0 -131
  238. package/mcps/davinci-resolve-mcp/src/utils/project_properties.py +0 -601
  239. package/mcps/davinci-resolve-mcp/src/utils/project_spec.py +0 -459
  240. package/mcps/davinci-resolve-mcp/src/utils/readback.py +0 -91
  241. package/mcps/davinci-resolve-mcp/src/utils/render_deliver_live_probe.py +0 -384
  242. package/mcps/davinci-resolve-mcp/src/utils/resolve_ai_governance.py +0 -214
  243. package/mcps/davinci-resolve-mcp/src/utils/resolve_ai_ledger.py +0 -244
  244. package/mcps/davinci-resolve-mcp/src/utils/resolve_busy.py +0 -171
  245. package/mcps/davinci-resolve-mcp/src/utils/resolve_connection.py +0 -77
  246. package/mcps/davinci-resolve-mcp/src/utils/review_annotation_live_probe.py +0 -352
  247. package/mcps/davinci-resolve-mcp/src/utils/script_templates.py +0 -1193
  248. package/mcps/davinci-resolve-mcp/src/utils/shot_relationships.py +0 -544
  249. package/mcps/davinci-resolve-mcp/src/utils/structural_diff.py +0 -175
  250. package/mcps/davinci-resolve-mcp/src/utils/sync_detection.py +0 -889
  251. package/mcps/davinci-resolve-mcp/src/utils/timeline_brain_db.py +0 -826
  252. package/mcps/davinci-resolve-mcp/src/utils/timeline_conform_live_probe.py +0 -280
  253. package/mcps/davinci-resolve-mcp/src/utils/timeline_kernel_live_probe.py +0 -1092
  254. package/mcps/davinci-resolve-mcp/src/utils/timeline_kernel_probe.py +0 -185
  255. package/mcps/davinci-resolve-mcp/src/utils/timeline_title_text.py +0 -87
  256. package/mcps/davinci-resolve-mcp/src/utils/timeline_versioning.py +0 -730
  257. package/mcps/davinci-resolve-mcp/src/utils/update_check.py +0 -685
  258. package/mcps/vectorworks-mcp/.dockerignore +0 -8
  259. package/mcps/vectorworks-mcp/Dockerfile +0 -28
  260. package/mcps/vectorworks-mcp/README.md +0 -156
  261. package/mcps/vectorworks-mcp/app/__init__.py +0 -2
  262. package/mcps/vectorworks-mcp/app/api.py +0 -52
  263. package/mcps/vectorworks-mcp/app/chunking.py +0 -56
  264. package/mcps/vectorworks-mcp/app/config.py +0 -29
  265. package/mcps/vectorworks-mcp/app/embeddings.py +0 -28
  266. package/mcps/vectorworks-mcp/app/indexer.py +0 -106
  267. package/mcps/vectorworks-mcp/app/main.py +0 -33
  268. package/mcps/vectorworks-mcp/app/mcp_server.py +0 -71
  269. package/mcps/vectorworks-mcp/app/search.py +0 -54
  270. package/mcps/vectorworks-mcp/app/utils.py +0 -14
  271. package/mcps/vectorworks-mcp/data/.gitkeep +0 -1
  272. package/mcps/vectorworks-mcp/data/vw-app-help/VW2022_PluginScript.htm +0 -95
  273. package/mcps/vectorworks-mcp/data/vw-app-help/VW2022_ScriptEditor.htm +0 -266
  274. package/mcps/vectorworks-mcp/data/vw-app-help/VW2022_Scripting.htm +0 -106
  275. package/mcps/vectorworks-mcp/data/vw-app-help/VW2023_CreatingScriptedPlugins.htm +0 -327
  276. package/mcps/vectorworks-mcp/data/vw-app-help/VW2024_RunningScripts.htm +0 -116
  277. package/mcps/vectorworks-mcp/data/vw-devwiki/VS_Function_Reference_category.html +0 -2129
  278. package/mcps/vectorworks-mcp/data/vw-jp-ref/ObjectsSymbols.html +0 -2035
  279. package/mcps/vectorworks-mcp/data/vw-jp-ref/ScriptFunctionReference.html +0 -29
  280. package/mcps/vectorworks-mcp/design.md +0 -57
  281. package/mcps/vectorworks-mcp/docker-compose.yml +0 -18
  282. package/mcps/vectorworks-mcp/index/.gitkeep +0 -1
  283. package/mcps/vectorworks-mcp/index/meta.jsonl +0 -3956
  284. package/mcps/vectorworks-mcp/index/vw.faiss +0 -0
  285. package/mcps/vectorworks-mcp/requirements.txt +0 -10
  286. package/mcps/vectorworks-mcp/scripts/fetch_docs_minimal.sh +0 -84
  287. package/mcps/vectorworks-mcp/scripts/fetch_github_vectorworks.sh +0 -85
  288. package/mcps/vectorworks-mcp/templates/index.html +0 -40
  289. package/scripts/ecosystem-health-audit.js +0 -257
  290. package/skills/bdb-dev-os-skill/SKILL.md +0 -49
  291. package/skills/bdb-dev-os-skill/package.json +0 -11
  292. package/skills/bdbsaastraining/SKILL.md +0 -316
  293. package/skills/bdbsaastraining/references/exam-pool.md +0 -313
  294. package/skills/bdbsaastraining/references/interaction-modes.md +0 -94
  295. package/skills/bdbsaastraining/references/track-a-ai-agent.md +0 -111
  296. package/skills/bdbsaastraining/references/track-b-wordpress.md +0 -111
  297. package/skills/bdbsaastraining/references/track-c-mailserver.md +0 -107
  298. package/skills/bdbsaastraining/references/track-d-debian.md +0 -109
  299. package/skills/bdbsaastraining/references/track-e-custom.md +0 -83
  300. package/skills/bdbsaastraining/scripts/build_profile.py +0 -529
  301. package/skills/bdbsaastraining/scripts/generate_certificate.py +0 -161
  302. package/skills/bdbsaastraining/scripts/preflight_check.sh +0 -150
  303. package/skills/bdbsaastraining/templates/certificate_template.html +0 -508
  304. package/skills/global_config/bdb-ecosystem-health/SKILL.md +0 -68
  305. package/skills/global_config/bdbsaas-ops/SKILL.md +0 -16
  306. package/skills/global_config/bdbsaashost/SKILL.md +0 -125
@@ -1,28 +0,0 @@
1
- FROM python:3.11-slim
2
-
3
- ENV PYTHONDONTWRITEBYTECODE=1 \
4
- PYTHONUNBUFFERED=1
5
-
6
- WORKDIR /app
7
-
8
- # System deps for faiss/numpy
9
- RUN apt-get update && apt-get install -y --no-install-recommends \
10
- build-essential \
11
- g++ \
12
- libopenblas-dev \
13
- git \
14
- curl \
15
- ca-certificates \
16
- && rm -rf /var/lib/apt/lists/*
17
-
18
- COPY requirements.txt ./
19
- RUN pip install --no-cache-dir -r requirements.txt
20
-
21
- COPY . .
22
-
23
- # Default directories
24
- RUN mkdir -p /app/data /app/index
25
-
26
- EXPOSE 8000 8765
27
-
28
- CMD ["python", "-m", "app.main"]
@@ -1,156 +0,0 @@
1
- # Vectorworks RAG + MCP
2
-
3
- - Vectorworks の Python / VectorScript ドキュメントをローカルに取り込み、FAISS で横断検索します。
4
- - FastAPI で `/search` `/answer` `/get` を提供し、簡易 Web UI から検索・出典確認できます。
5
- - WebSocket(JSON-RPC 2.0) の MCP サーバーを同時起動し、`vw.search` / `vw.answer` / `vw.get` ツールを提供します。
6
- - docker compose で `app`(API/MCP)と `db`(Postgres 16)を同時起動します
7
-
8
- ---
9
-
10
- ## 必要要件
11
-
12
- - Docker / Docker Compose(v2)
13
-
14
- ## クイックスタート
15
-
16
- 1. ビルド
17
-
18
- - `docker compose build`
19
-
20
- 2. 文書取得
21
-
22
- - `docker compose run --rm app bash scripts/fetch_docs_minimal.sh`
23
- - `docker compose run --rm -e GITHUB_TOKEN="$GITHUB_TOKEN" app bash scripts/fetch_github_vectorworks.sh`
24
-
25
- 3. ベクター生成(埋め込み + FAISS)
26
-
27
- - `docker compose run --rm app python -m app.indexer`
28
- - 既にインデックスがある状態でドキュメントを追加した場合は再作成してください:
29
- - `docker compose run --rm app python -m app.indexer --rebuild`
30
-
31
- 4. 起動(UI + MCP + Postgres)
32
-
33
- - `docker compose up`
34
-
35
- 5. アクセス
36
-
37
- - UI: `http://localhost:8000`
38
- - MCP: `ws://localhost:8765`
39
-
40
- 補足
41
-
42
- - 2. と 3) は次のワンライナーでも可:
43
- - `docker compose run --rm app bash -lc 'scripts/fetch_docs_minimal.sh && python -m app.indexer'`
44
-
45
- ## ドキュメントの取得
46
-
47
- 以下のコマンドで、必要最小限のドキュメント(md/html のみ)を `data/` に取得します。
48
-
49
- - 依存: `git`, `curl`
50
- - 実行(コンテナ内):
51
- - `docker compose run --rm app bash scripts/fetch_docs_minimal.sh`
52
- - ネットワーク事情で 403 が発生する場合、スクリプトは該当ページをスキップして続行します。
53
- - 必要なら UA を上書き可能: `docker compose run --rm -e UA="Mozilla/5.0 ..." app bash scripts/fetch_docs_minimal.sh`
54
-
55
- 取得対象(要点のみ)
56
-
57
- - GitHub: Vectorworks/developer-scripting(入門/導線の Markdown)
58
- - App Help: Scripting の基本導線(2022/2023/2024 の要点ページ)
59
- - 日本語サイト: VectorScript 関数索引ページ + 例示ページ
60
- - Developer Wiki: VS Function Reference カテゴリインデックス(HTML)
61
-
62
- 注意
63
-
64
- - インデクサは `.md` `.markdown` `.html` `.htm` `.txt` のみ対応です。PDF 等は対象外です。
65
-
66
- ## GitHub(Vectorworks 指定リポのみ取得)
67
-
68
- - 目的: 次の3つのリポジトリのみを `data/github/vectorworks/` にクローン(または更新)します。
69
- - `Vectorworks/developer-scripting`
70
- - `Vectorworks/developer-sdk`
71
- - `Vectorworks/developer-worksheets`
72
- - 実行(コンテナ内):
73
- - `docker compose run --rm app bash scripts/fetch_github_vectorworks.sh`
74
- - 取得先: `data/github/vectorworks/<repo>`
75
- - 追加/変更したい場合は環境変数 `REPOS` で指定できます(スペースまたはカンマ区切り)。
76
- - 例: `docker compose run --rm -e REPOS="Vectorworks/developer-scripting,Vectorworks/developer-sdk" app bash scripts/fetch_github_vectorworks.sh`
77
- - 更新方式の指定(任意): `UPDATE_MODE=pull`(既定)または `UPDATE_MODE=reset`
78
- - `pull`: `git pull --ff-only --depth=1 --prune` による高速更新(ローカル変更がある場合は失敗→フェールセーフで fetch+reset)
79
- - `reset`: `fetch --depth=1` 後に `reset --hard` で完全同期(ローカル変更を破棄)
80
-
81
- 注意
82
-
83
- - インデクサはテキスト系拡張子(.md/.html/.txt 等)のみ対象とします。
84
-
85
- ## ベクター生成(埋め込み + FAISS インデックス)
86
-
87
- - 実行(コンテナ内):
88
- - `docker compose run --rm app python -m app.indexer`
89
-
90
- 実行後、`index/` に `vw.faiss` と `meta.jsonl` が作成されます。
91
- (先に `bash scripts/fetch_docs_minimal.sh` などで `data/` に文書がある状態にしてください)
92
-
93
- ## 起動(UI + MCP + Postgres)
94
-
95
- - `docker compose up --build`
96
- - UI: `http://localhost:8000`
97
- - MCP: `ws://localhost:8765`
98
- - Postgres はコンテナ内部ネットワークで起動(ホストへ未公開)
99
-
100
- ## API 例
101
-
102
- - 検索: `GET /search?q=PushAttrs&k=6`
103
- - 例: `curl -s "http://localhost:8000/search?q=VectorScript&k=6" | jq .`
104
- - 回答(ドラフト): `GET /answer?q=...&k=6`
105
- - 例: `curl -s "http://localhost:8000/answer?q=record+format" | jq .`
106
- - チャンク取得: `GET /get?doc_id=...&chunk_id=...`
107
-
108
- UI は `GET /` にあり、検索フォームから同等の結果を確認できます。
109
-
110
- ## MCP(Model Context Protocol)
111
-
112
- - VS Code から接続: 次のコマンドで MCP を追加
113
- - `code --add-mcp '{"name":"vw_docs_local","url":"ws://localhost:8765"}'`
114
- - サポートするツール
115
- - `vw.search({ query, k? })`
116
- - `vw.answer({ query, k? })`
117
- - `vw.get({ doc_id, chunk_id })`
118
-
119
- 実装は JSON-RPC 2.0 ベースの WebSocket サーバーです(`app/mcp_server.py`)。
120
-
121
- ## ディレクトリ構成
122
-
123
- - `app/` アプリ本体
124
- - `api.py` FastAPI アプリ
125
- - `mcp_server.py` MCP(WebSocket) サーバー
126
- - `indexer.py` 取込・ベクター化(埋め込み + FAISS 作成)
127
- - `search.py` 検索/回答のコアロジック
128
- - `chunking.py` チャンク分割(約 700 トークン相当の文字長を目安)
129
- - `templates/` Web UI テンプレート
130
- - `data/` 原文の md/html(相対パスが `doc_id`)
131
- - `index/` FAISS とメタデータ(`vw.faiss`, `meta.jsonl`)
132
-
133
- ## 環境変数(任意)
134
-
135
- - `DATA_DIR` データ配置ディレクトリ(既定: `data`)
136
- - `INDEX_DIR` インデックス出力ディレクトリ(既定: `index`)
137
- - `EMBED_MODEL` 埋め込みモデル(既定: `sentence-transformers/all-MiniLM-L6-v2`)
138
- - `CHUNK_CHARS` チャンク文字長の目安(既定: `2800` ≒ 700 トークン)
139
- - `CHUNK_OVERLAP` チャンクの文字オーバーラップ(既定: `480`)
140
- - `API_HOST` / `API_PORT` FastAPI バインド(既定: `0.0.0.0:8000`)
141
- - `MCP_HOST` / `MCP_PORT` MCP バインド(既定: `0.0.0.0:8765`)
142
-
143
- Postgres(将来用)
144
-
145
- - `PGHOST` / `PGPORT` / `PGDATABASE` / `PGUSER` / `PGPASSWORD`
146
-
147
- ## 運用メモ
148
-
149
- - ドキュメントを更新したら、再度ベクター生成: `python -m app.indexer`
150
- - 初回は埋め込みモデルのダウンロードで時間がかかる場合があります。
151
- - CPU で実行する前提のため、FAISS は `IndexFlatIP` + 正規化ベクター(cosine 相当)を使用しています。
152
-
153
- ## ライセンス / 注意
154
-
155
- - このリポジトリはドキュメントを含みません。各自の利用規約・著作権に従って `data/` に配置してください。
156
- - `answer` は抜粋ベースの簡易ドラフトです。最終判断は原文を確認してください。
@@ -1,2 +0,0 @@
1
- __all__ = []
2
-
@@ -1,52 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from pathlib import Path
4
- from typing import Optional
5
-
6
- from fastapi import FastAPI, HTTPException, Query, Request
7
- from fastapi.responses import HTMLResponse
8
- from fastapi.templating import Jinja2Templates
9
-
10
- from .config import settings
11
- from .embeddings import Embedder
12
- from .indexer import IndexPaths, ensure_index
13
- from .search import Searcher
14
-
15
-
16
- def create_app() -> FastAPI:
17
- app = FastAPI(title="Vectorworks Docs RAG")
18
-
19
- templates = Jinja2Templates(directory=str(Path("templates")))
20
-
21
- embedder = Embedder()
22
- index, meta = ensure_index(embedder)
23
- searcher = Searcher(index=index, meta=meta, embedder=embedder)
24
-
25
- @app.get("/", response_class=HTMLResponse)
26
- async def home(request: Request, q: Optional[str] = None, k: int = 6):
27
- results = searcher.search(q, k=k) if q else []
28
- return templates.TemplateResponse(
29
- "index.html",
30
- {"request": request, "q": q or "", "results": results},
31
- )
32
-
33
- @app.get("/search")
34
- async def api_search(q: str = Query(...), k: int = 6):
35
- return {"query": q, "results": searcher.search(q, k=k)}
36
-
37
- @app.get("/answer")
38
- async def api_answer(q: str = Query(...), k: int = 6):
39
- return searcher.answer(q, k=k)
40
-
41
- @app.get("/get")
42
- async def api_get(doc_id: str, chunk_id: int):
43
- try:
44
- return searcher.get(doc_id, chunk_id)
45
- except KeyError as e:
46
- raise HTTPException(status_code=404, detail=str(e))
47
-
48
- return app
49
-
50
-
51
- app = create_app()
52
-
@@ -1,56 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import re
4
- from typing import Iterable, List
5
-
6
-
7
- def split_paragraphs(text: str) -> List[str]:
8
- # Normalize line endings and split on blank lines
9
- parts = re.split(r"\n\s*\n+", text.strip())
10
- return [p.strip() for p in parts if p.strip()]
11
-
12
-
13
- def merge_to_chunks(paragraphs: Iterable[str], max_chars: int, overlap: int) -> List[str]:
14
- chunks: List[str] = []
15
- buf: List[str] = []
16
- buf_len = 0
17
-
18
- for p in paragraphs:
19
- # If a single paragraph is larger than max, hard-split by sentences
20
- if len(p) > max_chars:
21
- sentences = re.split(r"(?<=[。..!?])\s+", p)
22
- p_parts: List[str] = []
23
- cur = ""
24
- for s in sentences:
25
- if not s:
26
- continue
27
- if len(cur) + len(s) + 1 > max_chars and cur:
28
- p_parts.append(cur)
29
- cur = s
30
- else:
31
- cur = (cur + " " + s).strip()
32
- if cur:
33
- p_parts.append(cur)
34
- else:
35
- p_parts = [p]
36
-
37
- for part in p_parts:
38
- if buf_len + len(part) + 2 > max_chars and buf:
39
- chunks.append("\n\n".join(buf))
40
- # overlap by characters from the end of the previous chunk
41
- if overlap > 0:
42
- tail = chunks[-1][-overlap:]
43
- buf = [tail, part]
44
- buf_len = len(tail) + len(part) + 2
45
- else:
46
- buf = [part]
47
- buf_len = len(part)
48
- else:
49
- buf.append(part)
50
- buf_len += len(part) + 2
51
-
52
- if buf:
53
- chunks.append("\n\n".join(buf))
54
-
55
- return chunks
56
-
@@ -1,29 +0,0 @@
1
- import os
2
- from dataclasses import dataclass
3
-
4
-
5
- @dataclass
6
- class Settings:
7
- # Paths
8
- data_dir: str = os.getenv("DATA_DIR", "data")
9
- index_dir: str = os.getenv("INDEX_DIR", "index")
10
- index_file: str = os.getenv("INDEX_FILE", "vw.faiss")
11
- meta_file: str = os.getenv("META_FILE", "meta.jsonl")
12
-
13
- # Embeddings
14
- model_name: str = os.getenv("EMBED_MODEL", "sentence-transformers/all-MiniLM-L6-v2")
15
- batch_size: int = int(os.getenv("EMBED_BATCH", "32"))
16
-
17
- # Chunking
18
- chunk_chars: int = int(os.getenv("CHUNK_CHARS", "2800"))
19
- chunk_overlap: int = int(os.getenv("CHUNK_OVERLAP", "480"))
20
-
21
- # API / MCP
22
- api_host: str = os.getenv("API_HOST", "0.0.0.0")
23
- api_port: int = int(os.getenv("API_PORT", "8000"))
24
- mcp_host: str = os.getenv("MCP_HOST", "0.0.0.0")
25
- mcp_port: int = int(os.getenv("MCP_PORT", "8765"))
26
-
27
-
28
- settings = Settings()
29
-
@@ -1,28 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass
4
- from typing import List
5
-
6
- import numpy as np
7
- from sentence_transformers import SentenceTransformer
8
-
9
- from .config import settings
10
-
11
-
12
- @dataclass
13
- class Embedder:
14
- model_name: str = settings.model_name
15
- batch_size: int = settings.batch_size
16
-
17
- def __post_init__(self):
18
- self.model = SentenceTransformer(self.model_name, device="cpu")
19
-
20
- def encode(self, texts: List[str]) -> np.ndarray:
21
- vectors = self.model.encode(
22
- texts,
23
- batch_size=self.batch_size,
24
- show_progress_bar=False,
25
- normalize_embeddings=True, # cosine via dot product
26
- )
27
- return np.asarray(vectors, dtype=np.float32)
28
-
@@ -1,106 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import argparse
4
- import json
5
- from dataclasses import dataclass
6
- from pathlib import Path
7
- from typing import List, Tuple
8
-
9
- import faiss # type: ignore
10
- import numpy as np
11
-
12
- from .chunking import merge_to_chunks, split_paragraphs
13
- from .config import settings
14
- from .embeddings import Embedder
15
- from .utils import iter_text_files
16
-
17
-
18
- @dataclass
19
- class IndexPaths:
20
- base: Path
21
- index_file: Path
22
- meta_file: Path
23
-
24
- @staticmethod
25
- def from_settings() -> "IndexPaths":
26
- base = Path(settings.index_dir)
27
- return IndexPaths(
28
- base=base,
29
- index_file=base / settings.index_file,
30
- meta_file=base / settings.meta_file,
31
- )
32
-
33
-
34
- def build_index(data_dir: Path, index_paths: IndexPaths, embedder: Embedder) -> Tuple[faiss.Index, List[dict]]:
35
- index_paths.base.mkdir(parents=True, exist_ok=True)
36
-
37
- texts: List[str] = []
38
- meta: List[dict] = []
39
-
40
- for src in iter_text_files(data_dir):
41
- rel = src.relative_to(data_dir).as_posix()
42
- content = src.read_text(encoding="utf-8", errors="ignore")
43
- paragraphs = split_paragraphs(content)
44
- chunks = merge_to_chunks(paragraphs, settings.chunk_chars, settings.chunk_overlap)
45
- for i, chunk in enumerate(chunks):
46
- texts.append(chunk)
47
- meta.append({"doc_id": rel, "chunk_id": i, "text": chunk})
48
-
49
- if not texts:
50
- raise RuntimeError(f"No ingestable files found under {data_dir}")
51
-
52
- vectors = embedder.encode(texts)
53
- dim = vectors.shape[1]
54
- index = faiss.IndexFlatIP(dim)
55
- index.add(vectors)
56
-
57
- # persist
58
- faiss.write_index(index, str(index_paths.index_file))
59
- with index_paths.meta_file.open("w", encoding="utf-8") as f:
60
- for m in meta:
61
- f.write(json.dumps(m, ensure_ascii=False) + "\n")
62
-
63
- return index, meta
64
-
65
-
66
- def load_index(index_paths: IndexPaths) -> Tuple[faiss.Index, List[dict]]:
67
- index = faiss.read_index(str(index_paths.index_file))
68
- meta: List[dict] = []
69
- with index_paths.meta_file.open("r", encoding="utf-8") as f:
70
- for line in f:
71
- meta.append(json.loads(line))
72
- return index, meta
73
-
74
-
75
- def ensure_index(embedder: Embedder) -> Tuple[faiss.Index, List[dict]]:
76
- data_dir = Path(settings.data_dir)
77
- index_paths = IndexPaths.from_settings()
78
- if not index_paths.index_file.exists() or not index_paths.meta_file.exists():
79
- return build_index(data_dir, index_paths, embedder)
80
- return load_index(index_paths)
81
-
82
-
83
- def main():
84
- parser = argparse.ArgumentParser(description="Build or rebuild FAISS index from data/")
85
- parser.add_argument(
86
- "--rebuild",
87
- action="store_true",
88
- help="Force rebuild index from scratch (ignores existing index files)",
89
- )
90
- args = parser.parse_args()
91
-
92
- emb = Embedder()
93
- data_dir = Path(settings.data_dir)
94
- index_paths = IndexPaths.from_settings()
95
-
96
- if args.rebuild:
97
- index_paths.base.mkdir(parents=True, exist_ok=True)
98
- idx, meta = build_index(data_dir, index_paths, emb)
99
- else:
100
- idx, meta = ensure_index(emb)
101
-
102
- print(f"Indexed {len(meta)} chunks → {settings.index_dir}/{settings.index_file}")
103
-
104
-
105
- if __name__ == "__main__":
106
- main()
@@ -1,33 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import asyncio
4
- import contextlib
5
-
6
- import uvicorn
7
-
8
- from .api import app as fastapi_app
9
- from .config import settings
10
- from .mcp_server import run_server as run_mcp
11
-
12
-
13
- async def main_async():
14
- config = uvicorn.Config(fastapi_app, host=settings.api_host, port=settings.api_port, log_level="info")
15
- server = uvicorn.Server(config)
16
-
17
- async def run_api():
18
- await server.serve()
19
-
20
- async def run_ws():
21
- await run_mcp()
22
-
23
- await asyncio.gather(run_api(), run_ws())
24
-
25
-
26
- def main():
27
- with contextlib.suppress(KeyboardInterrupt):
28
- asyncio.run(main_async())
29
-
30
-
31
- if __name__ == "__main__":
32
- main()
33
-
@@ -1,71 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import asyncio
4
- import json
5
- from dataclasses import dataclass
6
- from typing import Any, Awaitable, Callable, Dict
7
-
8
- import websockets
9
-
10
- from .config import settings
11
- from .embeddings import Embedder
12
- from .indexer import ensure_index
13
- from .search import Searcher
14
-
15
-
16
- Json = Dict[str, Any]
17
-
18
-
19
- @dataclass
20
- class McpServer:
21
- host: str = settings.mcp_host
22
- port: int = settings.mcp_port
23
-
24
- def __post_init__(self):
25
- emb = Embedder()
26
- index, meta = ensure_index(emb)
27
- self.searcher = Searcher(index=index, meta=meta, embedder=emb)
28
-
29
- async def handler(self, websocket):
30
- async for message in websocket:
31
- try:
32
- req = json.loads(message)
33
- if not isinstance(req, dict):
34
- raise ValueError("Invalid JSON-RPC request")
35
- method = req.get("method")
36
- req_id = req.get("id")
37
- params = req.get("params", {})
38
-
39
- if method == "vw.search":
40
- q = params.get("query")
41
- k = int(params.get("k", 6))
42
- result = self.searcher.search(q, k=k)
43
- elif method == "vw.answer":
44
- q = params.get("query")
45
- k = int(params.get("k", 6))
46
- result = self.searcher.answer(q, k=k)
47
- elif method == "vw.get":
48
- doc_id = params.get("doc_id")
49
- chunk_id = int(params.get("chunk_id"))
50
- result = self.searcher.get(doc_id, chunk_id)
51
- else:
52
- raise ValueError(f"Unknown method: {method}")
53
-
54
- resp: Json = {"jsonrpc": "2.0", "id": req_id, "result": result}
55
- except Exception as e: # pragma: no cover - basic error surface
56
- resp = {
57
- "jsonrpc": "2.0",
58
- "id": req.get("id") if isinstance(req, dict) else None,
59
- "error": {"code": -32000, "message": str(e)},
60
- }
61
- await websocket.send(json.dumps(resp, ensure_ascii=False))
62
-
63
- async def run(self):
64
- async with websockets.serve(self.handler, self.host, self.port):
65
- await asyncio.Future() # run forever
66
-
67
-
68
- async def run_server():
69
- server = McpServer()
70
- await server.run()
71
-
@@ -1,54 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass
4
- from typing import List, Tuple
5
-
6
- import faiss # type: ignore
7
- import numpy as np
8
-
9
- from .embeddings import Embedder
10
-
11
-
12
- @dataclass
13
- class Searcher:
14
- index: faiss.Index
15
- meta: List[dict]
16
- embedder: Embedder
17
-
18
- def search(self, query: str, k: int = 6) -> List[dict]:
19
- vec = self.embedder.encode([query]) # normalized
20
- scores, idxs = self.index.search(vec, k)
21
- out: List[dict] = []
22
- for score, idx in zip(scores[0].tolist(), idxs[0].tolist()):
23
- if idx == -1:
24
- continue
25
- m = self.meta[idx]
26
- out.append({
27
- "score": float(score),
28
- "doc_id": m["doc_id"],
29
- "chunk_id": m["chunk_id"],
30
- "text": m["text"],
31
- })
32
- return out
33
-
34
- def get(self, doc_id: str, chunk_id: int) -> dict:
35
- # naive lookup by scanning meta (meta is same order as index)
36
- for m in self.meta:
37
- if m["doc_id"] == doc_id and m["chunk_id"] == chunk_id:
38
- return m
39
- raise KeyError(f"Chunk not found: {doc_id}#{chunk_id}")
40
-
41
- def answer(self, query: str, k: int = 6) -> dict:
42
- # Simple extractive draft: stitch top-k snippets
43
- hits = self.search(query, k=k)
44
- summary_lines: List[str] = []
45
- for i, h in enumerate(hits, start=1):
46
- text = h["text"].strip().splitlines()
47
- lead = " ".join(text[:2])[:400]
48
- summary_lines.append(f"[{i}] {lead}")
49
- draft = (
50
- "以下は関連する資料からの抜粋です。詳細は出典を参照してください。\n\n"
51
- + "\n".join(summary_lines)
52
- )
53
- return {"draft": draft, "sources": hits}
54
-
@@ -1,14 +0,0 @@
1
- import hashlib
2
- from pathlib import Path
3
-
4
-
5
- def iter_text_files(root: Path):
6
- exts = {".md", ".markdown", ".html", ".htm", ".txt"}
7
- for p in sorted(root.rglob("*")):
8
- if p.is_file() and p.suffix.lower() in exts:
9
- yield p
10
-
11
-
12
- def stable_uid(text: str) -> str:
13
- return hashlib.md5(text.encode("utf-8")).hexdigest() # nosec - non-crypto id
14
-
@@ -1 +0,0 @@
1
-