@hybridlabor-api/aos 4.4.1 → 4.4.2-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/firecrawl/SKILL.md +149 -0
- package/.agents/skills/firecrawl/rules/install.md +82 -0
- package/.agents/skills/firecrawl/rules/security.md +26 -0
- package/.agents/skills/firecrawl-agent/SKILL.md +58 -0
- package/.agents/skills/firecrawl-build/SKILL.md +39 -0
- package/.agents/skills/firecrawl-build-interact/SKILL.md +68 -0
- package/.agents/skills/firecrawl-build-onboarding/SKILL.md +103 -0
- package/.agents/skills/firecrawl-build-onboarding/references/auth-flow.md +39 -0
- package/.agents/skills/firecrawl-build-onboarding/references/project-setup.md +20 -0
- package/.agents/skills/firecrawl-build-onboarding/references/sdk-installation.md +17 -0
- package/.agents/skills/firecrawl-build-scrape/SKILL.md +69 -0
- package/.agents/skills/firecrawl-build-search/SKILL.md +69 -0
- package/.agents/skills/firecrawl-crawl/SKILL.md +59 -0
- package/.agents/skills/firecrawl-download/SKILL.md +70 -0
- package/.agents/skills/firecrawl-interact/SKILL.md +84 -0
- package/.agents/skills/firecrawl-map/SKILL.md +51 -0
- package/.agents/skills/firecrawl-scrape/SKILL.md +69 -0
- package/.agents/skills/firecrawl-search/SKILL.md +60 -0
- package/CLAUDE.md +573 -0
- package/README.de.md +0 -8
- package/README.md +0 -8
- package/README.pt.md +0 -8
- package/assets/brand/ao-ant-mark.svg +91 -0
- package/assets/brand/bdb-core-mark.svg +34 -0
- package/assets/brand/heimdall-guardian-mark.svg +16 -0
- package/assets/brand/memb-crystal-mark.svg +18 -0
- package/bin/aos-config.mjs +89 -0
- package/bin/aos-dashboard.mjs +608 -0
- package/bin/aos-uninstall.mjs +227 -0
- package/docs/sessions/audit-2026-09-14-silent-failures.md +114 -0
- package/docs/skills_table.md +0 -3
- package/installer.js +471 -237
- package/mcps/RhinoMCP/cc-plugin/.claude/settings.json +10 -0
- package/mcps/after-effects-mcp/build/index.js +840 -0
- package/mcps/after-effects-mcp/build/scripts/applyEffect.jsx +153 -0
- package/mcps/after-effects-mcp/build/scripts/applyEffectTemplate.jsx +218 -0
- package/mcps/after-effects-mcp/build/scripts/createComposition.jsx +71 -0
- package/mcps/after-effects-mcp/build/scripts/createShapeLayer.jsx +147 -0
- package/mcps/after-effects-mcp/build/scripts/createSolidLayer.jsx +114 -0
- package/mcps/after-effects-mcp/build/scripts/createTextLayer.jsx +115 -0
- package/mcps/after-effects-mcp/build/scripts/getLayerInfo.jsx +192 -0
- package/mcps/after-effects-mcp/build/scripts/getProjectInfo.jsx +90 -0
- package/mcps/after-effects-mcp/build/scripts/listCompositions.jsx +50 -0
- package/mcps/after-effects-mcp/build/scripts/mcp-bridge-auto.jsx +1773 -0
- package/mcps/after-effects-mcp/build/scripts/setLayerProperties.jsx +160 -0
- package/mcps/computer-use-mcp/dist/client.d.ts +150 -0
- package/mcps/computer-use-mcp/dist/client.js +136 -0
- package/mcps/computer-use-mcp/dist/entrypoint.d.ts +16 -0
- package/mcps/computer-use-mcp/dist/entrypoint.js +26 -0
- package/mcps/computer-use-mcp/dist/native.d.ts +212 -0
- package/mcps/computer-use-mcp/dist/native.js +50 -0
- package/mcps/computer-use-mcp/dist/server.d.ts +32 -0
- package/mcps/computer-use-mcp/dist/server.js +342 -0
- package/mcps/computer-use-mcp/dist/session.d.ts +101 -0
- package/mcps/computer-use-mcp/dist/session.js +2372 -0
- package/package.json +13 -4
- package/skills/global_config/aos-project-init/SKILL.md +97 -130
- package/skills/global_config/aos-project-init/assets/openwikiignore.template +62 -0
- package/skills/global_config/aos-project-init/scripts/aos-project-doctor.mjs +38 -1
- package/skills/global_config/aos-setup/SKILL.md +98 -8
- package/skills/global_config/aos-setup/scripts/aos-doctor.mjs +21 -2
- package/skills/global_config/ask-tim/SKILL.md +2 -7
- package/skills/global_config/openwiki-skill/scripts/openwiki_daemon.py +65 -12
- package/bin/setup-saas.mjs +0 -792
- package/mcps/blender-mcp-server/.dockerignore +0 -19
- package/mcps/blender-mcp-server/.github/workflows/ci.yml +0 -67
- package/mcps/blender-mcp-server/.github/workflows/publish-pypi.yml +0 -54
- package/mcps/blender-mcp-server/CHANGELOG.md +0 -64
- package/mcps/blender-mcp-server/CONTRIBUTING.md +0 -107
- package/mcps/blender-mcp-server/Dockerfile +0 -19
- package/mcps/blender-mcp-server/LICENSE +0 -21
- package/mcps/blender-mcp-server/README.md +0 -409
- package/mcps/blender-mcp-server/addon/__init__.py +0 -1440
- package/mcps/blender-mcp-server/addon/models.py +0 -223
- package/mcps/blender-mcp-server/pyproject.toml +0 -120
- package/mcps/blender-mcp-server/scripts/blender_bridge_request.py +0 -71
- package/mcps/blender-mcp-server/scripts/blender_create_test_cube.py +0 -49
- package/mcps/blender-mcp-server/scripts/blender_scene_info.py +0 -38
- package/mcps/blender-mcp-server/scripts/build_addon_zip.sh +0 -29
- package/mcps/blender-mcp-server/scripts/demos/README.md +0 -186
- package/mcps/blender-mcp-server/scripts/demos/dam_break_scene.py +0 -276
- package/mcps/blender-mcp-server/scripts/demos/open_dam_break_gui.py +0 -33
- package/mcps/blender-mcp-server/scripts/demos/pipe_movement_study.py +0 -518
- package/mcps/blender-mcp-server/scripts/demos/pipe_pressure_failure_scene.py +0 -806
- package/mcps/blender-mcp-server/scripts/demos/procedural_dam_break_scene.py +0 -600
- package/mcps/blender-mcp-server/scripts/demos/run_dam_break.py +0 -510
- package/mcps/blender-mcp-server/scripts/launch_blender_gui.py +0 -41
- package/mcps/blender-mcp-server/scripts/library/README.md +0 -64
- package/mcps/blender-mcp-server/scripts/library/apply_transforms.py +0 -46
- package/mcps/blender-mcp-server/scripts/library/camera.py +0 -51
- package/mcps/blender-mcp-server/scripts/library/collections.py +0 -65
- package/mcps/blender-mcp-server/scripts/library/create_mesh.py +0 -41
- package/mcps/blender-mcp-server/scripts/library/effector.py +0 -48
- package/mcps/blender-mcp-server/scripts/library/fluid_domain.py +0 -80
- package/mcps/blender-mcp-server/scripts/library/fluid_inflow.py +0 -98
- package/mcps/blender-mcp-server/scripts/library/frame_range.py +0 -35
- package/mcps/blender-mcp-server/scripts/library/keyframes.py +0 -59
- package/mcps/blender-mcp-server/scripts/library/rigid_body.py +0 -52
- package/mcps/blender-mcp-server/scripts/library/save_blend.py +0 -40
- package/mcps/blender-mcp-server/scripts/server_start.sh +0 -26
- package/mcps/blender-mcp-server/src/blender_mcp_server/__init__.py +0 -3
- package/mcps/blender-mcp-server/src/blender_mcp_server/headless.py +0 -330
- package/mcps/blender-mcp-server/src/blender_mcp_server/server.py +0 -606
- package/mcps/davinci-mcp-professional/.bandit +0 -35
- package/mcps/davinci-mcp-professional/.claude/commands/security-review.md +0 -191
- package/mcps/davinci-mcp-professional/.claude/settings.json +0 -1
- package/mcps/davinci-mcp-professional/.editorconfig +0 -27
- package/mcps/davinci-mcp-professional/.gitattributes +0 -207
- package/mcps/davinci-mcp-professional/.github/CODEOWNERS +0 -2
- package/mcps/davinci-mcp-professional/.github/ISSUE_TEMPLATE/bug_report.md +0 -33
- package/mcps/davinci-mcp-professional/.github/ISSUE_TEMPLATE/feature_request.md +0 -19
- package/mcps/davinci-mcp-professional/.github/PULL_REQUEST_TEMPLATE.md +0 -20
- package/mcps/davinci-mcp-professional/.github/SECURITY.md +0 -97
- package/mcps/davinci-mcp-professional/.github/dependabot.yml +0 -27
- package/mcps/davinci-mcp-professional/.github/workflows/ci.yml +0 -39
- package/mcps/davinci-mcp-professional/ATTRIBUTION.md +0 -4
- package/mcps/davinci-mcp-professional/AUTHORS.md +0 -9
- package/mcps/davinci-mcp-professional/BUGS.md +0 -55
- package/mcps/davinci-mcp-professional/CLAUDE.md +0 -229
- package/mcps/davinci-mcp-professional/CONTRIBUTING.md +0 -51
- package/mcps/davinci-mcp-professional/COPYING.md +0 -228
- package/mcps/davinci-mcp-professional/Doxyfile +0 -379
- package/mcps/davinci-mcp-professional/README.md +0 -143
- package/mcps/davinci-mcp-professional/SECURITY.md +0 -40
- package/mcps/davinci-mcp-professional/USING.md +0 -301
- package/mcps/davinci-mcp-professional/VERSION.md +0 -13
- package/mcps/davinci-mcp-professional/build.py +0 -169
- package/mcps/davinci-mcp-professional/claude_desktop_config_template.json +0 -11
- package/mcps/davinci-mcp-professional/hooks/ci-check.sh +0 -29
- package/mcps/davinci-mcp-professional/hooks/pre-push +0 -46
- package/mcps/davinci-mcp-professional/main.py +0 -40
- package/mcps/davinci-mcp-professional/mcp_server.py +0 -30
- package/mcps/davinci-mcp-professional/pyproject.toml +0 -115
- package/mcps/davinci-mcp-professional/security_audit.py +0 -379
- package/mcps/davinci-mcp-professional/src/davinci_mcp/__init__.py +0 -19
- package/mcps/davinci-mcp-professional/src/davinci_mcp/cli.py +0 -138
- package/mcps/davinci-mcp-professional/src/davinci_mcp/resolve_client.py +0 -342
- package/mcps/davinci-mcp-professional/src/davinci_mcp/resources/__init__.py +0 -60
- package/mcps/davinci-mcp-professional/src/davinci_mcp/server.py +0 -185
- package/mcps/davinci-mcp-professional/src/davinci_mcp/tools/__init__.py +0 -146
- package/mcps/davinci-mcp-professional/src/davinci_mcp/types.py +0 -125
- package/mcps/davinci-mcp-professional/src/davinci_mcp/utils/__init__.py +0 -19
- package/mcps/davinci-mcp-professional/src/davinci_mcp/utils/platform.py +0 -239
- package/mcps/davinci-mcp-professional/test.py +0 -186
- package/mcps/davinci-mcp-professional/uv.lock +0 -2073
- package/mcps/davinci-resolve-mcp/.claude/skills/media-analysis.md +0 -44
- package/mcps/davinci-resolve-mcp/.clinerules +0 -17
- package/mcps/davinci-resolve-mcp/.cursorrules +0 -17
- package/mcps/davinci-resolve-mcp/.github/copilot-instructions.md +0 -17
- package/mcps/davinci-resolve-mcp/.github/workflows/npm-publish.yml +0 -109
- package/mcps/davinci-resolve-mcp/.windsurfrules +0 -17
- package/mcps/davinci-resolve-mcp/AGENTS.md +0 -114
- package/mcps/davinci-resolve-mcp/CHANGELOG.md +0 -2648
- package/mcps/davinci-resolve-mcp/CLAUDE.md +0 -15
- package/mcps/davinci-resolve-mcp/LICENSE +0 -21
- package/mcps/davinci-resolve-mcp/README.md +0 -173
- package/mcps/davinci-resolve-mcp/SECURITY.md +0 -53
- package/mcps/davinci-resolve-mcp/bin/davinci-resolve-mcp.mjs +0 -450
- package/mcps/davinci-resolve-mcp/examples/README.md +0 -53
- package/mcps/davinci-resolve-mcp/examples/markers/README.md +0 -81
- package/mcps/davinci-resolve-mcp/examples/media/README.md +0 -94
- package/mcps/davinci-resolve-mcp/examples/timeline/README.md +0 -98
- package/mcps/davinci-resolve-mcp/install.py +0 -1687
- package/mcps/davinci-resolve-mcp/package.json +0 -52
- package/mcps/davinci-resolve-mcp/release-notes/v2.22.0.md +0 -51
- package/mcps/davinci-resolve-mcp/release-notes/v2.23.0.md +0 -51
- package/mcps/davinci-resolve-mcp/release-notes/v2.23.1.md +0 -35
- package/mcps/davinci-resolve-mcp/release-notes/v2.24.1.md +0 -32
- package/mcps/davinci-resolve-mcp/scripts/audit_api_parity.py +0 -275
- package/mcps/davinci-resolve-mcp/scripts/audit_readwrite_symmetry.py +0 -80
- package/mcps/davinci-resolve-mcp/scripts/doctor.py +0 -227
- package/mcps/davinci-resolve-mcp/scripts/gen_api_limitations.py +0 -144
- package/mcps/davinci-resolve-mcp/scripts/live_media_analysis_polish_probe.py +0 -65
- package/mcps/davinci-resolve-mcp/scripts/measure_bridge_cost.py +0 -65
- package/mcps/davinci-resolve-mcp/scripts/regen_panel_screenshots.py +0 -76
- package/mcps/davinci-resolve-mcp/src/__init__.py +0 -3
- package/mcps/davinci-resolve-mcp/src/analysis_dashboard.py +0 -15505
- package/mcps/davinci-resolve-mcp/src/batch_cli.py +0 -540
- package/mcps/davinci-resolve-mcp/src/control_panel.py +0 -13
- package/mcps/davinci-resolve-mcp/src/granular/__init__.py +0 -17
- package/mcps/davinci-resolve-mcp/src/granular/common.py +0 -741
- package/mcps/davinci-resolve-mcp/src/granular/folder.py +0 -420
- package/mcps/davinci-resolve-mcp/src/granular/gallery.py +0 -306
- package/mcps/davinci-resolve-mcp/src/granular/graph.py +0 -309
- package/mcps/davinci-resolve-mcp/src/granular/media_pool.py +0 -679
- package/mcps/davinci-resolve-mcp/src/granular/media_pool_item.py +0 -1020
- package/mcps/davinci-resolve-mcp/src/granular/media_storage.py +0 -179
- package/mcps/davinci-resolve-mcp/src/granular/project.py +0 -1654
- package/mcps/davinci-resolve-mcp/src/granular/resolve_control.py +0 -538
- package/mcps/davinci-resolve-mcp/src/granular/timeline.py +0 -1075
- package/mcps/davinci-resolve-mcp/src/granular/timeline_item.py +0 -2251
- package/mcps/davinci-resolve-mcp/src/resolve_mcp_server.py +0 -43
- package/mcps/davinci-resolve-mcp/src/server.py +0 -24116
- package/mcps/davinci-resolve-mcp/src/utils/__init__.py +0 -3
- package/mcps/davinci-resolve-mcp/src/utils/actor_identity.py +0 -46
- package/mcps/davinci-resolve-mcp/src/utils/analysis_caps.py +0 -678
- package/mcps/davinci-resolve-mcp/src/utils/analysis_memory.py +0 -755
- package/mcps/davinci-resolve-mcp/src/utils/analysis_runs.py +0 -307
- package/mcps/davinci-resolve-mcp/src/utils/analysis_store.py +0 -945
- package/mcps/davinci-resolve-mcp/src/utils/api_truth.py +0 -525
- package/mcps/davinci-resolve-mcp/src/utils/app_control.py +0 -319
- package/mcps/davinci-resolve-mcp/src/utils/audio_fairlight_live_probe.py +0 -263
- package/mcps/davinci-resolve-mcp/src/utils/brain_edits.py +0 -387
- package/mcps/davinci-resolve-mcp/src/utils/bridge_metrics.py +0 -76
- package/mcps/davinci-resolve-mcp/src/utils/cdl.py +0 -20
- package/mcps/davinci-resolve-mcp/src/utils/clip_query.py +0 -85
- package/mcps/davinci-resolve-mcp/src/utils/cloud_operations.py +0 -192
- package/mcps/davinci-resolve-mcp/src/utils/color_grade_live_probe.py +0 -444
- package/mcps/davinci-resolve-mcp/src/utils/contracts.py +0 -102
- package/mcps/davinci-resolve-mcp/src/utils/cut_ir.py +0 -115
- package/mcps/davinci-resolve-mcp/src/utils/dctl_templates.py +0 -368
- package/mcps/davinci-resolve-mcp/src/utils/deep_vision.py +0 -643
- package/mcps/davinci-resolve-mcp/src/utils/destructive_hook.py +0 -606
- package/mcps/davinci-resolve-mcp/src/utils/edit_engine.py +0 -737
- package/mcps/davinci-resolve-mcp/src/utils/embeddings.py +0 -922
- package/mcps/davinci-resolve-mcp/src/utils/entities.py +0 -579
- package/mcps/davinci-resolve-mcp/src/utils/extension_authoring_live_probe.py +0 -292
- package/mcps/davinci-resolve-mcp/src/utils/failure_tracker.py +0 -119
- package/mcps/davinci-resolve-mcp/src/utils/fuse_templates.py +0 -1968
- package/mcps/davinci-resolve-mcp/src/utils/fusion_composition_live_probe.py +0 -284
- package/mcps/davinci-resolve-mcp/src/utils/fusion_group_settings.py +0 -334
- package/mcps/davinci-resolve-mcp/src/utils/layout_presets.py +0 -333
- package/mcps/davinci-resolve-mcp/src/utils/mcp_stdio.py +0 -32
- package/mcps/davinci-resolve-mcp/src/utils/mcp_transport.py +0 -128
- package/mcps/davinci-resolve-mcp/src/utils/media_analysis.py +0 -7690
- package/mcps/davinci-resolve-mcp/src/utils/media_analysis_jobs.py +0 -805
- package/mcps/davinci-resolve-mcp/src/utils/media_pool_changes.py +0 -121
- package/mcps/davinci-resolve-mcp/src/utils/media_pool_ingest_live_probe.py +0 -592
- package/mcps/davinci-resolve-mcp/src/utils/multicam.py +0 -393
- package/mcps/davinci-resolve-mcp/src/utils/object_inspection.py +0 -301
- package/mcps/davinci-resolve-mcp/src/utils/page_lock.py +0 -75
- package/mcps/davinci-resolve-mcp/src/utils/platform.py +0 -157
- package/mcps/davinci-resolve-mcp/src/utils/proc.py +0 -26
- package/mcps/davinci-resolve-mcp/src/utils/project_cleanup.py +0 -73
- package/mcps/davinci-resolve-mcp/src/utils/project_lifecycle_live_probe.py +0 -376
- package/mcps/davinci-resolve-mcp/src/utils/project_lint.py +0 -131
- package/mcps/davinci-resolve-mcp/src/utils/project_properties.py +0 -601
- package/mcps/davinci-resolve-mcp/src/utils/project_spec.py +0 -459
- package/mcps/davinci-resolve-mcp/src/utils/readback.py +0 -91
- package/mcps/davinci-resolve-mcp/src/utils/render_deliver_live_probe.py +0 -384
- package/mcps/davinci-resolve-mcp/src/utils/resolve_ai_governance.py +0 -214
- package/mcps/davinci-resolve-mcp/src/utils/resolve_ai_ledger.py +0 -244
- package/mcps/davinci-resolve-mcp/src/utils/resolve_busy.py +0 -171
- package/mcps/davinci-resolve-mcp/src/utils/resolve_connection.py +0 -77
- package/mcps/davinci-resolve-mcp/src/utils/review_annotation_live_probe.py +0 -352
- package/mcps/davinci-resolve-mcp/src/utils/script_templates.py +0 -1193
- package/mcps/davinci-resolve-mcp/src/utils/shot_relationships.py +0 -544
- package/mcps/davinci-resolve-mcp/src/utils/structural_diff.py +0 -175
- package/mcps/davinci-resolve-mcp/src/utils/sync_detection.py +0 -889
- package/mcps/davinci-resolve-mcp/src/utils/timeline_brain_db.py +0 -826
- package/mcps/davinci-resolve-mcp/src/utils/timeline_conform_live_probe.py +0 -280
- package/mcps/davinci-resolve-mcp/src/utils/timeline_kernel_live_probe.py +0 -1092
- package/mcps/davinci-resolve-mcp/src/utils/timeline_kernel_probe.py +0 -185
- package/mcps/davinci-resolve-mcp/src/utils/timeline_title_text.py +0 -87
- package/mcps/davinci-resolve-mcp/src/utils/timeline_versioning.py +0 -730
- package/mcps/davinci-resolve-mcp/src/utils/update_check.py +0 -685
- package/mcps/vectorworks-mcp/.dockerignore +0 -8
- package/mcps/vectorworks-mcp/Dockerfile +0 -28
- package/mcps/vectorworks-mcp/README.md +0 -156
- package/mcps/vectorworks-mcp/app/__init__.py +0 -2
- package/mcps/vectorworks-mcp/app/api.py +0 -52
- package/mcps/vectorworks-mcp/app/chunking.py +0 -56
- package/mcps/vectorworks-mcp/app/config.py +0 -29
- package/mcps/vectorworks-mcp/app/embeddings.py +0 -28
- package/mcps/vectorworks-mcp/app/indexer.py +0 -106
- package/mcps/vectorworks-mcp/app/main.py +0 -33
- package/mcps/vectorworks-mcp/app/mcp_server.py +0 -71
- package/mcps/vectorworks-mcp/app/search.py +0 -54
- package/mcps/vectorworks-mcp/app/utils.py +0 -14
- package/mcps/vectorworks-mcp/data/.gitkeep +0 -1
- package/mcps/vectorworks-mcp/data/vw-app-help/VW2022_PluginScript.htm +0 -95
- package/mcps/vectorworks-mcp/data/vw-app-help/VW2022_ScriptEditor.htm +0 -266
- package/mcps/vectorworks-mcp/data/vw-app-help/VW2022_Scripting.htm +0 -106
- package/mcps/vectorworks-mcp/data/vw-app-help/VW2023_CreatingScriptedPlugins.htm +0 -327
- package/mcps/vectorworks-mcp/data/vw-app-help/VW2024_RunningScripts.htm +0 -116
- package/mcps/vectorworks-mcp/data/vw-devwiki/VS_Function_Reference_category.html +0 -2129
- package/mcps/vectorworks-mcp/data/vw-jp-ref/ObjectsSymbols.html +0 -2035
- package/mcps/vectorworks-mcp/data/vw-jp-ref/ScriptFunctionReference.html +0 -29
- package/mcps/vectorworks-mcp/design.md +0 -57
- package/mcps/vectorworks-mcp/docker-compose.yml +0 -18
- package/mcps/vectorworks-mcp/index/.gitkeep +0 -1
- package/mcps/vectorworks-mcp/index/meta.jsonl +0 -3956
- package/mcps/vectorworks-mcp/index/vw.faiss +0 -0
- package/mcps/vectorworks-mcp/requirements.txt +0 -10
- package/mcps/vectorworks-mcp/scripts/fetch_docs_minimal.sh +0 -84
- package/mcps/vectorworks-mcp/scripts/fetch_github_vectorworks.sh +0 -85
- package/mcps/vectorworks-mcp/templates/index.html +0 -40
- package/scripts/ecosystem-health-audit.js +0 -257
- package/skills/bdb-dev-os-skill/SKILL.md +0 -49
- package/skills/bdb-dev-os-skill/package.json +0 -11
- package/skills/bdbsaastraining/SKILL.md +0 -316
- package/skills/bdbsaastraining/references/exam-pool.md +0 -313
- package/skills/bdbsaastraining/references/interaction-modes.md +0 -94
- package/skills/bdbsaastraining/references/track-a-ai-agent.md +0 -111
- package/skills/bdbsaastraining/references/track-b-wordpress.md +0 -111
- package/skills/bdbsaastraining/references/track-c-mailserver.md +0 -107
- package/skills/bdbsaastraining/references/track-d-debian.md +0 -109
- package/skills/bdbsaastraining/references/track-e-custom.md +0 -83
- package/skills/bdbsaastraining/scripts/build_profile.py +0 -529
- package/skills/bdbsaastraining/scripts/generate_certificate.py +0 -161
- package/skills/bdbsaastraining/scripts/preflight_check.sh +0 -150
- package/skills/bdbsaastraining/templates/certificate_template.html +0 -508
- package/skills/global_config/bdb-ecosystem-health/SKILL.md +0 -68
- package/skills/global_config/bdbsaas-ops/SKILL.md +0 -16
- package/skills/global_config/bdbsaashost/SKILL.md +0 -125
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Read-only diagnostics for a local DaVinci Resolve MCP setup.
|
|
3
|
-
|
|
4
|
-
Checks the checkout, Python interpreter, Resolve app and scripting-API paths,
|
|
5
|
-
MCP client configs, and probes the DaVinciResolveScript bridge without
|
|
6
|
-
mutating anything. Prints OK/WARN/FAIL lines (or JSON with --json) and exits
|
|
7
|
-
nonzero only when a FAIL is present.
|
|
8
|
-
|
|
9
|
-
Run: `python3 scripts/doctor.py`
|
|
10
|
-
|
|
11
|
-
Overridable via environment: DAVINCI_MCP_REPO, DAVINCI_MCP_PYTHON,
|
|
12
|
-
CODEX_HOME, CLAUDE_DESKTOP_CONFIG, RESOLVE_APP, RESOLVE_SCRIPT_API,
|
|
13
|
-
RESOLVE_SCRIPT_MODULES, RESOLVE_SCRIPT_LIB.
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
from __future__ import annotations
|
|
17
|
-
|
|
18
|
-
import argparse
|
|
19
|
-
import json
|
|
20
|
-
import os
|
|
21
|
-
import re
|
|
22
|
-
import subprocess
|
|
23
|
-
import sys
|
|
24
|
-
from pathlib import Path
|
|
25
|
-
from typing import Any
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def find_repo_root() -> Path:
|
|
29
|
-
env_repo = os.environ.get("DAVINCI_MCP_REPO")
|
|
30
|
-
if env_repo:
|
|
31
|
-
return Path(env_repo).expanduser().resolve()
|
|
32
|
-
current = Path(__file__).resolve()
|
|
33
|
-
for candidate in [current, *current.parents]:
|
|
34
|
-
if (candidate / "src" / "server.py").exists():
|
|
35
|
-
return candidate
|
|
36
|
-
return current.parents[1]
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
REPO = find_repo_root()
|
|
40
|
-
PYTHON = Path(os.environ.get("DAVINCI_MCP_PYTHON", REPO / "venv" / "bin" / "python")).expanduser()
|
|
41
|
-
if not PYTHON.exists():
|
|
42
|
-
PYTHON = REPO / ".venv" / "bin" / "python"
|
|
43
|
-
if not PYTHON.exists():
|
|
44
|
-
PYTHON = Path(sys.executable)
|
|
45
|
-
SERVER = REPO / "src" / "server.py"
|
|
46
|
-
CODEX_HOME = Path(os.environ.get("CODEX_HOME", "~/.codex")).expanduser()
|
|
47
|
-
CODEX_CONFIG = CODEX_HOME / "config.toml"
|
|
48
|
-
CLAUDE_CONFIG = Path(
|
|
49
|
-
os.environ.get(
|
|
50
|
-
"CLAUDE_DESKTOP_CONFIG",
|
|
51
|
-
"~/Library/Application Support/Claude/claude_desktop_config.json",
|
|
52
|
-
)
|
|
53
|
-
).expanduser()
|
|
54
|
-
RESOLVE_APP = Path(os.environ.get("RESOLVE_APP", "/Applications/DaVinci Resolve/DaVinci Resolve.app"))
|
|
55
|
-
RESOLVE_API = Path(
|
|
56
|
-
os.environ.get(
|
|
57
|
-
"RESOLVE_SCRIPT_API",
|
|
58
|
-
"/Library/Application Support/Blackmagic Design/DaVinci Resolve/Developer/Scripting",
|
|
59
|
-
)
|
|
60
|
-
)
|
|
61
|
-
RESOLVE_MODULES = Path(os.environ.get("RESOLVE_SCRIPT_MODULES", RESOLVE_API / "Modules"))
|
|
62
|
-
RESOLVE_LIB = Path(
|
|
63
|
-
os.environ.get(
|
|
64
|
-
"RESOLVE_SCRIPT_LIB",
|
|
65
|
-
"/Applications/DaVinci Resolve/DaVinci Resolve.app/Contents/Libraries/Fusion/fusionscript.so",
|
|
66
|
-
)
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def run(cmd: list[str], timeout: int = 12) -> dict[str, Any]:
|
|
71
|
-
try:
|
|
72
|
-
proc = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
|
|
73
|
-
return {
|
|
74
|
-
"ok": proc.returncode == 0,
|
|
75
|
-
"returncode": proc.returncode,
|
|
76
|
-
"stdout": proc.stdout.strip(),
|
|
77
|
-
"stderr": proc.stderr.strip(),
|
|
78
|
-
}
|
|
79
|
-
except Exception as exc:
|
|
80
|
-
return {"ok": False, "returncode": None, "stdout": "", "stderr": str(exc)}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def run_in_repo(cmd: list[str], timeout: int = 12) -> dict[str, Any]:
|
|
84
|
-
try:
|
|
85
|
-
proc = subprocess.run(cmd, cwd=REPO, capture_output=True, text=True, timeout=timeout)
|
|
86
|
-
return {
|
|
87
|
-
"ok": proc.returncode == 0,
|
|
88
|
-
"returncode": proc.returncode,
|
|
89
|
-
"stdout": proc.stdout.strip(),
|
|
90
|
-
"stderr": proc.stderr.strip(),
|
|
91
|
-
}
|
|
92
|
-
except Exception as exc:
|
|
93
|
-
return {"ok": False, "returncode": None, "stdout": "", "stderr": str(exc)}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
def check(results: list[dict[str, str]], status: str, name: str, detail: str) -> None:
|
|
97
|
-
results.append({"status": status, "name": name, "detail": detail})
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
def file_contains(path: Path, needles: list[str]) -> tuple[bool, str]:
|
|
101
|
-
if not path.exists():
|
|
102
|
-
return False, "missing"
|
|
103
|
-
text = path.read_text(errors="replace")
|
|
104
|
-
missing = [needle for needle in needles if needle not in text]
|
|
105
|
-
if missing:
|
|
106
|
-
return False, "missing: " + ", ".join(missing)
|
|
107
|
-
return True, "contains davinci-resolve MCP entry"
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
def version_from_server() -> str:
|
|
111
|
-
if not SERVER.exists():
|
|
112
|
-
return "unknown"
|
|
113
|
-
match = re.search(r'^VERSION\s*=\s*"([^"]+)"', SERVER.read_text(errors="replace"), re.M)
|
|
114
|
-
return match.group(1) if match else "unknown"
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
def git_summary() -> str:
|
|
118
|
-
if not (REPO / ".git").exists():
|
|
119
|
-
return "not a git checkout"
|
|
120
|
-
status = run_in_repo(["git", "status", "--short", "--branch"], timeout=8)
|
|
121
|
-
return status["stdout"] or status["stderr"] or "git status produced no output"
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
def git_head() -> str:
|
|
125
|
-
if not (REPO / ".git").exists():
|
|
126
|
-
return "not a git checkout"
|
|
127
|
-
head = run_in_repo(["git", "describe", "--tags", "--always", "--dirty"], timeout=8)
|
|
128
|
-
return head["stdout"] or head["stderr"] or "git describe produced no output"
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
def resolve_probe() -> dict[str, Any]:
|
|
132
|
-
if not PYTHON.exists():
|
|
133
|
-
return {"import_ok": False, "error": f"{PYTHON} is missing"}
|
|
134
|
-
|
|
135
|
-
code = f"""
|
|
136
|
-
import json
|
|
137
|
-
import sys
|
|
138
|
-
sys.path.insert(0, {str(RESOLVE_MODULES)!r})
|
|
139
|
-
try:
|
|
140
|
-
import DaVinciResolveScript as dvr
|
|
141
|
-
resolve = dvr.scriptapp("Resolve")
|
|
142
|
-
payload = {{
|
|
143
|
-
"import_ok": True,
|
|
144
|
-
"module": getattr(dvr, "__file__", None),
|
|
145
|
-
"resolve_connected": bool(resolve),
|
|
146
|
-
"product": resolve.GetProductName() if resolve else None,
|
|
147
|
-
"version": resolve.GetVersionString() if resolve else None,
|
|
148
|
-
}}
|
|
149
|
-
except Exception as exc:
|
|
150
|
-
payload = {{"import_ok": False, "error": repr(exc)}}
|
|
151
|
-
print(json.dumps(payload))
|
|
152
|
-
"""
|
|
153
|
-
env = {
|
|
154
|
-
**os.environ,
|
|
155
|
-
"RESOLVE_SCRIPT_API": str(RESOLVE_API),
|
|
156
|
-
"RESOLVE_SCRIPT_LIB": str(RESOLVE_LIB),
|
|
157
|
-
"PYTHONPATH": str(RESOLVE_MODULES),
|
|
158
|
-
}
|
|
159
|
-
proc = subprocess.run([str(PYTHON), "-c", code], capture_output=True, text=True, timeout=12, env=env)
|
|
160
|
-
output = (proc.stdout or proc.stderr).strip()
|
|
161
|
-
try:
|
|
162
|
-
payload = json.loads(output)
|
|
163
|
-
except json.JSONDecodeError:
|
|
164
|
-
payload = {"import_ok": False, "error": output or f"probe exited {proc.returncode}"}
|
|
165
|
-
payload["returncode"] = proc.returncode
|
|
166
|
-
return payload
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
def collect() -> list[dict[str, str]]:
|
|
170
|
-
results: list[dict[str, str]] = []
|
|
171
|
-
|
|
172
|
-
check(results, "OK" if REPO.exists() else "FAIL", "MCP checkout", str(REPO))
|
|
173
|
-
check(results, "OK" if SERVER.exists() else "FAIL", "Server entrypoint", str(SERVER))
|
|
174
|
-
check(results, "OK" if PYTHON.exists() else "FAIL", "Python", str(PYTHON))
|
|
175
|
-
check(results, "OK" if RESOLVE_APP.exists() else "FAIL", "Resolve app", str(RESOLVE_APP))
|
|
176
|
-
check(results, "OK" if RESOLVE_API.exists() else "FAIL", "Resolve scripting API", str(RESOLVE_API))
|
|
177
|
-
check(results, "OK" if RESOLVE_MODULES.exists() else "FAIL", "Resolve scripting modules", str(RESOLVE_MODULES))
|
|
178
|
-
check(results, "OK" if RESOLVE_LIB.exists() else "FAIL", "Resolve scripting library", str(RESOLVE_LIB))
|
|
179
|
-
|
|
180
|
-
needles = [str(SERVER)]
|
|
181
|
-
ok, detail = file_contains(CODEX_CONFIG, needles)
|
|
182
|
-
check(results, "OK" if ok else "WARN", "Codex MCP config", f"{CODEX_CONFIG}: {detail}")
|
|
183
|
-
ok, detail = file_contains(CLAUDE_CONFIG, needles)
|
|
184
|
-
check(results, "OK" if ok else "WARN", "Claude Desktop MCP config", f"{CLAUDE_CONFIG}: {detail}")
|
|
185
|
-
|
|
186
|
-
pyver = run([str(PYTHON), "--version"]) if PYTHON.exists() else {"ok": False, "stdout": "", "stderr": "missing"}
|
|
187
|
-
check(results, "OK" if pyver["ok"] else "FAIL", "Python version", pyver["stdout"] or pyver["stderr"])
|
|
188
|
-
|
|
189
|
-
probe = resolve_probe()
|
|
190
|
-
if probe.get("import_ok"):
|
|
191
|
-
check(results, "OK", "DaVinciResolveScript import", str(probe.get("module")))
|
|
192
|
-
if probe.get("resolve_connected"):
|
|
193
|
-
detail = f"{probe.get('product')} {probe.get('version')}"
|
|
194
|
-
check(results, "OK", "Resolve scripting connection", detail)
|
|
195
|
-
else:
|
|
196
|
-
check(
|
|
197
|
-
results,
|
|
198
|
-
"WARN",
|
|
199
|
-
"Resolve scripting connection",
|
|
200
|
-
'Module import worked, but scriptapp("Resolve") returned no object. Open DaVinci Resolve Studio, set Preferences > General > External scripting using = Local, and restart Resolve.',
|
|
201
|
-
)
|
|
202
|
-
else:
|
|
203
|
-
check(results, "FAIL", "DaVinciResolveScript import", str(probe.get("error")))
|
|
204
|
-
|
|
205
|
-
check(results, "OK", "MCP server version", version_from_server())
|
|
206
|
-
check(results, "OK", "MCP git head", git_head())
|
|
207
|
-
check(results, "OK", "Git status", git_summary())
|
|
208
|
-
return results
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
def main() -> int:
|
|
212
|
-
parser = argparse.ArgumentParser(description=__doc__)
|
|
213
|
-
parser.add_argument("--json", action="store_true", help="Print machine-readable JSON")
|
|
214
|
-
args = parser.parse_args()
|
|
215
|
-
|
|
216
|
-
results = collect()
|
|
217
|
-
if args.json:
|
|
218
|
-
print(json.dumps({"checks": results}, indent=2))
|
|
219
|
-
else:
|
|
220
|
-
for item in results:
|
|
221
|
-
print(f"[{item['status']}] {item['name']}: {item['detail']}")
|
|
222
|
-
|
|
223
|
-
return 1 if any(item["status"] == "FAIL" for item in results) else 0
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
if __name__ == "__main__":
|
|
227
|
-
raise SystemExit(main())
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Generate the Blackmagic-facing DaVinci Resolve API limitations report.
|
|
3
|
-
|
|
4
|
-
The single source of truth is the ``submit``-tagged entries in
|
|
5
|
-
``src/utils/api_truth.py`` (see ``submittable_limitations``). This script renders
|
|
6
|
-
them into ``docs/reference/api-limitations.md`` — a curated, behaviorally-verified
|
|
7
|
-
list that can be submitted to Blackmagic Design's developer feedback, split into
|
|
8
|
-
capabilities they should *add* and behaviors they should *fix*.
|
|
9
|
-
|
|
10
|
-
The output is deterministic (no timestamps) so ``tests.test_api_limitations_doc``
|
|
11
|
-
can assert the committed file matches. Regenerate after editing any ``submit``
|
|
12
|
-
entry:
|
|
13
|
-
|
|
14
|
-
venv/bin/python scripts/gen_api_limitations.py
|
|
15
|
-
|
|
16
|
-
Run with ``--check`` to fail (exit 1) when the committed doc is stale.
|
|
17
|
-
"""
|
|
18
|
-
from __future__ import annotations
|
|
19
|
-
|
|
20
|
-
import sys
|
|
21
|
-
from pathlib import Path
|
|
22
|
-
|
|
23
|
-
REPO_ROOT = Path(__file__).resolve().parent.parent
|
|
24
|
-
if str(REPO_ROOT) not in sys.path:
|
|
25
|
-
sys.path.insert(0, str(REPO_ROOT))
|
|
26
|
-
|
|
27
|
-
from src.utils.api_truth import ( # noqa: E402
|
|
28
|
-
VERIFIED_ON,
|
|
29
|
-
submittable_limitations,
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
DOC_PATH = REPO_ROOT / "docs" / "reference" / "api-limitations.md"
|
|
33
|
-
ISSUE_URL = "https://github.com/samuelgursky/davinci-resolve-mcp/issues"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def _render_entry(entry: dict) -> str:
|
|
37
|
-
lines = [f"### {entry['symbol']}", ""]
|
|
38
|
-
obj = entry.get("object")
|
|
39
|
-
if obj:
|
|
40
|
-
lines.append(f"- **Object:** `{obj}`")
|
|
41
|
-
sig = entry.get("signature")
|
|
42
|
-
if sig:
|
|
43
|
-
lines.append(f"- **Signature:** `{sig}`")
|
|
44
|
-
lines.append(f"- **Behavior:** {entry['reality']}")
|
|
45
|
-
rec = entry.get("recommended")
|
|
46
|
-
if rec:
|
|
47
|
-
lines.append(f"- **Workaround / current handling:** {rec}")
|
|
48
|
-
issue = entry.get("issue")
|
|
49
|
-
if issue is not None:
|
|
50
|
-
lines.append(f"- **Reference:** [issue #{issue}]({ISSUE_URL}/{issue})")
|
|
51
|
-
tags = entry.get("tags")
|
|
52
|
-
if tags:
|
|
53
|
-
lines.append(f"- **Tags:** {', '.join(tags)}")
|
|
54
|
-
lines.append("")
|
|
55
|
-
return "\n".join(lines)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
def render() -> str:
|
|
59
|
-
groups = submittable_limitations()
|
|
60
|
-
missing = groups["missing"]
|
|
61
|
-
bugs = groups["bug"]
|
|
62
|
-
|
|
63
|
-
out = [
|
|
64
|
-
"# DaVinci Resolve Scripting API — Limitations & Feedback",
|
|
65
|
-
"",
|
|
66
|
-
"<!-- GENERATED FILE — do not edit by hand.",
|
|
67
|
-
" Source: src/utils/api_truth.py (entries tagged `submit`).",
|
|
68
|
-
" Regenerate: venv/bin/python scripts/gen_api_limitations.py -->",
|
|
69
|
-
"",
|
|
70
|
-
"This is a curated, behaviorally-verified list of DaVinci Resolve scripting",
|
|
71
|
-
"API gaps and bugs encountered while building this MCP server, intended for",
|
|
72
|
-
"submission to Blackmagic Design's developer feedback. Every item was",
|
|
73
|
-
"observed against live Resolve; each entry notes the current workaround (or",
|
|
74
|
-
"that none exists).",
|
|
75
|
-
"",
|
|
76
|
-
f"**Verified on:** {VERIFIED_ON}",
|
|
77
|
-
"",
|
|
78
|
-
f"**Totals:** {len(missing)} missing capabilities, {len(bugs)} bugs / "
|
|
79
|
-
"unreliable behaviors.",
|
|
80
|
-
"",
|
|
81
|
-
"The authoritative source is the runtime-queryable `api_truth` ledger",
|
|
82
|
-
"(`resolve_control api_truth \"<query>\"`); this document is generated from",
|
|
83
|
-
"it and stays in sync via a drift guard.",
|
|
84
|
-
"",
|
|
85
|
-
"### Scope & completeness",
|
|
86
|
-
"",
|
|
87
|
-
"This list is **not guaranteed exhaustive.** It combines (a) issues hit",
|
|
88
|
-
"while building this MCP server, (b) a `dir()` surface audit of the live",
|
|
89
|
-
"Resolve API objects (ProjectManager, Project, MediaPool, MediaPoolItem,",
|
|
90
|
-
"Timeline, TimelineItem, Graph) diffed against Resolve's UI feature set,",
|
|
91
|
-
"and (c) a live mutating harness (`tests/live_api_gap_verification.py`)",
|
|
92
|
-
"that attempts each operation against a disposable project built from",
|
|
93
|
-
"synthetic media and confirms it fails while a related control succeeds.",
|
|
94
|
-
"That catches absent methods and documented constraints, but not subtler",
|
|
95
|
-
"issues: parameters that exist yet misbehave, version-specific regressions,",
|
|
96
|
-
"or capabilities we simply never exercised. New findings are added as",
|
|
97
|
-
"`submit`-tagged `api_truth` entries and this document is regenerated.",
|
|
98
|
-
"",
|
|
99
|
-
"Note: `hasattr()`/`getattr()` cannot be used to probe this API — the",
|
|
100
|
-
"Python bridge fabricates a callable for any attribute name (see the",
|
|
101
|
-
"`hasattr` bug below). Method existence here was checked with `dir()`.",
|
|
102
|
-
"",
|
|
103
|
-
"## Missing Capabilities (please add)",
|
|
104
|
-
"",
|
|
105
|
-
"Functionality that exists in the Resolve UI but has no scripting API",
|
|
106
|
-
"equivalent, blocking full automation.",
|
|
107
|
-
"",
|
|
108
|
-
]
|
|
109
|
-
for entry in missing:
|
|
110
|
-
out.append(_render_entry(entry))
|
|
111
|
-
|
|
112
|
-
out += [
|
|
113
|
-
"## Bugs / Unreliable Behavior (please fix)",
|
|
114
|
-
"",
|
|
115
|
-
"Methods that exist but misbehave — silent failures, unreliable return",
|
|
116
|
-
"values, or automation-hostile modal prompts.",
|
|
117
|
-
"",
|
|
118
|
-
]
|
|
119
|
-
for entry in bugs:
|
|
120
|
-
out.append(_render_entry(entry))
|
|
121
|
-
|
|
122
|
-
return "\n".join(out).rstrip() + "\n"
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
def main(argv: list[str]) -> int:
|
|
126
|
-
content = render()
|
|
127
|
-
if "--check" in argv:
|
|
128
|
-
current = DOC_PATH.read_text() if DOC_PATH.exists() else ""
|
|
129
|
-
if current != content:
|
|
130
|
-
print(
|
|
131
|
-
f"STALE: {DOC_PATH.relative_to(REPO_ROOT)} is out of date.\n"
|
|
132
|
-
"Run: venv/bin/python scripts/gen_api_limitations.py",
|
|
133
|
-
file=sys.stderr,
|
|
134
|
-
)
|
|
135
|
-
return 1
|
|
136
|
-
print(f"OK: {DOC_PATH.relative_to(REPO_ROOT)} is up to date.")
|
|
137
|
-
return 0
|
|
138
|
-
DOC_PATH.write_text(content)
|
|
139
|
-
print(f"Wrote {DOC_PATH.relative_to(REPO_ROOT)}")
|
|
140
|
-
return 0
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if __name__ == "__main__":
|
|
144
|
-
raise SystemExit(main(sys.argv[1:]))
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Opt-in live probe for media-analysis polish.
|
|
3
|
-
|
|
4
|
-
This script connects to the currently open Resolve project and exercises only
|
|
5
|
-
source-safe planning/review surfaces. It may write analysis artifacts under the
|
|
6
|
-
project analysis root, but it does not import, transcode, proxy, move, rename,
|
|
7
|
-
or write beside source media.
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
from __future__ import annotations
|
|
11
|
-
|
|
12
|
-
import argparse
|
|
13
|
-
import asyncio
|
|
14
|
-
import json
|
|
15
|
-
import os
|
|
16
|
-
import sys
|
|
17
|
-
from pathlib import Path
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
|
21
|
-
if str(PROJECT_ROOT) not in sys.path:
|
|
22
|
-
sys.path.insert(0, str(PROJECT_ROOT))
|
|
23
|
-
|
|
24
|
-
from src.server import media_analysis # noqa: E402
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
async def main() -> int:
|
|
28
|
-
parser = argparse.ArgumentParser(description="Run a source-safe live media-analysis polish probe.")
|
|
29
|
-
parser.add_argument("--target", default="project", help="project, selected, bin:<path>, or absolute file path")
|
|
30
|
-
parser.add_argument("--depth", default="standard", choices=["quick", "standard", "deep", "custom"])
|
|
31
|
-
parser.add_argument("--analysis-root", default=None, help="Optional base analysis root; project subdir is still added")
|
|
32
|
-
parser.add_argument("--max-samples", type=int, default=8, help="Marker thumbnail samples for review")
|
|
33
|
-
parser.add_argument("--execute", action="store_true", help="Execute analysis instead of dry-run planning")
|
|
34
|
-
parser.add_argument("--persist", action="store_true", help="Keep executed analysis artifacts under the project root")
|
|
35
|
-
args = parser.parse_args()
|
|
36
|
-
|
|
37
|
-
common = {
|
|
38
|
-
"target": args.target,
|
|
39
|
-
"depth": args.depth,
|
|
40
|
-
"analysis_root": args.analysis_root,
|
|
41
|
-
"dry_run": not args.execute,
|
|
42
|
-
"persist": args.persist,
|
|
43
|
-
"session_only": bool(args.execute and not args.persist),
|
|
44
|
-
"reuse_existing": True,
|
|
45
|
-
"max_analysis_frames": 8,
|
|
46
|
-
"vision": {"enabled": False},
|
|
47
|
-
"transcription": {"enabled": False},
|
|
48
|
-
}
|
|
49
|
-
plan = await media_analysis("plan", common)
|
|
50
|
-
review = await media_analysis("review_timeline_markers", {
|
|
51
|
-
"analysis_root": args.analysis_root,
|
|
52
|
-
"max_samples": args.max_samples,
|
|
53
|
-
"vision": {"enabled": False},
|
|
54
|
-
})
|
|
55
|
-
print(json.dumps({
|
|
56
|
-
"success": bool(plan.get("success")),
|
|
57
|
-
"cwd": os.getcwd(),
|
|
58
|
-
"plan": plan,
|
|
59
|
-
"marker_review": review,
|
|
60
|
-
}, indent=2, ensure_ascii=False))
|
|
61
|
-
return 0 if plan.get("success") else 1
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if __name__ == "__main__":
|
|
65
|
-
raise SystemExit(asyncio.run(main()))
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Measure DaVinci Resolve bridge round-trips for representative operations.
|
|
3
|
-
|
|
4
|
-
Wraps the live project in a counting proxy and runs a few common traversals,
|
|
5
|
-
reporting how many attribute accesses + method calls (each a bridge round-trip)
|
|
6
|
-
they cost. This is the measurement that gates whether a property cache is worth
|
|
7
|
-
building. Run against an OPEN project; it only reads.
|
|
8
|
-
|
|
9
|
-
PYTHONPATH=. venv/bin/python scripts/measure_bridge_cost.py
|
|
10
|
-
"""
|
|
11
|
-
import sys
|
|
12
|
-
|
|
13
|
-
import src.server as s
|
|
14
|
-
from src.utils.bridge_metrics import measure
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def _walk_media_pool(project_proxy):
|
|
18
|
-
"""A typical media-pool traversal: every folder, every clip, name + a property."""
|
|
19
|
-
mp = project_proxy.GetMediaPool()
|
|
20
|
-
root = mp.GetRootFolder()
|
|
21
|
-
clips_seen = 0
|
|
22
|
-
|
|
23
|
-
def walk(folder):
|
|
24
|
-
nonlocal clips_seen
|
|
25
|
-
for clip in (folder.GetClipList() or []):
|
|
26
|
-
clip.GetName()
|
|
27
|
-
clip.GetClipProperty("Type")
|
|
28
|
-
clips_seen += 1
|
|
29
|
-
for sub in (folder.GetSubFolderList() or []):
|
|
30
|
-
walk(sub)
|
|
31
|
-
|
|
32
|
-
walk(root)
|
|
33
|
-
return clips_seen
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def main():
|
|
37
|
-
r = s.get_resolve()
|
|
38
|
-
if not r:
|
|
39
|
-
print("Not connected to Resolve.")
|
|
40
|
-
return 1
|
|
41
|
-
proj = r.GetProjectManager().GetCurrentProject()
|
|
42
|
-
if not proj:
|
|
43
|
-
print("No project open.")
|
|
44
|
-
return 1
|
|
45
|
-
|
|
46
|
-
clips_holder = {}
|
|
47
|
-
|
|
48
|
-
def op(proj_proxy):
|
|
49
|
-
clips_holder["n"] = _walk_media_pool(proj_proxy)
|
|
50
|
-
|
|
51
|
-
counts = measure(op, proj)
|
|
52
|
-
n = clips_holder.get("n", 0)
|
|
53
|
-
total = counts["attr_access"] + counts["calls"]
|
|
54
|
-
print(f"project: {proj.GetName()!r}")
|
|
55
|
-
print(f"clips walked: {n}")
|
|
56
|
-
print(f"bridge attr-accesses: {counts['attr_access']}")
|
|
57
|
-
print(f"bridge method-calls: {counts['calls']}")
|
|
58
|
-
print(f"total round-trips: {total}")
|
|
59
|
-
if n:
|
|
60
|
-
print(f"round-trips per clip: {total / n:.1f}")
|
|
61
|
-
return 0
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if __name__ == "__main__":
|
|
65
|
-
sys.exit(main())
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Regenerate the control-panel doc screenshots from a live panel.
|
|
3
|
-
|
|
4
|
-
Drives the panel's hash deep links headlessly and writes 1280x800 captures
|
|
5
|
-
into docs/images/control-panel/. Run whenever the panel UI changes visibly.
|
|
6
|
-
|
|
7
|
-
Setup:
|
|
8
|
-
1. venv/bin/pip install playwright (chromium is fetched on first run if absent)
|
|
9
|
-
2. Start the panel bound to a project that HAS an analyzed clip, e.g.:
|
|
10
|
-
venv/bin/python -m src.control_panel --no-open
|
|
11
|
-
(Bind to a rich analysis context if the live Resolve project is empty.)
|
|
12
|
-
3. venv/bin/python scripts/regen_panel_screenshots.py [--clip-id <id>] [--port 8765]
|
|
13
|
-
|
|
14
|
-
The clip id defaults to the first analyzed clip reported by /api/clips.
|
|
15
|
-
"""
|
|
16
|
-
from __future__ import annotations
|
|
17
|
-
|
|
18
|
-
import argparse
|
|
19
|
-
import json
|
|
20
|
-
import pathlib
|
|
21
|
-
import sys
|
|
22
|
-
import urllib.request
|
|
23
|
-
|
|
24
|
-
OUT_DIR = pathlib.Path(__file__).resolve().parent.parent / "docs" / "images" / "control-panel"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def first_clip_id(base: str) -> str:
|
|
28
|
-
with urllib.request.urlopen(f"{base}/api/clips", timeout=10) as resp:
|
|
29
|
-
payload = json.load(resp)
|
|
30
|
-
clips = payload.get("clips") or []
|
|
31
|
-
if not clips:
|
|
32
|
-
sys.exit("No analyzed clips in the panel's project — bind the panel to a project with analysis data first.")
|
|
33
|
-
return clips[0]["clip_id"]
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def main() -> int:
|
|
37
|
-
parser = argparse.ArgumentParser(description=__doc__)
|
|
38
|
-
parser.add_argument("--port", type=int, default=8765)
|
|
39
|
-
parser.add_argument("--clip-id", default=None)
|
|
40
|
-
args = parser.parse_args()
|
|
41
|
-
base = f"http://127.0.0.1:{args.port}"
|
|
42
|
-
|
|
43
|
-
try:
|
|
44
|
-
from playwright.sync_api import sync_playwright
|
|
45
|
-
except ImportError:
|
|
46
|
-
sys.exit("playwright not installed: venv/bin/pip install playwright")
|
|
47
|
-
|
|
48
|
-
clip = args.clip_id or first_clip_id(base)
|
|
49
|
-
shots = [
|
|
50
|
-
("#overview", "01-overview.png", 3000),
|
|
51
|
-
("#analysis/review", "02-review-bin-grid.png", 3500),
|
|
52
|
-
(f"#analysis/review/clip/{clip}", "03-clip-detail.png", 4000),
|
|
53
|
-
(f"#analysis/review/clip/{clip}/transcript", "04-transcript.png", 4000),
|
|
54
|
-
(f"#analysis/review/clip/{clip}/shot/3", "05-shot-detail.png", 4500),
|
|
55
|
-
("#analysis/media", "06-inventory.png", 3500),
|
|
56
|
-
("#diagnostics/resolve", "07-diagnostics-resolve.png", 3000),
|
|
57
|
-
("#preferences/analysis", "08-preferences-analysis.png", 3000),
|
|
58
|
-
("#aiconsole", "09-ai-console.png", 3000),
|
|
59
|
-
("#analysis/review/history", "10-history.png", 3500),
|
|
60
|
-
("#analysis/review/plans", "11-edit-plans.png", 3500),
|
|
61
|
-
]
|
|
62
|
-
with sync_playwright() as pw:
|
|
63
|
-
browser = pw.chromium.launch()
|
|
64
|
-
page = browser.new_page(viewport={"width": 1280, "height": 800})
|
|
65
|
-
for hash_, name, wait in shots:
|
|
66
|
-
page.goto(f"{base}/{hash_}")
|
|
67
|
-
page.wait_for_timeout(wait)
|
|
68
|
-
page.screenshot(path=str(OUT_DIR / name))
|
|
69
|
-
print("shot:", name)
|
|
70
|
-
browser.close()
|
|
71
|
-
print(f"done — {len(shots)} screenshots in {OUT_DIR}")
|
|
72
|
-
return 0
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if __name__ == "__main__":
|
|
76
|
-
raise SystemExit(main())
|