synapse-sdk 1.0.0a13__py3-none-any.whl → 2025.11.7__py3-none-any.whl
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.
Potentially problematic release.
This version of synapse-sdk might be problematic. Click here for more details.
- synapse_sdk/__init__.py +24 -0
- synapse_sdk/cli/__init__.py +310 -5
- synapse_sdk/cli/alias/__init__.py +22 -0
- synapse_sdk/cli/alias/create.py +36 -0
- synapse_sdk/cli/alias/dataclass.py +31 -0
- synapse_sdk/cli/alias/default.py +16 -0
- synapse_sdk/cli/alias/delete.py +15 -0
- synapse_sdk/cli/alias/list.py +19 -0
- synapse_sdk/cli/alias/read.py +15 -0
- synapse_sdk/cli/alias/update.py +17 -0
- synapse_sdk/cli/alias/utils.py +61 -0
- synapse_sdk/cli/code_server.py +687 -0
- synapse_sdk/cli/config.py +440 -0
- synapse_sdk/cli/devtools.py +90 -0
- synapse_sdk/cli/plugin/__init__.py +33 -0
- synapse_sdk/cli/{create_plugin.py → plugin/create.py} +2 -2
- synapse_sdk/cli/plugin/publish.py +45 -0
- synapse_sdk/{plugins/cli → cli/plugin}/run.py +12 -5
- synapse_sdk/clients/agent/__init__.py +9 -3
- synapse_sdk/clients/agent/container.py +133 -0
- synapse_sdk/clients/agent/core.py +19 -0
- synapse_sdk/clients/agent/ray.py +298 -9
- synapse_sdk/clients/backend/__init__.py +41 -12
- synapse_sdk/clients/backend/annotation.py +13 -5
- synapse_sdk/clients/backend/core.py +59 -0
- synapse_sdk/clients/backend/data_collection.py +186 -0
- synapse_sdk/clients/backend/hitl.py +17 -0
- synapse_sdk/clients/backend/integration.py +19 -4
- synapse_sdk/clients/backend/ml.py +10 -7
- synapse_sdk/clients/backend/models.py +78 -0
- synapse_sdk/clients/base.py +381 -34
- synapse_sdk/clients/ray/serve.py +2 -0
- synapse_sdk/clients/validators/collections.py +31 -0
- synapse_sdk/devtools/config.py +94 -0
- synapse_sdk/devtools/docs/.gitignore +20 -0
- synapse_sdk/devtools/docs/README.md +41 -0
- synapse_sdk/devtools/docs/blog/2019-05-28-first-blog-post.md +12 -0
- synapse_sdk/devtools/docs/blog/2019-05-29-long-blog-post.md +44 -0
- synapse_sdk/devtools/docs/blog/2021-08-01-mdx-blog-post.mdx +24 -0
- synapse_sdk/devtools/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
- synapse_sdk/devtools/docs/blog/2021-08-26-welcome/index.md +29 -0
- synapse_sdk/devtools/docs/blog/authors.yml +25 -0
- synapse_sdk/devtools/docs/blog/tags.yml +19 -0
- synapse_sdk/devtools/docs/docs/api/clients/agent.md +43 -0
- synapse_sdk/devtools/docs/docs/api/clients/annotation-mixin.md +378 -0
- synapse_sdk/devtools/docs/docs/api/clients/backend.md +420 -0
- synapse_sdk/devtools/docs/docs/api/clients/base.md +257 -0
- synapse_sdk/devtools/docs/docs/api/clients/core-mixin.md +477 -0
- synapse_sdk/devtools/docs/docs/api/clients/data-collection-mixin.md +422 -0
- synapse_sdk/devtools/docs/docs/api/clients/hitl-mixin.md +554 -0
- synapse_sdk/devtools/docs/docs/api/clients/index.md +391 -0
- synapse_sdk/devtools/docs/docs/api/clients/integration-mixin.md +571 -0
- synapse_sdk/devtools/docs/docs/api/clients/ml-mixin.md +578 -0
- synapse_sdk/devtools/docs/docs/api/clients/ray.md +342 -0
- synapse_sdk/devtools/docs/docs/api/index.md +52 -0
- synapse_sdk/devtools/docs/docs/api/plugins/categories.md +43 -0
- synapse_sdk/devtools/docs/docs/api/plugins/models.md +114 -0
- synapse_sdk/devtools/docs/docs/api/plugins/utils.md +328 -0
- synapse_sdk/devtools/docs/docs/categories.md +0 -0
- synapse_sdk/devtools/docs/docs/cli-usage.md +280 -0
- synapse_sdk/devtools/docs/docs/concepts/index.md +38 -0
- synapse_sdk/devtools/docs/docs/configuration.md +83 -0
- synapse_sdk/devtools/docs/docs/contributing.md +306 -0
- synapse_sdk/devtools/docs/docs/examples/index.md +29 -0
- synapse_sdk/devtools/docs/docs/faq.md +179 -0
- synapse_sdk/devtools/docs/docs/features/converters/index.md +455 -0
- synapse_sdk/devtools/docs/docs/features/index.md +24 -0
- synapse_sdk/devtools/docs/docs/features/utils/file.md +415 -0
- synapse_sdk/devtools/docs/docs/features/utils/network.md +378 -0
- synapse_sdk/devtools/docs/docs/features/utils/storage.md +57 -0
- synapse_sdk/devtools/docs/docs/features/utils/types.md +51 -0
- synapse_sdk/devtools/docs/docs/installation.md +94 -0
- synapse_sdk/devtools/docs/docs/introduction.md +47 -0
- synapse_sdk/devtools/docs/docs/plugins/categories/neural-net-plugins/train-action-overview.md +814 -0
- synapse_sdk/devtools/docs/docs/plugins/categories/pre-annotation-plugins/pre-annotation-plugin-overview.md +198 -0
- synapse_sdk/devtools/docs/docs/plugins/categories/pre-annotation-plugins/to-task-action-development.md +1645 -0
- synapse_sdk/devtools/docs/docs/plugins/categories/pre-annotation-plugins/to-task-overview.md +717 -0
- synapse_sdk/devtools/docs/docs/plugins/categories/pre-annotation-plugins/to-task-template-development.md +1380 -0
- synapse_sdk/devtools/docs/docs/plugins/categories/upload-plugins/upload-plugin-action.md +948 -0
- synapse_sdk/devtools/docs/docs/plugins/categories/upload-plugins/upload-plugin-overview.md +544 -0
- synapse_sdk/devtools/docs/docs/plugins/categories/upload-plugins/upload-plugin-template.md +766 -0
- synapse_sdk/devtools/docs/docs/plugins/export-plugins.md +1092 -0
- synapse_sdk/devtools/docs/docs/plugins/plugins.md +852 -0
- synapse_sdk/devtools/docs/docs/quickstart.md +78 -0
- synapse_sdk/devtools/docs/docs/troubleshooting.md +519 -0
- synapse_sdk/devtools/docs/docs/tutorial-basics/_category_.json +8 -0
- synapse_sdk/devtools/docs/docs/tutorial-basics/congratulations.md +23 -0
- synapse_sdk/devtools/docs/docs/tutorial-basics/create-a-blog-post.md +34 -0
- synapse_sdk/devtools/docs/docs/tutorial-basics/create-a-document.md +57 -0
- synapse_sdk/devtools/docs/docs/tutorial-basics/create-a-page.md +43 -0
- synapse_sdk/devtools/docs/docs/tutorial-basics/deploy-your-site.md +31 -0
- synapse_sdk/devtools/docs/docs/tutorial-basics/markdown-features.mdx +152 -0
- synapse_sdk/devtools/docs/docs/tutorial-extras/_category_.json +7 -0
- synapse_sdk/devtools/docs/docs/tutorial-extras/img/docsVersionDropdown.png +0 -0
- synapse_sdk/devtools/docs/docs/tutorial-extras/img/localeDropdown.png +0 -0
- synapse_sdk/devtools/docs/docs/tutorial-extras/manage-docs-versions.md +55 -0
- synapse_sdk/devtools/docs/docs/tutorial-extras/translate-your-site.md +88 -0
- synapse_sdk/devtools/docs/docusaurus.config.ts +148 -0
- synapse_sdk/devtools/docs/i18n/ko/code.json +325 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/agent.md +43 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/annotation-mixin.md +289 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/backend.md +420 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/base.md +257 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/core-mixin.md +417 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/data-collection-mixin.md +356 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/hitl-mixin.md +192 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/index.md +391 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/integration-mixin.md +479 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/ml-mixin.md +284 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/ray.md +342 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/index.md +52 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/plugins/models.md +114 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/categories.md +0 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/cli-usage.md +280 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/concepts/index.md +38 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/configuration.md +83 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/contributing.md +306 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/examples/index.md +29 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/faq.md +179 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/converters/index.md +30 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/index.md +24 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/utils/file.md +415 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/utils/network.md +378 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/utils/storage.md +60 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/utils/types.md +51 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/installation.md +94 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/introduction.md +47 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/neural-net-plugins/train-action-overview.md +815 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/pre-annotation-plugins/pre-annotation-plugin-overview.md +198 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/pre-annotation-plugins/to-task-action-development.md +1645 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/pre-annotation-plugins/to-task-overview.md +717 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/pre-annotation-plugins/to-task-template-development.md +1380 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/upload-plugins/upload-plugin-action.md +948 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/upload-plugins/upload-plugin-overview.md +544 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/upload-plugins/upload-plugin-template.md +766 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/export-plugins.md +1092 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/plugins.md +117 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/quickstart.md +78 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/troubleshooting.md +519 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current.json +34 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-theme-classic/footer.json +42 -0
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-theme-classic/navbar.json +18 -0
- synapse_sdk/devtools/docs/package-lock.json +18784 -0
- synapse_sdk/devtools/docs/package.json +48 -0
- synapse_sdk/devtools/docs/sidebars.ts +122 -0
- synapse_sdk/devtools/docs/src/components/HomepageFeatures/index.tsx +71 -0
- synapse_sdk/devtools/docs/src/components/HomepageFeatures/styles.module.css +11 -0
- synapse_sdk/devtools/docs/src/css/custom.css +30 -0
- synapse_sdk/devtools/docs/src/pages/index.module.css +23 -0
- synapse_sdk/devtools/docs/src/pages/index.tsx +21 -0
- synapse_sdk/devtools/docs/src/pages/markdown-page.md +7 -0
- synapse_sdk/devtools/docs/static/.nojekyll +0 -0
- synapse_sdk/devtools/docs/static/img/docusaurus-social-card.jpg +0 -0
- synapse_sdk/devtools/docs/static/img/docusaurus.png +0 -0
- synapse_sdk/devtools/docs/static/img/favicon.ico +0 -0
- synapse_sdk/devtools/docs/static/img/logo.png +0 -0
- synapse_sdk/devtools/docs/static/img/undraw_docusaurus_mountain.svg +171 -0
- synapse_sdk/devtools/docs/static/img/undraw_docusaurus_react.svg +170 -0
- synapse_sdk/devtools/docs/static/img/undraw_docusaurus_tree.svg +40 -0
- synapse_sdk/devtools/docs/tsconfig.json +8 -0
- synapse_sdk/devtools/server.py +41 -0
- synapse_sdk/devtools/streamlit_app/__init__.py +5 -0
- synapse_sdk/devtools/streamlit_app/app.py +128 -0
- synapse_sdk/devtools/streamlit_app/services/__init__.py +11 -0
- synapse_sdk/devtools/streamlit_app/services/job_service.py +233 -0
- synapse_sdk/devtools/streamlit_app/services/plugin_service.py +236 -0
- synapse_sdk/devtools/streamlit_app/services/serve_service.py +95 -0
- synapse_sdk/devtools/streamlit_app/ui/__init__.py +15 -0
- synapse_sdk/devtools/streamlit_app/ui/config_tab.py +76 -0
- synapse_sdk/devtools/streamlit_app/ui/deployment_tab.py +66 -0
- synapse_sdk/devtools/streamlit_app/ui/http_tab.py +125 -0
- synapse_sdk/devtools/streamlit_app/ui/jobs_tab.py +573 -0
- synapse_sdk/devtools/streamlit_app/ui/serve_tab.py +346 -0
- synapse_sdk/devtools/streamlit_app/ui/status_bar.py +118 -0
- synapse_sdk/devtools/streamlit_app/utils/__init__.py +40 -0
- synapse_sdk/devtools/streamlit_app/utils/json_viewer.py +197 -0
- synapse_sdk/devtools/streamlit_app/utils/log_formatter.py +38 -0
- synapse_sdk/devtools/streamlit_app/utils/styles.py +241 -0
- synapse_sdk/devtools/streamlit_app/utils/ui_components.py +289 -0
- synapse_sdk/devtools/streamlit_app.py +10 -0
- synapse_sdk/loggers.py +74 -9
- synapse_sdk/plugins/README.md +1340 -0
- synapse_sdk/plugins/__init__.py +0 -13
- synapse_sdk/plugins/categories/base.py +145 -30
- synapse_sdk/plugins/categories/data_validation/actions/validation.py +72 -0
- synapse_sdk/plugins/categories/data_validation/templates/plugin/validation.py +33 -5
- synapse_sdk/plugins/categories/export/actions/__init__.py +3 -0
- synapse_sdk/plugins/categories/export/actions/export/__init__.py +28 -0
- synapse_sdk/plugins/categories/export/actions/export/action.py +165 -0
- synapse_sdk/plugins/categories/export/actions/export/enums.py +113 -0
- synapse_sdk/plugins/categories/export/actions/export/exceptions.py +53 -0
- synapse_sdk/plugins/categories/export/actions/export/models.py +74 -0
- synapse_sdk/plugins/categories/export/actions/export/run.py +195 -0
- synapse_sdk/plugins/categories/export/actions/export/utils.py +187 -0
- synapse_sdk/plugins/categories/export/templates/config.yaml +21 -0
- synapse_sdk/plugins/categories/export/templates/plugin/__init__.py +390 -0
- synapse_sdk/plugins/categories/export/templates/plugin/export.py +160 -0
- synapse_sdk/plugins/categories/neural_net/actions/deployment.py +29 -14
- synapse_sdk/plugins/categories/neural_net/actions/inference.py +13 -1
- synapse_sdk/plugins/categories/neural_net/actions/train.py +1084 -38
- synapse_sdk/plugins/categories/neural_net/actions/tune.py +534 -0
- synapse_sdk/plugins/categories/neural_net/base/__init__.py +0 -0
- synapse_sdk/plugins/categories/neural_net/base/inference.py +37 -0
- synapse_sdk/plugins/categories/neural_net/templates/config.yaml +30 -5
- synapse_sdk/plugins/categories/neural_net/templates/plugin/inference.py +26 -10
- synapse_sdk/plugins/categories/pre_annotation/actions/__init__.py +4 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/pre_annotation/__init__.py +3 -0
- synapse_sdk/plugins/categories/{export/actions/export.py → pre_annotation/actions/pre_annotation/action.py} +4 -4
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/__init__.py +28 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/action.py +145 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/enums.py +269 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/exceptions.py +14 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/factory.py +76 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/models.py +97 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/orchestrator.py +250 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/run.py +64 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/__init__.py +17 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/annotation.py +287 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/base.py +170 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/extraction.py +83 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/metrics.py +87 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/preprocessor.py +127 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/validation.py +143 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/to_task.py +966 -0
- synapse_sdk/plugins/categories/pre_annotation/templates/config.yaml +19 -0
- synapse_sdk/plugins/categories/pre_annotation/templates/plugin/to_task.py +40 -0
- synapse_sdk/plugins/categories/smart_tool/templates/config.yaml +5 -2
- synapse_sdk/plugins/categories/upload/__init__.py +0 -0
- synapse_sdk/plugins/categories/upload/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/upload/actions/upload/__init__.py +19 -0
- synapse_sdk/plugins/categories/upload/actions/upload/action.py +232 -0
- synapse_sdk/plugins/categories/upload/actions/upload/context.py +185 -0
- synapse_sdk/plugins/categories/upload/actions/upload/enums.py +471 -0
- synapse_sdk/plugins/categories/upload/actions/upload/exceptions.py +36 -0
- synapse_sdk/plugins/categories/upload/actions/upload/factory.py +138 -0
- synapse_sdk/plugins/categories/upload/actions/upload/models.py +203 -0
- synapse_sdk/plugins/categories/upload/actions/upload/orchestrator.py +183 -0
- synapse_sdk/plugins/categories/upload/actions/upload/registry.py +113 -0
- synapse_sdk/plugins/categories/upload/actions/upload/run.py +179 -0
- synapse_sdk/plugins/categories/upload/actions/upload/steps/__init__.py +1 -0
- synapse_sdk/plugins/categories/upload/actions/upload/steps/base.py +107 -0
- synapse_sdk/plugins/categories/upload/actions/upload/steps/cleanup.py +62 -0
- synapse_sdk/plugins/categories/upload/actions/upload/steps/collection.py +63 -0
- synapse_sdk/plugins/categories/upload/actions/upload/steps/generate.py +84 -0
- synapse_sdk/plugins/categories/upload/actions/upload/steps/initialize.py +82 -0
- synapse_sdk/plugins/categories/upload/actions/upload/steps/metadata.py +235 -0
- synapse_sdk/plugins/categories/upload/actions/upload/steps/organize.py +203 -0
- synapse_sdk/plugins/categories/upload/actions/upload/steps/upload.py +97 -0
- synapse_sdk/plugins/categories/upload/actions/upload/steps/validate.py +71 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/__init__.py +1 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/base.py +82 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/data_unit/__init__.py +1 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/data_unit/batch.py +39 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/data_unit/single.py +29 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/file_discovery/__init__.py +1 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/file_discovery/flat.py +258 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/file_discovery/recursive.py +281 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/metadata/__init__.py +1 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/metadata/excel.py +174 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/metadata/none.py +16 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/upload/__init__.py +1 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/upload/sync.py +84 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/validation/__init__.py +1 -0
- synapse_sdk/plugins/categories/upload/actions/upload/strategies/validation/default.py +60 -0
- synapse_sdk/plugins/categories/upload/actions/upload/utils.py +250 -0
- synapse_sdk/plugins/categories/upload/templates/README.md +470 -0
- synapse_sdk/plugins/categories/upload/templates/config.yaml +33 -0
- synapse_sdk/plugins/categories/upload/templates/plugin/__init__.py +294 -0
- synapse_sdk/plugins/categories/upload/templates/plugin/upload.py +102 -0
- synapse_sdk/plugins/enums.py +3 -1
- synapse_sdk/plugins/models.py +140 -16
- synapse_sdk/plugins/templates/plugin-config-schema.json +406 -0
- synapse_sdk/plugins/templates/schema.json +491 -0
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/config.yaml +1 -0
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/requirements.txt +1 -1
- synapse_sdk/plugins/utils/__init__.py +46 -0
- synapse_sdk/plugins/utils/actions.py +119 -0
- synapse_sdk/plugins/utils/config.py +203 -0
- synapse_sdk/plugins/utils/legacy.py +95 -0
- synapse_sdk/plugins/utils/ray_gcs.py +66 -0
- synapse_sdk/plugins/utils/registry.py +58 -0
- synapse_sdk/shared/__init__.py +25 -0
- synapse_sdk/shared/enums.py +93 -0
- synapse_sdk/types.py +19 -0
- synapse_sdk/utils/converters/__init__.py +240 -0
- synapse_sdk/utils/converters/coco/__init__.py +0 -0
- synapse_sdk/utils/converters/coco/from_dm.py +322 -0
- synapse_sdk/utils/converters/coco/to_dm.py +215 -0
- synapse_sdk/utils/converters/dm/__init__.py +56 -0
- synapse_sdk/utils/converters/dm/from_v1.py +627 -0
- synapse_sdk/utils/converters/dm/to_v1.py +367 -0
- synapse_sdk/utils/converters/pascal/__init__.py +0 -0
- synapse_sdk/utils/converters/pascal/from_dm.py +244 -0
- synapse_sdk/utils/converters/pascal/to_dm.py +214 -0
- synapse_sdk/utils/converters/yolo/__init__.py +0 -0
- synapse_sdk/utils/converters/yolo/from_dm.py +384 -0
- synapse_sdk/utils/converters/yolo/to_dm.py +267 -0
- synapse_sdk/utils/dataset.py +46 -0
- synapse_sdk/utils/encryption.py +158 -0
- synapse_sdk/utils/file/__init__.py +39 -0
- synapse_sdk/utils/file/archive.py +32 -0
- synapse_sdk/utils/file/checksum.py +56 -0
- synapse_sdk/utils/file/chunking.py +31 -0
- synapse_sdk/utils/file/download.py +385 -0
- synapse_sdk/utils/file/encoding.py +40 -0
- synapse_sdk/utils/file/io.py +22 -0
- synapse_sdk/utils/file/video/__init__.py +29 -0
- synapse_sdk/utils/file/video/transcode.py +307 -0
- synapse_sdk/utils/file.py.backup +301 -0
- synapse_sdk/utils/http.py +138 -0
- synapse_sdk/utils/network.py +309 -0
- synapse_sdk/utils/storage/__init__.py +72 -0
- synapse_sdk/utils/storage/providers/__init__.py +183 -0
- synapse_sdk/utils/storage/providers/file_system.py +134 -0
- synapse_sdk/utils/storage/providers/gcp.py +13 -0
- synapse_sdk/utils/storage/providers/http.py +190 -0
- synapse_sdk/utils/storage/providers/s3.py +91 -0
- synapse_sdk/utils/storage/providers/sftp.py +47 -0
- synapse_sdk/utils/storage/registry.py +17 -0
- synapse_sdk-2025.11.7.dist-info/METADATA +122 -0
- synapse_sdk-2025.11.7.dist-info/RECORD +386 -0
- {synapse_sdk-1.0.0a13.dist-info → synapse_sdk-2025.11.7.dist-info}/WHEEL +1 -1
- synapse_sdk/clients/backend/dataset.py +0 -51
- synapse_sdk/plugins/categories/import/actions/import.py +0 -10
- synapse_sdk/plugins/cli/__init__.py +0 -21
- synapse_sdk/plugins/cli/publish.py +0 -37
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.env +0 -24
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.env.dist +0 -24
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/main.py +0 -4
- synapse_sdk/plugins/utils.py +0 -50
- synapse_sdk/utils/file.py +0 -87
- synapse_sdk/utils/storage.py +0 -91
- synapse_sdk-1.0.0a13.dist-info/METADATA +0 -43
- synapse_sdk-1.0.0a13.dist-info/RECORD +0 -111
- /synapse_sdk/{plugins/categories/import → clients/validators}/__init__.py +0 -0
- /synapse_sdk/{plugins/categories/import/actions → devtools}/__init__.py +0 -0
- {synapse_sdk-1.0.0a13.dist-info → synapse_sdk-2025.11.7.dist-info}/entry_points.txt +0 -0
- {synapse_sdk-1.0.0a13.dist-info → synapse_sdk-2025.11.7.dist-info/licenses}/LICENSE +0 -0
- {synapse_sdk-1.0.0a13.dist-info → synapse_sdk-2025.11.7.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,687 @@
|
|
|
1
|
+
"""Code-server integration for remote plugin development."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import shutil
|
|
5
|
+
import socket
|
|
6
|
+
import subprocess
|
|
7
|
+
import webbrowser
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Optional
|
|
10
|
+
from urllib.parse import quote
|
|
11
|
+
|
|
12
|
+
import click
|
|
13
|
+
import inquirer
|
|
14
|
+
import yaml
|
|
15
|
+
|
|
16
|
+
from synapse_sdk.cli.config import fetch_agents_from_backend, get_agent_config
|
|
17
|
+
from synapse_sdk.devtools.config import get_backend_config
|
|
18
|
+
from synapse_sdk.utils.encryption import encrypt_plugin, get_plugin_info, is_plugin_directory
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_agent_client(agent: Optional[str] = None):
|
|
22
|
+
"""Helper function to get an agent client.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
agent: Optional agent ID. If not provided, uses current agent or prompts user.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
tuple: (AgentClient instance, agent_id) or (None, None) if failed
|
|
29
|
+
"""
|
|
30
|
+
# Get current agent configuration
|
|
31
|
+
agent_config = get_agent_config()
|
|
32
|
+
backend_config = get_backend_config()
|
|
33
|
+
|
|
34
|
+
if not backend_config:
|
|
35
|
+
click.echo("❌ No backend configured. Run 'synapse config' first.")
|
|
36
|
+
return None, None
|
|
37
|
+
|
|
38
|
+
# If no agent specified, use current agent or let user choose
|
|
39
|
+
if not agent:
|
|
40
|
+
if agent_config and agent_config.get('id'):
|
|
41
|
+
agent = agent_config['id']
|
|
42
|
+
click.echo(f'Using current agent: {agent_config.get("name", agent)}')
|
|
43
|
+
else:
|
|
44
|
+
# List available agents
|
|
45
|
+
agents, error = fetch_agents_from_backend()
|
|
46
|
+
if not agents:
|
|
47
|
+
click.echo('❌ No agents available. Check your backend configuration.')
|
|
48
|
+
return None, None
|
|
49
|
+
|
|
50
|
+
if len(agents) == 1:
|
|
51
|
+
# If only one agent, use it
|
|
52
|
+
agent = agents[0]['id']
|
|
53
|
+
click.echo(f'Using agent: {agents[0].get("name", agent)}')
|
|
54
|
+
else:
|
|
55
|
+
# Let user choose
|
|
56
|
+
click.echo('Available agents:')
|
|
57
|
+
for i, agent_info in enumerate(agents, 1):
|
|
58
|
+
status = agent_info.get('status_display', 'Unknown')
|
|
59
|
+
name = agent_info.get('name', agent_info['id'])
|
|
60
|
+
click.echo(f' {i}. {name} ({status})')
|
|
61
|
+
|
|
62
|
+
try:
|
|
63
|
+
choice = click.prompt('Select agent', type=int)
|
|
64
|
+
if 1 <= choice <= len(agents):
|
|
65
|
+
agent = agents[choice - 1]['id']
|
|
66
|
+
else:
|
|
67
|
+
click.echo('❌ Invalid selection')
|
|
68
|
+
return None, None
|
|
69
|
+
except (ValueError, EOFError, KeyboardInterrupt):
|
|
70
|
+
click.echo('\n❌ Cancelled')
|
|
71
|
+
return None, None
|
|
72
|
+
|
|
73
|
+
# Get agent details from backend
|
|
74
|
+
try:
|
|
75
|
+
from synapse_sdk.clients.backend import BackendClient
|
|
76
|
+
|
|
77
|
+
backend_client = BackendClient(backend_config['host'], access_token=backend_config['token'])
|
|
78
|
+
|
|
79
|
+
# Get agent information
|
|
80
|
+
try:
|
|
81
|
+
agent_info = backend_client._get(f'agents/{agent}/')
|
|
82
|
+
except Exception as e:
|
|
83
|
+
click.echo(f'❌ Failed to get agent information for: {agent}')
|
|
84
|
+
click.echo(f'Error: {e}')
|
|
85
|
+
return None, None
|
|
86
|
+
|
|
87
|
+
if not agent_info or not agent_info.get('url'):
|
|
88
|
+
click.echo(f'❌ Agent {agent} does not have a valid URL')
|
|
89
|
+
return None, None
|
|
90
|
+
|
|
91
|
+
# Get the agent token from local configuration
|
|
92
|
+
agent_token = agent_config.get('token')
|
|
93
|
+
if not agent_token:
|
|
94
|
+
click.echo('❌ No agent token found in configuration')
|
|
95
|
+
click.echo("Run 'synapse config' to configure the agent")
|
|
96
|
+
return None, None
|
|
97
|
+
|
|
98
|
+
# Create agent client
|
|
99
|
+
from synapse_sdk.clients.agent import AgentClient
|
|
100
|
+
|
|
101
|
+
client = AgentClient(base_url=agent_info['url'], agent_token=agent_token, user_token=backend_config['token'])
|
|
102
|
+
return client, agent
|
|
103
|
+
|
|
104
|
+
except Exception as e:
|
|
105
|
+
click.echo(f'❌ Failed to connect to agent: {e}')
|
|
106
|
+
return None, None
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def detect_and_encrypt_plugin(workspace_path: str) -> Optional[dict]:
|
|
110
|
+
"""Detect and encrypt plugin code in the workspace.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
workspace_path: Path to check for plugin
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
dict: Encrypted plugin data or None if no plugin found
|
|
117
|
+
"""
|
|
118
|
+
plugin_path = Path(workspace_path)
|
|
119
|
+
|
|
120
|
+
if not is_plugin_directory(plugin_path):
|
|
121
|
+
return None
|
|
122
|
+
|
|
123
|
+
try:
|
|
124
|
+
plugin_info = get_plugin_info(plugin_path)
|
|
125
|
+
click.echo(f'🔍 Detected plugin: {plugin_info["name"]}')
|
|
126
|
+
|
|
127
|
+
if 'version' in plugin_info:
|
|
128
|
+
click.echo(f' Version: {plugin_info["version"]}')
|
|
129
|
+
if 'description' in plugin_info:
|
|
130
|
+
click.echo(f' Description: {plugin_info["description"]}')
|
|
131
|
+
|
|
132
|
+
click.echo('🔐 Encrypting plugin code...')
|
|
133
|
+
encrypted_package, password = encrypt_plugin(plugin_path)
|
|
134
|
+
|
|
135
|
+
# Add password to the package (in real implementation, this would be handled securely)
|
|
136
|
+
encrypted_package['password'] = password
|
|
137
|
+
|
|
138
|
+
click.echo('✅ Plugin code encrypted successfully')
|
|
139
|
+
return encrypted_package
|
|
140
|
+
|
|
141
|
+
except Exception as e:
|
|
142
|
+
click.echo(f'❌ Failed to encrypt plugin: {e}')
|
|
143
|
+
return None
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def is_ssh_session() -> bool:
|
|
147
|
+
"""Check if we're in an SSH session.
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
bool: True if in SSH session, False otherwise
|
|
151
|
+
"""
|
|
152
|
+
return bool(os.environ.get('SSH_CONNECTION') or os.environ.get('SSH_CLIENT'))
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def is_vscode_terminal() -> bool:
|
|
156
|
+
"""Check if we're running in a VSCode terminal.
|
|
157
|
+
|
|
158
|
+
Returns:
|
|
159
|
+
bool: True if in VSCode terminal, False otherwise
|
|
160
|
+
"""
|
|
161
|
+
return os.environ.get('TERM_PROGRAM') == 'vscode'
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def is_vscode_ssh_session() -> bool:
|
|
165
|
+
"""Check if we're in a VSCode terminal over SSH.
|
|
166
|
+
|
|
167
|
+
Returns:
|
|
168
|
+
bool: True if in VSCode terminal via SSH, False otherwise
|
|
169
|
+
"""
|
|
170
|
+
return is_vscode_terminal() and is_ssh_session()
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def get_ssh_tunnel_instructions(port: int) -> str:
|
|
174
|
+
"""Get SSH tunnel setup instructions for VSCode users.
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
port: The port number code-server is running on
|
|
178
|
+
|
|
179
|
+
Returns:
|
|
180
|
+
str: Instructions for setting up SSH tunnel
|
|
181
|
+
"""
|
|
182
|
+
ssh_client = os.environ.get('SSH_CLIENT', '').split()[0] if os.environ.get('SSH_CLIENT') else 'your_server'
|
|
183
|
+
|
|
184
|
+
instructions = f"""
|
|
185
|
+
📡 VSCode SSH Tunnel Setup:
|
|
186
|
+
|
|
187
|
+
Since you're using VSCode's integrated terminal over SSH, you can access code-server locally by:
|
|
188
|
+
|
|
189
|
+
1. Using VSCode's built-in port forwarding:
|
|
190
|
+
• Open Command Palette (Cmd/Ctrl+Shift+P)
|
|
191
|
+
• Type "Forward a Port"
|
|
192
|
+
• Enter port: {port}
|
|
193
|
+
• VSCode will automatically forward the port
|
|
194
|
+
|
|
195
|
+
2. Or manually forward the port in a new local terminal:
|
|
196
|
+
ssh -L {port}:localhost:{port} {ssh_client}
|
|
197
|
+
|
|
198
|
+
3. Then open in your local browser:
|
|
199
|
+
http://localhost:{port}
|
|
200
|
+
"""
|
|
201
|
+
return instructions
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def open_browser_smart(url: str) -> bool:
|
|
205
|
+
"""Open browser with smart fallback handling.
|
|
206
|
+
|
|
207
|
+
Attempts to open a browser using multiple methods, with appropriate
|
|
208
|
+
handling for SSH sessions and headless environments.
|
|
209
|
+
|
|
210
|
+
Args:
|
|
211
|
+
url: URL to open
|
|
212
|
+
|
|
213
|
+
Returns:
|
|
214
|
+
bool: True if browser was opened successfully, False otherwise
|
|
215
|
+
"""
|
|
216
|
+
# Don't even try to open browser in SSH sessions (except VSCode can handle it)
|
|
217
|
+
if is_ssh_session() and not is_vscode_terminal():
|
|
218
|
+
return False
|
|
219
|
+
|
|
220
|
+
# Try Python's webbrowser module first (cross-platform)
|
|
221
|
+
try:
|
|
222
|
+
if webbrowser.open(url):
|
|
223
|
+
return True
|
|
224
|
+
except Exception:
|
|
225
|
+
pass
|
|
226
|
+
|
|
227
|
+
# Try platform-specific commands
|
|
228
|
+
commands = []
|
|
229
|
+
|
|
230
|
+
# Check for macOS
|
|
231
|
+
if shutil.which('open'):
|
|
232
|
+
commands.append(['open', url])
|
|
233
|
+
|
|
234
|
+
# Check for Linux with display
|
|
235
|
+
if os.environ.get('DISPLAY'):
|
|
236
|
+
if shutil.which('xdg-open'):
|
|
237
|
+
commands.append(['xdg-open', url])
|
|
238
|
+
if shutil.which('gnome-open'):
|
|
239
|
+
commands.append(['gnome-open', url])
|
|
240
|
+
if shutil.which('kde-open'):
|
|
241
|
+
commands.append(['kde-open', url])
|
|
242
|
+
|
|
243
|
+
# Try each command
|
|
244
|
+
for cmd in commands:
|
|
245
|
+
try:
|
|
246
|
+
result = subprocess.run(cmd, capture_output=True, text=True, timeout=2)
|
|
247
|
+
if result.returncode == 0:
|
|
248
|
+
return True
|
|
249
|
+
except Exception:
|
|
250
|
+
continue
|
|
251
|
+
|
|
252
|
+
return False
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def is_port_in_use(port: int) -> bool:
|
|
256
|
+
"""Check if a port is already in use.
|
|
257
|
+
|
|
258
|
+
Args:
|
|
259
|
+
port: Port number to check
|
|
260
|
+
|
|
261
|
+
Returns:
|
|
262
|
+
bool: True if port is in use, False otherwise
|
|
263
|
+
"""
|
|
264
|
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
265
|
+
try:
|
|
266
|
+
s.bind(('127.0.0.1', port))
|
|
267
|
+
return False
|
|
268
|
+
except socket.error:
|
|
269
|
+
return True
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def get_process_on_port(port: int) -> Optional[str]:
|
|
273
|
+
"""Get the name of the process using a specific port.
|
|
274
|
+
|
|
275
|
+
Args:
|
|
276
|
+
port: Port number to check
|
|
277
|
+
|
|
278
|
+
Returns:
|
|
279
|
+
str: Process name if found, None otherwise
|
|
280
|
+
"""
|
|
281
|
+
try:
|
|
282
|
+
# Use lsof to find the process
|
|
283
|
+
result = subprocess.run(['lsof', '-i', f':{port}', '-t'], capture_output=True, text=True, timeout=2)
|
|
284
|
+
|
|
285
|
+
if result.returncode == 0 and result.stdout.strip():
|
|
286
|
+
# Get the PID
|
|
287
|
+
pid = result.stdout.strip().split('\n')[0]
|
|
288
|
+
|
|
289
|
+
# Get process details
|
|
290
|
+
proc_result = subprocess.run(['ps', '-p', pid, '-o', 'comm='], capture_output=True, text=True, timeout=2)
|
|
291
|
+
|
|
292
|
+
if proc_result.returncode == 0:
|
|
293
|
+
process_name = proc_result.stdout.strip()
|
|
294
|
+
# Check if it's a code-server process
|
|
295
|
+
if 'node' in process_name or 'code-server' in process_name:
|
|
296
|
+
# Try to get more details
|
|
297
|
+
cmd_result = subprocess.run(
|
|
298
|
+
['ps', '-p', pid, '-o', 'args='], capture_output=True, text=True, timeout=2
|
|
299
|
+
)
|
|
300
|
+
if cmd_result.returncode == 0 and 'code-server' in cmd_result.stdout:
|
|
301
|
+
return 'code-server'
|
|
302
|
+
return process_name
|
|
303
|
+
except Exception:
|
|
304
|
+
pass
|
|
305
|
+
|
|
306
|
+
return None
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def is_code_server_installed() -> bool:
|
|
310
|
+
"""Check if code-server is installed locally.
|
|
311
|
+
|
|
312
|
+
Returns:
|
|
313
|
+
bool: True if code-server is available in PATH
|
|
314
|
+
"""
|
|
315
|
+
return shutil.which('code-server') is not None
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
def get_code_server_port() -> int:
|
|
319
|
+
"""Get code-server port from config file.
|
|
320
|
+
|
|
321
|
+
Returns:
|
|
322
|
+
int: Port number from config, defaults to 8070 if not found
|
|
323
|
+
"""
|
|
324
|
+
config_path = Path.home() / '.config' / 'code-server' / 'config.yaml'
|
|
325
|
+
|
|
326
|
+
try:
|
|
327
|
+
if config_path.exists():
|
|
328
|
+
with open(config_path, 'r') as f:
|
|
329
|
+
config = yaml.safe_load(f)
|
|
330
|
+
|
|
331
|
+
# Parse bind-addr which can be in format "127.0.0.1:8070" or just ":8070"
|
|
332
|
+
bind_addr = config.get('bind-addr', '')
|
|
333
|
+
if ':' in bind_addr:
|
|
334
|
+
port_str = bind_addr.split(':')[-1]
|
|
335
|
+
try:
|
|
336
|
+
return int(port_str)
|
|
337
|
+
except ValueError:
|
|
338
|
+
pass
|
|
339
|
+
except Exception:
|
|
340
|
+
# If any error occurs reading config, fall back to default
|
|
341
|
+
pass
|
|
342
|
+
|
|
343
|
+
# Default port if config not found or invalid
|
|
344
|
+
return 8070
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
def launch_local_code_server(workspace_path: str, open_browser: bool = True, custom_port: Optional[int] = None) -> None:
|
|
348
|
+
"""Launch local code-server instance.
|
|
349
|
+
|
|
350
|
+
Args:
|
|
351
|
+
workspace_path: Directory to open in code-server
|
|
352
|
+
open_browser: Whether to open browser automatically
|
|
353
|
+
custom_port: Optional custom port to use instead of config/default
|
|
354
|
+
"""
|
|
355
|
+
try:
|
|
356
|
+
# Use custom port if provided, otherwise get from config
|
|
357
|
+
port = custom_port if custom_port else get_code_server_port()
|
|
358
|
+
|
|
359
|
+
# Check if port is already in use
|
|
360
|
+
if is_port_in_use(port):
|
|
361
|
+
process_name = get_process_on_port(port)
|
|
362
|
+
|
|
363
|
+
if process_name == 'code-server':
|
|
364
|
+
# Code-server is already running
|
|
365
|
+
click.echo(f'⚠️ Code-server is already running on port {port}')
|
|
366
|
+
|
|
367
|
+
# Create URL with folder query parameter
|
|
368
|
+
encoded_path = quote(workspace_path)
|
|
369
|
+
url_with_folder = f'http://localhost:{port}/?folder={encoded_path}'
|
|
370
|
+
|
|
371
|
+
# Ask user what to do
|
|
372
|
+
questions = [
|
|
373
|
+
inquirer.List(
|
|
374
|
+
'action',
|
|
375
|
+
message='What would you like to do?',
|
|
376
|
+
choices=[
|
|
377
|
+
('Use existing code-server instance', 'use_existing'),
|
|
378
|
+
('Stop existing and start new instance', 'restart'),
|
|
379
|
+
('Cancel', 'cancel'),
|
|
380
|
+
],
|
|
381
|
+
)
|
|
382
|
+
]
|
|
383
|
+
|
|
384
|
+
try:
|
|
385
|
+
answers = inquirer.prompt(questions)
|
|
386
|
+
|
|
387
|
+
if not answers or answers['action'] == 'cancel':
|
|
388
|
+
click.echo('Cancelled')
|
|
389
|
+
return
|
|
390
|
+
|
|
391
|
+
if answers['action'] == 'use_existing':
|
|
392
|
+
click.echo('\n✅ Using existing code-server instance')
|
|
393
|
+
click.echo(f' URL: {url_with_folder}')
|
|
394
|
+
|
|
395
|
+
# Optionally open browser
|
|
396
|
+
if open_browser:
|
|
397
|
+
if is_vscode_ssh_session():
|
|
398
|
+
# Special handling for VSCode SSH sessions
|
|
399
|
+
click.echo(get_ssh_tunnel_instructions(port))
|
|
400
|
+
click.echo(f'🔗 Remote URL: {url_with_folder}')
|
|
401
|
+
click.echo(f'\n✨ After port forwarding, access at: http://localhost:{port}')
|
|
402
|
+
elif is_ssh_session():
|
|
403
|
+
click.echo('📝 SSH session detected - please open the URL in your local browser')
|
|
404
|
+
click.echo(f'👉 URL: {url_with_folder}')
|
|
405
|
+
elif open_browser_smart(url_with_folder):
|
|
406
|
+
click.echo('✅ Browser opened successfully')
|
|
407
|
+
else:
|
|
408
|
+
click.echo('⚠️ Could not open browser automatically')
|
|
409
|
+
click.echo(f'👉 URL: {url_with_folder}')
|
|
410
|
+
return
|
|
411
|
+
|
|
412
|
+
if answers['action'] == 'restart':
|
|
413
|
+
# Stop existing code-server
|
|
414
|
+
click.echo('Stopping existing code-server...')
|
|
415
|
+
try:
|
|
416
|
+
# Get PID of code-server process
|
|
417
|
+
result = subprocess.run(
|
|
418
|
+
['lsof', '-i', f':{port}', '-t'], capture_output=True, text=True, timeout=2
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
if result.returncode == 0 and result.stdout.strip():
|
|
422
|
+
pid = result.stdout.strip().split('\n')[0]
|
|
423
|
+
subprocess.run(['kill', pid], timeout=5)
|
|
424
|
+
|
|
425
|
+
# Wait a moment for process to stop
|
|
426
|
+
import time
|
|
427
|
+
|
|
428
|
+
time.sleep(2)
|
|
429
|
+
|
|
430
|
+
click.echo('✅ Existing code-server stopped')
|
|
431
|
+
except Exception as e:
|
|
432
|
+
click.echo(f'⚠️ Could not stop existing code-server: {e}')
|
|
433
|
+
click.echo('Please stop it manually and try again')
|
|
434
|
+
return
|
|
435
|
+
|
|
436
|
+
except (KeyboardInterrupt, EOFError):
|
|
437
|
+
click.echo('\nCancelled')
|
|
438
|
+
return
|
|
439
|
+
|
|
440
|
+
else:
|
|
441
|
+
# Another process is using the port
|
|
442
|
+
click.echo(f'❌ Port {port} is already in use by: {process_name or "unknown process"}')
|
|
443
|
+
if not custom_port:
|
|
444
|
+
click.echo('\nYou can:')
|
|
445
|
+
click.echo('1. Stop the process using the port')
|
|
446
|
+
click.echo('2. Use a different port with --port option (e.g., --port 8071)')
|
|
447
|
+
click.echo('3. Change the default port in ~/.config/code-server/config.yaml')
|
|
448
|
+
else:
|
|
449
|
+
click.echo(f'Please try a different port or stop the process using port {port}')
|
|
450
|
+
return
|
|
451
|
+
|
|
452
|
+
# Create URL with folder query parameter
|
|
453
|
+
encoded_path = quote(workspace_path)
|
|
454
|
+
url_with_folder = f'http://localhost:{port}/?folder={encoded_path}'
|
|
455
|
+
|
|
456
|
+
# Basic code-server command - let code-server handle the workspace internally
|
|
457
|
+
cmd = ['code-server']
|
|
458
|
+
|
|
459
|
+
# Add custom port binding if specified
|
|
460
|
+
if custom_port:
|
|
461
|
+
cmd.extend(['--bind-addr', f'127.0.0.1:{port}'])
|
|
462
|
+
|
|
463
|
+
cmd.append(workspace_path)
|
|
464
|
+
|
|
465
|
+
if not open_browser:
|
|
466
|
+
cmd.append('--disable-getting-started-override')
|
|
467
|
+
|
|
468
|
+
click.echo(f'🚀 Starting local code-server for workspace: {workspace_path}')
|
|
469
|
+
if custom_port:
|
|
470
|
+
click.echo(f' Using custom port: {port}')
|
|
471
|
+
click.echo(f' URL: {url_with_folder}')
|
|
472
|
+
click.echo(' Press Ctrl+C to stop the server')
|
|
473
|
+
|
|
474
|
+
# Start code-server in background if we need to open browser
|
|
475
|
+
if open_browser:
|
|
476
|
+
# Start code-server in background
|
|
477
|
+
import threading
|
|
478
|
+
import time
|
|
479
|
+
|
|
480
|
+
def start_server():
|
|
481
|
+
subprocess.run(cmd)
|
|
482
|
+
|
|
483
|
+
server_thread = threading.Thread(target=start_server, daemon=True)
|
|
484
|
+
server_thread.start()
|
|
485
|
+
|
|
486
|
+
# Give server a moment to start
|
|
487
|
+
click.echo(' Waiting for server to start...')
|
|
488
|
+
time.sleep(3)
|
|
489
|
+
|
|
490
|
+
# Open browser with folder parameter
|
|
491
|
+
if is_vscode_ssh_session():
|
|
492
|
+
# Special handling for VSCode SSH sessions
|
|
493
|
+
click.echo(get_ssh_tunnel_instructions(port))
|
|
494
|
+
click.echo(f'🔗 Remote URL: {url_with_folder}')
|
|
495
|
+
click.echo(f'\n✨ After port forwarding, access at: http://localhost:{port}')
|
|
496
|
+
elif is_ssh_session():
|
|
497
|
+
click.echo('📝 SSH session detected - please open the URL in your local browser')
|
|
498
|
+
click.echo(f'👉 URL: {url_with_folder}')
|
|
499
|
+
elif open_browser_smart(url_with_folder):
|
|
500
|
+
click.echo('✅ Browser opened successfully')
|
|
501
|
+
else:
|
|
502
|
+
click.echo('⚠️ Could not open browser automatically')
|
|
503
|
+
click.echo(f'👉 Please manually open: {url_with_folder}')
|
|
504
|
+
|
|
505
|
+
# Wait for the server thread (blocking)
|
|
506
|
+
try:
|
|
507
|
+
server_thread.join()
|
|
508
|
+
except KeyboardInterrupt:
|
|
509
|
+
click.echo('\n\n✅ Code-server stopped')
|
|
510
|
+
else:
|
|
511
|
+
# Start code-server normally (blocking)
|
|
512
|
+
subprocess.run(cmd)
|
|
513
|
+
|
|
514
|
+
except KeyboardInterrupt:
|
|
515
|
+
click.echo('\n\n✅ Code-server stopped')
|
|
516
|
+
except Exception as e:
|
|
517
|
+
click.echo(f'❌ Failed to start local code-server: {e}')
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
def show_code_server_installation_help() -> None:
|
|
521
|
+
"""Show installation instructions for code-server."""
|
|
522
|
+
click.echo('\n❌ Code-server is not installed locally')
|
|
523
|
+
click.echo('\n📦 To install code-server, choose one of these options:')
|
|
524
|
+
click.echo('\n1. Install script (recommended):')
|
|
525
|
+
click.echo(' curl -fsSL https://code-server.dev/install.sh | sh')
|
|
526
|
+
click.echo('\n2. Using npm:')
|
|
527
|
+
click.echo(' npm install -g code-server')
|
|
528
|
+
click.echo('\n3. Using yarn:')
|
|
529
|
+
click.echo(' yarn global add code-server')
|
|
530
|
+
click.echo('\n4. Download from releases:')
|
|
531
|
+
click.echo(' https://github.com/coder/code-server/releases')
|
|
532
|
+
click.echo('\n📚 For more installation options, visit: https://coder.com/docs/code-server/latest/install')
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
def run_agent_code_server(agent: Optional[str], workspace: str, open_browser: bool) -> None:
|
|
536
|
+
"""Run code-server through agent (existing functionality).
|
|
537
|
+
|
|
538
|
+
Args:
|
|
539
|
+
agent: Agent name or ID
|
|
540
|
+
workspace: Workspace directory path
|
|
541
|
+
open_browser: Whether to open browser automatically
|
|
542
|
+
"""
|
|
543
|
+
client, _ = get_agent_client(agent)
|
|
544
|
+
if not client:
|
|
545
|
+
return
|
|
546
|
+
|
|
547
|
+
# Check for plugin and show info if found
|
|
548
|
+
plugin_data = detect_and_encrypt_plugin(workspace)
|
|
549
|
+
if plugin_data:
|
|
550
|
+
click.echo('📦 Plugin detected and encrypted for secure transfer')
|
|
551
|
+
|
|
552
|
+
# Get code-server information
|
|
553
|
+
try:
|
|
554
|
+
info = client.get_code_server_info(workspace_path=workspace)
|
|
555
|
+
except Exception as e:
|
|
556
|
+
# Handle other errors
|
|
557
|
+
click.echo(f'❌ Failed to get code-server info: {e}')
|
|
558
|
+
click.echo('\nNote: The agent might not have code-server endpoint implemented yet.')
|
|
559
|
+
return
|
|
560
|
+
|
|
561
|
+
# Ensure info is a dictionary
|
|
562
|
+
if not isinstance(info, dict):
|
|
563
|
+
click.echo('❌ Invalid response from agent')
|
|
564
|
+
return
|
|
565
|
+
|
|
566
|
+
if not info.get('available', False):
|
|
567
|
+
message = info.get('message', 'Code-server is not available')
|
|
568
|
+
click.echo(f'❌ {message}')
|
|
569
|
+
click.echo('\nTo enable code-server, reinstall the agent with code-server support.')
|
|
570
|
+
return
|
|
571
|
+
|
|
572
|
+
# Display connection information
|
|
573
|
+
click.echo('\n✅ Code-Server is available!')
|
|
574
|
+
|
|
575
|
+
# Get the workspace path from response or use the requested one
|
|
576
|
+
actual_workspace = info.get('workspace', workspace)
|
|
577
|
+
|
|
578
|
+
# Show web browser access
|
|
579
|
+
click.echo('\n🌐 Web-based VS Code:')
|
|
580
|
+
url = info.get('url')
|
|
581
|
+
if not url:
|
|
582
|
+
click.echo('❌ No URL provided by agent')
|
|
583
|
+
return
|
|
584
|
+
|
|
585
|
+
click.echo(f' URL: {url}')
|
|
586
|
+
password = info.get('password')
|
|
587
|
+
if password:
|
|
588
|
+
click.echo(f' Password: {password}')
|
|
589
|
+
else:
|
|
590
|
+
click.echo(' Password: Not required (passwordless mode)')
|
|
591
|
+
|
|
592
|
+
# Show workspace information with better context
|
|
593
|
+
click.echo(f'\n📁 Agent Workspace: {actual_workspace}')
|
|
594
|
+
click.echo(f'📂 Local Project: {workspace}')
|
|
595
|
+
|
|
596
|
+
# Only show warning if the paths are drastically different and it's not the expected container path
|
|
597
|
+
if actual_workspace != workspace and not actual_workspace.startswith('/home/coder'):
|
|
598
|
+
click.echo(' ⚠️ Note: Agent workspace differs from local project path')
|
|
599
|
+
|
|
600
|
+
# Optionally open in browser
|
|
601
|
+
if open_browser and url:
|
|
602
|
+
click.echo('\nAttempting to open in browser...')
|
|
603
|
+
|
|
604
|
+
if is_vscode_ssh_session():
|
|
605
|
+
# Extract port from URL for instructions
|
|
606
|
+
import re
|
|
607
|
+
|
|
608
|
+
port_match = re.search(r':(\d+)', url)
|
|
609
|
+
if port_match:
|
|
610
|
+
agent_port = int(port_match.group(1))
|
|
611
|
+
click.echo(get_ssh_tunnel_instructions(agent_port))
|
|
612
|
+
click.echo(f'🔗 Remote URL: {url}')
|
|
613
|
+
elif is_ssh_session():
|
|
614
|
+
click.echo('📝 SSH session detected - please open the URL in your local browser')
|
|
615
|
+
click.echo(f'👉 URL: {url}')
|
|
616
|
+
elif open_browser_smart(url):
|
|
617
|
+
click.echo('✅ Browser opened successfully')
|
|
618
|
+
else:
|
|
619
|
+
click.echo('⚠️ Could not open browser automatically')
|
|
620
|
+
click.echo(f'👉 Please manually open: {url}')
|
|
621
|
+
|
|
622
|
+
# Show additional instructions
|
|
623
|
+
click.echo('\n📝 Quick Start:')
|
|
624
|
+
click.echo('1. Open the URL in your browser')
|
|
625
|
+
click.echo('2. Enter the password if prompted')
|
|
626
|
+
click.echo('3. Start coding in the web-based VS Code!')
|
|
627
|
+
|
|
628
|
+
# Add note about workspace synchronization
|
|
629
|
+
if actual_workspace.startswith('/home/coder'):
|
|
630
|
+
click.echo("\n💡 Note: Your local project files will be available in the agent's workspace.")
|
|
631
|
+
click.echo(' Changes made in code-server will be reflected in your local project.')
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
@click.command()
|
|
635
|
+
@click.option('--agent', help='Agent name or ID')
|
|
636
|
+
@click.option('--open-browser/--no-open-browser', default=True, help='Open in browser')
|
|
637
|
+
@click.option('--workspace', help='Workspace directory path (defaults to current directory)')
|
|
638
|
+
@click.option('--port', type=int, help='Port to bind code-server (default: from config or 8070)')
|
|
639
|
+
def code_server(agent: Optional[str], open_browser: bool, workspace: Optional[str], port: Optional[int]):
|
|
640
|
+
"""Open code-server either through agent or locally."""
|
|
641
|
+
|
|
642
|
+
# Get current working directory if workspace not specified
|
|
643
|
+
if not workspace:
|
|
644
|
+
workspace = os.getcwd()
|
|
645
|
+
|
|
646
|
+
click.echo(f'Using workspace: {workspace}')
|
|
647
|
+
|
|
648
|
+
# Check if local code-server is available
|
|
649
|
+
local_available = is_code_server_installed()
|
|
650
|
+
|
|
651
|
+
# Create menu options based on availability
|
|
652
|
+
choices = []
|
|
653
|
+
|
|
654
|
+
# Always offer agent option
|
|
655
|
+
choices.append(('Open code-server through agent', 'agent'))
|
|
656
|
+
|
|
657
|
+
# Add local option if available
|
|
658
|
+
if local_available:
|
|
659
|
+
choices.append(('Open local code-server', 'local'))
|
|
660
|
+
else:
|
|
661
|
+
choices.append(('Install local code-server (not installed)', 'install'))
|
|
662
|
+
|
|
663
|
+
choices.append(('Cancel', 'cancel'))
|
|
664
|
+
|
|
665
|
+
# Show selection menu
|
|
666
|
+
questions = [inquirer.List('option', message='How would you like to open code-server?', choices=choices)]
|
|
667
|
+
|
|
668
|
+
try:
|
|
669
|
+
answers = inquirer.prompt(questions)
|
|
670
|
+
if not answers or answers['option'] == 'cancel':
|
|
671
|
+
click.echo('Cancelled')
|
|
672
|
+
return
|
|
673
|
+
|
|
674
|
+
if answers['option'] == 'agent':
|
|
675
|
+
click.echo('\n🤖 Opening code-server through agent...')
|
|
676
|
+
run_agent_code_server(agent, workspace, open_browser)
|
|
677
|
+
|
|
678
|
+
elif answers['option'] == 'local':
|
|
679
|
+
click.echo('\n💻 Starting local code-server...')
|
|
680
|
+
launch_local_code_server(workspace, open_browser, port)
|
|
681
|
+
|
|
682
|
+
elif answers['option'] == 'install':
|
|
683
|
+
show_code_server_installation_help()
|
|
684
|
+
|
|
685
|
+
except (KeyboardInterrupt, EOFError):
|
|
686
|
+
click.echo('\n\nCancelled')
|
|
687
|
+
return
|