create-maa-project 1.2.2__tar.gz → 1.2.3__tar.gz
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.
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/.release/create-maa-project-manifest.json +23 -23
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/PKG-INFO +1 -1
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/package.json +1 -1
- create_maa_project-1.2.3/py-wrapper/create_maa_project/__init__.py +1 -0
- create_maa_project-1.2.3/py-wrapper/create_maa_project/release_manifest.py +2 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/pyproject.toml +1 -1
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/github/tools/build-release.mjs +23 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/bootstrap.py +137 -20
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/tests/scaffold.test.ts +6 -0
- create_maa_project-1.2.3/tests/test_agent_bootstrap.py +153 -0
- create_maa_project-1.2.2/py-wrapper/create_maa_project/__init__.py +0 -1
- create_maa_project-1.2.2/py-wrapper/create_maa_project/release_manifest.py +0 -2
- create_maa_project-1.2.2/tests/test_agent_bootstrap.py +0 -39
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/.editorconfig +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/.gitattributes +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/.github/cliff.toml +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/.github/workflows/network-assets.yml +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/.github/workflows/release.yml +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/.github/workflows/schema-sync.yml +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/.gitignore +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/.prettierignore +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/.prettierrc.mjs +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/LICENSE +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/README.en.md +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/README.md +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/pnpm-lock.yaml +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/pnpm-workspace.yaml +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/py-wrapper/create_maa_project/__main__.py +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/scripts/build-sea.mjs +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/scripts/build.mjs +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/scripts/check-network-assets.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/scripts/create-release-manifest.mjs +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/scripts/generate-template-assets.mjs +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/scripts/prepare-pypi-release.mjs +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/scripts/sync-release-version.mjs +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/scripts/sync-schema.mjs +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/scripts/test-python.mjs +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/src/addons.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/src/args.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/src/assets.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/src/controllers.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/src/doctor.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/src/features.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/src/incremental-addons.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/src/index.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/src/lang.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/src/log.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/src/mcp.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/src/project.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/src/prompt.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/src/report.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/src/scaffold.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/src/sync.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/src/template-assets.generated.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/src/templates.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/src/types.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/src/update.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/src/utils.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/auto-format/.github/workflows/format.yml +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/community/CONTRIBUTING.md +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/community/PULL_REQUEST_TEMPLATE.md +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/community/bug_report.yml +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/community/feature_request.yml +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/community/issue_config.yml +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/community/other_issue.yml +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/dependabot/.github/dependabot.yml +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/dev-tools/.vscode/extensions.agent.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/dev-tools/.vscode/extensions.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/dev-tools/.vscode/launch.agent.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/dev-tools/.vscode/settings.agent.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/dev-tools/.vscode/settings.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/dev-tools/.vscode/tasks.github.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/dev-tools/.vscode/tasks.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/dev-tools/package.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/dev-tools/pnpm-workspace.yaml +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/dev-tools/tools/check-project.mjs +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/dev-tools/tools/validate-schema.mjs +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/git-cliff/.github/cliff.toml +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/github/.github/workflows/check.yml +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/github/.github/workflows/release.yml +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/github/tools/sync-runtime.mjs +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/optimize-images/.github/workflows/optimize-images.yml +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/optimize-images/tools/optimize-images.mjs +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/schema-sync/.github/workflows/schema-sync.yml +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/schema-sync/tools/sync-schema.mjs +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/README.en.md +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/README.md +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/__init__.py +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/agent_runtime.py +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/custom/__init__.py +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/custom/action/__init__.py +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/custom/action/general.py +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/custom/reco/__init__.py +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/custom/reco/general.py +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/custom/sink/__init__.py +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/main.py +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/utils/__init__.py +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/utils/logger.py +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/utils/maa_types.py +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/utils/params.py +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/utils/pienv.py +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/utils/runtime_paths.py +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/pyproject.toml +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/requirements.txt +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/tools/schema/custom.action.schema.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/tools/schema/custom.recognition.schema.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/uv.lock +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/.editorconfig +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/.gitattributes +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/.gitignore +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/.prettierignore +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/.prettierrc.mjs +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/README.en.md +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/README.md +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/gitignore.tmpl +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/interface.json.tmpl +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/licenses/AGPL-3.0-or-later.txt +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/licenses/MIT.txt +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/maatools.config.mts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/resource/base/default_pipeline.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/resource/base/image/empty.png +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/resource/base/model/ocr/manifest.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/resource/base/pipeline/tutorial.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/tasks/tutorial.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/tools/schema/custom.action.schema.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/tools/schema/custom.recognition.schema.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/tools/schema/interface.schema.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/tools/schema/interface_config.schema.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/tools/schema/interface_import.schema.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/tools/schema/pipeline.schema.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/tools/schema/schema-manifest.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/tests/addons.test.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/tests/args.test.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/tests/child-env.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/tests/lang.test.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/tests/mcp.test.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/tests/project.test.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/tests/prompt.test.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/tests/report.test.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/tests/templates.test.ts +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/tests/test_py_wrapper.py +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/tsconfig.json +0 -0
- {create_maa_project-1.2.2 → create_maa_project-1.2.3}/vitest.config.ts +0 -0
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/.release/create-maa-project-manifest.json
RENAMED
|
@@ -1,68 +1,68 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"name": "create-maa-project",
|
|
4
|
-
"version": "1.2.
|
|
5
|
-
"tag": "v1.2.
|
|
4
|
+
"version": "1.2.3",
|
|
5
|
+
"tag": "v1.2.3",
|
|
6
6
|
"assets": [
|
|
7
7
|
{
|
|
8
8
|
"kind": "sea",
|
|
9
9
|
"os": "linux",
|
|
10
10
|
"arch": "aarch64",
|
|
11
|
-
"version": "1.2.
|
|
11
|
+
"version": "1.2.3",
|
|
12
12
|
"name": "create-maa-project-linux-aarch64",
|
|
13
|
-
"url": "https://github.com/Windsland52/create-maa-project/releases/download/v1.2.
|
|
14
|
-
"sha256": "
|
|
13
|
+
"url": "https://github.com/Windsland52/create-maa-project/releases/download/v1.2.3/create-maa-project-linux-aarch64",
|
|
14
|
+
"sha256": "8a6eda1cabb647e0df9ba8f2e12e273317089a97b43c465a54e3b5dc1ef0bc73",
|
|
15
15
|
"size": 123145344
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
18
|
"kind": "sea",
|
|
19
19
|
"os": "linux",
|
|
20
20
|
"arch": "x86_64",
|
|
21
|
-
"version": "1.2.
|
|
21
|
+
"version": "1.2.3",
|
|
22
22
|
"name": "create-maa-project-linux-x86_64",
|
|
23
|
-
"url": "https://github.com/Windsland52/create-maa-project/releases/download/v1.2.
|
|
24
|
-
"sha256": "
|
|
23
|
+
"url": "https://github.com/Windsland52/create-maa-project/releases/download/v1.2.3/create-maa-project-linux-x86_64",
|
|
24
|
+
"sha256": "f4cb775d3d85aba1475ef041d654de13a06cdf17801bc479648bd75e351932b5",
|
|
25
25
|
"size": 125045952
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
28
|
"kind": "sea",
|
|
29
29
|
"os": "macos",
|
|
30
30
|
"arch": "aarch64",
|
|
31
|
-
"version": "1.2.
|
|
31
|
+
"version": "1.2.3",
|
|
32
32
|
"name": "create-maa-project-macos-aarch64",
|
|
33
|
-
"url": "https://github.com/Windsland52/create-maa-project/releases/download/v1.2.
|
|
34
|
-
"sha256": "
|
|
33
|
+
"url": "https://github.com/Windsland52/create-maa-project/releases/download/v1.2.3/create-maa-project-macos-aarch64",
|
|
34
|
+
"sha256": "d0fe39da998fdde748ea5477618a705dad9adfb45ea8d34e17c8aa63430b943b",
|
|
35
35
|
"size": 121408240
|
|
36
36
|
},
|
|
37
37
|
{
|
|
38
38
|
"kind": "sea",
|
|
39
39
|
"os": "macos",
|
|
40
40
|
"arch": "x86_64",
|
|
41
|
-
"version": "1.2.
|
|
41
|
+
"version": "1.2.3",
|
|
42
42
|
"name": "create-maa-project-macos-x86_64",
|
|
43
|
-
"url": "https://github.com/Windsland52/create-maa-project/releases/download/v1.2.
|
|
44
|
-
"sha256": "
|
|
45
|
-
"size":
|
|
43
|
+
"url": "https://github.com/Windsland52/create-maa-project/releases/download/v1.2.3/create-maa-project-macos-x86_64",
|
|
44
|
+
"sha256": "68364953c76c81d8426ebaf2fc571296ecedc81f3f2f3c2e2f75146d98e7e16c",
|
|
45
|
+
"size": 124476368
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"kind": "sea",
|
|
49
49
|
"os": "win",
|
|
50
50
|
"arch": "aarch64",
|
|
51
|
-
"version": "1.2.
|
|
51
|
+
"version": "1.2.3",
|
|
52
52
|
"name": "create-maa-project-win-aarch64.exe",
|
|
53
|
-
"url": "https://github.com/Windsland52/create-maa-project/releases/download/v1.2.
|
|
54
|
-
"sha256": "
|
|
55
|
-
"size":
|
|
53
|
+
"url": "https://github.com/Windsland52/create-maa-project/releases/download/v1.2.3/create-maa-project-win-aarch64.exe",
|
|
54
|
+
"sha256": "68c26c233b409357e8873b014918c71bc3012addf9678315e4273180d2760ff3",
|
|
55
|
+
"size": 82565120
|
|
56
56
|
},
|
|
57
57
|
{
|
|
58
58
|
"kind": "sea",
|
|
59
59
|
"os": "win",
|
|
60
60
|
"arch": "x86_64",
|
|
61
|
-
"version": "1.2.
|
|
61
|
+
"version": "1.2.3",
|
|
62
62
|
"name": "create-maa-project-win-x86_64.exe",
|
|
63
|
-
"url": "https://github.com/Windsland52/create-maa-project/releases/download/v1.2.
|
|
64
|
-
"sha256": "
|
|
65
|
-
"size":
|
|
63
|
+
"url": "https://github.com/Windsland52/create-maa-project/releases/download/v1.2.3/create-maa-project-win-x86_64.exe",
|
|
64
|
+
"sha256": "e730e080a811fc901ea7c1932792452118d6468676bdb6560af491e0b8e796ff",
|
|
65
|
+
"size": 94031360
|
|
66
66
|
}
|
|
67
67
|
]
|
|
68
68
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: create-maa-project
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.3
|
|
4
4
|
Summary: 用于创建和维护 MaaFW 应用项目的脚手架 CLI / Scaffold and maintenance CLI for MaaFW application projects
|
|
5
5
|
Project-URL: Homepage, https://github.com/Windsland52/create-maa-project
|
|
6
6
|
Project-URL: Source, https://github.com/Windsland52/create-maa-project
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.2.3"
|
|
@@ -10,11 +10,13 @@ import {
|
|
|
10
10
|
statSync,
|
|
11
11
|
writeFileSync,
|
|
12
12
|
} from "node:fs";
|
|
13
|
+
import {createHash} from "node:crypto";
|
|
13
14
|
import {basename, dirname, join} from "node:path";
|
|
14
15
|
|
|
15
16
|
const dryRun = process.argv.includes("--dry-run");
|
|
16
17
|
const projectSlug = {{projectSlug}};
|
|
17
18
|
const releaseArtifactName = {{releaseArtifactName}};
|
|
19
|
+
const requirementsMarker = ".create-maa-project-requirements.sha256";
|
|
18
20
|
mkdirSync("dist", {recursive: true});
|
|
19
21
|
|
|
20
22
|
const lock = readJson("maa-project.lock.json");
|
|
@@ -278,6 +280,7 @@ function prepareReleasePackage(guiKey, gui, packagePaths, interfaceJson, runtime
|
|
|
278
280
|
}
|
|
279
281
|
if (packageHasAgent(interfaceJson) && hasEmbeddedPythonRuntime(runtimePlatform)) {
|
|
280
282
|
copyPath(pythonRuntimePath(runtimePlatform), join(pkgDir, "python"));
|
|
283
|
+
writeEmbeddedRequirementsMarker(pkgDir);
|
|
281
284
|
}
|
|
282
285
|
if (!gui.flatLayout) {
|
|
283
286
|
prepareMxuMaafwRuntime(pkgDir, runtimePlatform);
|
|
@@ -364,6 +367,17 @@ function smokeReleasePackage(gui, root, packagePaths, runtimePlatform) {
|
|
|
364
367
|
if (!existsSync(join(root, "agent", "bootstrap.py"))) {
|
|
365
368
|
throw new Error("release package smoke failed: Agent bootstrap is missing");
|
|
366
369
|
}
|
|
370
|
+
if (hasEmbeddedPythonRuntime(runtimePlatform)) {
|
|
371
|
+
const markerPath = join(root, "python", requirementsMarker);
|
|
372
|
+
if (!existsSync(markerPath)) {
|
|
373
|
+
throw new Error("release package smoke failed: Python requirements marker is missing");
|
|
374
|
+
}
|
|
375
|
+
const expectedDigest = requirementsDigest(join(root, "requirements.txt"));
|
|
376
|
+
const actualDigest = readFileSync(markerPath, "utf8").trim();
|
|
377
|
+
if (actualDigest !== expectedDigest) {
|
|
378
|
+
throw new Error("release package smoke failed: Python requirements marker does not match requirements.txt");
|
|
379
|
+
}
|
|
380
|
+
}
|
|
367
381
|
}
|
|
368
382
|
assertUnixExecutablePermissions(root, runtimePlatform);
|
|
369
383
|
for (const path of [
|
|
@@ -409,6 +423,15 @@ function copyDirectoryContents(source, target) {
|
|
|
409
423
|
}
|
|
410
424
|
}
|
|
411
425
|
|
|
426
|
+
function requirementsDigest(requirementsPath) {
|
|
427
|
+
return createHash("sha256").update(readFileSync(requirementsPath)).digest("hex");
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
function writeEmbeddedRequirementsMarker(pkgDir) {
|
|
431
|
+
const digest = requirementsDigest(join(pkgDir, "requirements.txt"));
|
|
432
|
+
writeFileSync(join(pkgDir, "python", requirementsMarker), digest + "\n", "utf8");
|
|
433
|
+
}
|
|
434
|
+
|
|
412
435
|
function shouldCopyAgentPath(source) {
|
|
413
436
|
const name = basename(source).toLowerCase();
|
|
414
437
|
return name !== "__pycache__" && !name.endsWith(".pyc") && !name.endsWith(".pyo");
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import errno
|
|
3
4
|
import hashlib
|
|
4
5
|
import importlib.metadata
|
|
5
6
|
import json
|
|
@@ -8,14 +9,19 @@ import runpy
|
|
|
8
9
|
import shutil
|
|
9
10
|
import subprocess
|
|
10
11
|
import sys
|
|
12
|
+
import time
|
|
13
|
+
from collections.abc import Generator
|
|
14
|
+
from contextlib import contextmanager
|
|
11
15
|
from datetime import UTC, datetime
|
|
12
16
|
from pathlib import Path
|
|
13
|
-
from typing import Any
|
|
17
|
+
from typing import Any, BinaryIO
|
|
14
18
|
|
|
15
19
|
PYTHON_MIN = (3, 13)
|
|
16
20
|
PYTHON_MAX = (3, 14)
|
|
17
21
|
VENV_NAME = ".venv"
|
|
18
22
|
REQUIREMENTS_MARKER = ".create-maa-project-requirements.sha256"
|
|
23
|
+
REQUIREMENTS_LOCK = ".create-maa-project-requirements.lock"
|
|
24
|
+
REQUIREMENTS_LOCK_TIMEOUT_SECONDS = 300.0
|
|
19
25
|
DEFAULT_PIP_CONFIG = {
|
|
20
26
|
"enable_pip_install": True,
|
|
21
27
|
"mirror": "https://pypi.tuna.tsinghua.edu.cn/simple",
|
|
@@ -172,23 +178,26 @@ def find_requirements_file(project_root: Path) -> Path:
|
|
|
172
178
|
|
|
173
179
|
|
|
174
180
|
def ensure_requirements_installed(project_root: Path, requirements: Path, digest: str) -> None:
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
181
|
+
with requirements_install_lock(project_root):
|
|
182
|
+
# Another Agent may have completed the installation while this process
|
|
183
|
+
# waited for the shared environment lock.
|
|
184
|
+
if not needs_requirement_install(project_root, digest):
|
|
185
|
+
return
|
|
186
|
+
|
|
187
|
+
pip_config = read_pip_config(project_root)
|
|
188
|
+
if not pip_config.get("enable_pip_install", True):
|
|
189
|
+
warn(project_root, "pip install is disabled by config/pip_config.json")
|
|
190
|
+
return
|
|
191
|
+
|
|
192
|
+
if install_from_local_wheels(project_root, requirements) or install_from_indexes(
|
|
193
|
+
project_root,
|
|
194
|
+
requirements,
|
|
195
|
+
pip_config,
|
|
196
|
+
):
|
|
197
|
+
write_requirements_marker(project_root, digest)
|
|
198
|
+
return
|
|
190
199
|
|
|
191
|
-
|
|
200
|
+
warn(project_root, "Python dependencies were not installed successfully")
|
|
192
201
|
|
|
193
202
|
|
|
194
203
|
def needs_requirement_install(project_root: Path, digest: str) -> bool:
|
|
@@ -203,16 +212,121 @@ def needs_requirement_install(project_root: Path, digest: str) -> bool:
|
|
|
203
212
|
def requirements_marker(project_root: Path) -> Path:
|
|
204
213
|
if is_running_in_project_venv(project_root):
|
|
205
214
|
return venv_dir(project_root) / REQUIREMENTS_MARKER
|
|
215
|
+
if is_running_in_embedded_python(project_root):
|
|
216
|
+
return project_root / "python" / REQUIREMENTS_MARKER
|
|
206
217
|
return project_root / "debug" / REQUIREMENTS_MARKER
|
|
207
218
|
|
|
208
219
|
|
|
220
|
+
def is_running_in_embedded_python(project_root: Path) -> bool:
|
|
221
|
+
try:
|
|
222
|
+
return Path(sys.executable).resolve().is_relative_to((project_root / "python").resolve())
|
|
223
|
+
except OSError:
|
|
224
|
+
return False
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def requirements_lock_path(project_root: Path) -> Path:
|
|
228
|
+
return requirements_marker(project_root).with_name(REQUIREMENTS_LOCK)
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
@contextmanager
|
|
232
|
+
def requirements_install_lock(
|
|
233
|
+
project_root: Path,
|
|
234
|
+
timeout_seconds: float = REQUIREMENTS_LOCK_TIMEOUT_SECONDS,
|
|
235
|
+
) -> Generator[None]:
|
|
236
|
+
lock_path = requirements_lock_path(project_root)
|
|
237
|
+
try:
|
|
238
|
+
lock_path.parent.mkdir(parents=True, exist_ok=True)
|
|
239
|
+
handle = lock_path.open("a+b")
|
|
240
|
+
except OSError as error:
|
|
241
|
+
warn(project_root, "failed to open Python requirements install lock: " + str(error))
|
|
242
|
+
raise SystemExit(1) from error
|
|
243
|
+
|
|
244
|
+
with handle:
|
|
245
|
+
try:
|
|
246
|
+
ensure_lock_file_byte(handle)
|
|
247
|
+
except OSError as error:
|
|
248
|
+
warn(project_root, "failed to initialize Python requirements install lock: " + str(error))
|
|
249
|
+
raise SystemExit(1) from error
|
|
250
|
+
|
|
251
|
+
deadline = time.monotonic() + timeout_seconds
|
|
252
|
+
waiting_logged = False
|
|
253
|
+
while True:
|
|
254
|
+
try:
|
|
255
|
+
acquired = try_lock_file(handle)
|
|
256
|
+
except OSError as error:
|
|
257
|
+
warn(project_root, "failed to acquire Python requirements install lock: " + str(error))
|
|
258
|
+
raise SystemExit(1) from error
|
|
259
|
+
if acquired:
|
|
260
|
+
break
|
|
261
|
+
if not waiting_logged:
|
|
262
|
+
log(project_root, "waiting for Python requirements install lock: " + str(lock_path))
|
|
263
|
+
waiting_logged = True
|
|
264
|
+
if time.monotonic() >= deadline:
|
|
265
|
+
warn(project_root, "timed out waiting for Python requirements install lock: " + str(lock_path))
|
|
266
|
+
raise SystemExit(1)
|
|
267
|
+
time.sleep(0.1)
|
|
268
|
+
|
|
269
|
+
log(project_root, "acquired Python requirements install lock: " + str(lock_path))
|
|
270
|
+
try:
|
|
271
|
+
yield
|
|
272
|
+
finally:
|
|
273
|
+
try:
|
|
274
|
+
unlock_file(handle)
|
|
275
|
+
except OSError as error:
|
|
276
|
+
warn(project_root, "failed to release Python requirements install lock: " + str(error))
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def ensure_lock_file_byte(handle: BinaryIO) -> None:
|
|
280
|
+
handle.seek(0, 2)
|
|
281
|
+
if handle.tell() == 0:
|
|
282
|
+
handle.write(b"\0")
|
|
283
|
+
handle.flush()
|
|
284
|
+
handle.seek(0)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def try_lock_file(handle: BinaryIO) -> bool:
|
|
288
|
+
handle.seek(0)
|
|
289
|
+
try:
|
|
290
|
+
if sys.platform.startswith("win"):
|
|
291
|
+
import msvcrt
|
|
292
|
+
|
|
293
|
+
msvcrt.locking(handle.fileno(), msvcrt.LK_NBLCK, 1)
|
|
294
|
+
else:
|
|
295
|
+
import fcntl
|
|
296
|
+
|
|
297
|
+
fcntl.flock(handle.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
|
|
298
|
+
except OSError as error:
|
|
299
|
+
if error.errno in (errno.EACCES, errno.EAGAIN):
|
|
300
|
+
return False
|
|
301
|
+
raise
|
|
302
|
+
return True
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def unlock_file(handle: BinaryIO) -> None:
|
|
306
|
+
handle.seek(0)
|
|
307
|
+
if sys.platform.startswith("win"):
|
|
308
|
+
import msvcrt
|
|
309
|
+
|
|
310
|
+
msvcrt.locking(handle.fileno(), msvcrt.LK_UNLCK, 1)
|
|
311
|
+
else:
|
|
312
|
+
import fcntl
|
|
313
|
+
|
|
314
|
+
fcntl.flock(handle.fileno(), fcntl.LOCK_UN)
|
|
315
|
+
|
|
316
|
+
|
|
209
317
|
def write_requirements_marker(project_root: Path, digest: str) -> None:
|
|
210
318
|
marker = requirements_marker(project_root)
|
|
319
|
+
temp_marker = marker.with_name(marker.name + ".tmp")
|
|
211
320
|
try:
|
|
212
321
|
marker.parent.mkdir(parents=True, exist_ok=True)
|
|
213
|
-
|
|
322
|
+
temp_marker.write_text(digest + "\n", encoding="utf8")
|
|
323
|
+
temp_marker.replace(marker)
|
|
214
324
|
except OSError as error:
|
|
215
325
|
warn(project_root, "failed to write requirements marker: " + str(error))
|
|
326
|
+
try:
|
|
327
|
+
temp_marker.unlink(missing_ok=True)
|
|
328
|
+
except OSError:
|
|
329
|
+
pass
|
|
216
330
|
|
|
217
331
|
|
|
218
332
|
def install_from_local_wheels(project_root: Path, requirements: Path) -> bool:
|
|
@@ -320,15 +434,18 @@ def check_maafw(project_root: Path) -> None:
|
|
|
320
434
|
except importlib.metadata.PackageNotFoundError:
|
|
321
435
|
warn(project_root, "Python package maafw is not installed")
|
|
322
436
|
return
|
|
437
|
+
if not version:
|
|
438
|
+
warn(project_root, "Python package maafw has invalid or incomplete metadata")
|
|
439
|
+
return
|
|
323
440
|
log(project_root, "maafw " + version)
|
|
324
441
|
|
|
325
442
|
|
|
326
443
|
def is_package_installed(name: str) -> bool:
|
|
327
444
|
try:
|
|
328
|
-
importlib.metadata.version(name)
|
|
445
|
+
version = importlib.metadata.version(name)
|
|
329
446
|
except importlib.metadata.PackageNotFoundError:
|
|
330
447
|
return False
|
|
331
|
-
return
|
|
448
|
+
return bool(version)
|
|
332
449
|
|
|
333
450
|
|
|
334
451
|
def command_output(error: subprocess.CalledProcessError) -> str:
|
|
@@ -2465,6 +2465,12 @@ jobs:
|
|
|
2465
2465
|
expect(await pathExists(join(projectRoot, 'dist/package-mfaa/deps/maafw-0.0.0-py3-none-any.whl'))).toBe(true)
|
|
2466
2466
|
} else {
|
|
2467
2467
|
expect(await pathExists(join(projectRoot, 'dist/package-mfaa', expectedChildExec))).toBe(true)
|
|
2468
|
+
const packagedRequirements = await readFile(join(projectRoot, 'dist/package-mfaa/requirements.txt'))
|
|
2469
|
+
const packagedMarker = await readFile(
|
|
2470
|
+
join(projectRoot, 'dist/package-mfaa/python/.create-maa-project-requirements.sha256'),
|
|
2471
|
+
'utf8',
|
|
2472
|
+
)
|
|
2473
|
+
expect(packagedMarker).toBe(`${sha256(packagedRequirements)}\n`)
|
|
2468
2474
|
}
|
|
2469
2475
|
if (!runtimePlatform.startsWith('win-') && process.platform !== 'win32') {
|
|
2470
2476
|
expect(
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import importlib.util
|
|
4
|
+
import multiprocessing
|
|
5
|
+
import tempfile
|
|
6
|
+
import time
|
|
7
|
+
import unittest
|
|
8
|
+
from contextlib import nullcontext
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from unittest.mock import patch
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
BOOTSTRAP_PATH = Path(__file__).resolve().parents[1] / "templates" / "agent" / "agent" / "bootstrap.py"
|
|
14
|
+
SPEC = importlib.util.spec_from_file_location("agent_bootstrap_template", BOOTSTRAP_PATH)
|
|
15
|
+
if SPEC is None or SPEC.loader is None:
|
|
16
|
+
raise RuntimeError("unable to load Agent bootstrap template")
|
|
17
|
+
agent_bootstrap = importlib.util.module_from_spec(SPEC)
|
|
18
|
+
SPEC.loader.exec_module(agent_bootstrap)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def acquire_requirements_lock_and_touch(project_root: str, touched_path: str) -> None:
|
|
22
|
+
with agent_bootstrap.requirements_install_lock(Path(project_root), timeout_seconds=5.0):
|
|
23
|
+
Path(touched_path).write_text("acquired\n", encoding="utf8")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class AgentBootstrapRequirementsTest(unittest.TestCase):
|
|
27
|
+
def test_external_maafw_without_marker_does_not_skip_requirements(self) -> None:
|
|
28
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
29
|
+
project_root = Path(temp_dir)
|
|
30
|
+
with patch.object(agent_bootstrap, "is_package_installed", return_value=True):
|
|
31
|
+
with patch.object(agent_bootstrap, "is_running_in_project_venv", return_value=False):
|
|
32
|
+
self.assertTrue(agent_bootstrap.needs_requirement_install(project_root, "digest"))
|
|
33
|
+
|
|
34
|
+
def test_matching_marker_skips_reinstall_when_maafw_is_available(self) -> None:
|
|
35
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
36
|
+
project_root = Path(temp_dir)
|
|
37
|
+
marker = project_root / "debug" / agent_bootstrap.REQUIREMENTS_MARKER
|
|
38
|
+
marker.parent.mkdir()
|
|
39
|
+
marker.write_text("digest\n", encoding="utf8")
|
|
40
|
+
|
|
41
|
+
with patch.object(agent_bootstrap, "is_package_installed", return_value=True):
|
|
42
|
+
with patch.object(agent_bootstrap, "is_running_in_project_venv", return_value=False):
|
|
43
|
+
self.assertFalse(agent_bootstrap.needs_requirement_install(project_root, "digest"))
|
|
44
|
+
|
|
45
|
+
def test_system_python_bin_is_not_treated_as_embedded(self) -> None:
|
|
46
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
47
|
+
project_root = Path(temp_dir)
|
|
48
|
+
with patch.object(agent_bootstrap.sys, "executable", "/usr/bin/python3"):
|
|
49
|
+
self.assertFalse(agent_bootstrap.is_running_in_embedded_python(project_root))
|
|
50
|
+
|
|
51
|
+
def test_macos_packaged_python_path_is_treated_as_embedded(self) -> None:
|
|
52
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
53
|
+
project_root = Path(temp_dir)
|
|
54
|
+
embedded_python = project_root / "python" / "bin" / "python3"
|
|
55
|
+
with patch.object(agent_bootstrap.sys, "executable", str(embedded_python)):
|
|
56
|
+
self.assertTrue(agent_bootstrap.is_running_in_embedded_python(project_root))
|
|
57
|
+
|
|
58
|
+
def test_project_venv_marker_takes_priority_over_embedded_runtime(self) -> None:
|
|
59
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
60
|
+
project_root = Path(temp_dir)
|
|
61
|
+
with patch.object(agent_bootstrap, "is_running_in_project_venv", return_value=True):
|
|
62
|
+
with patch.object(agent_bootstrap, "is_running_in_embedded_python", return_value=True):
|
|
63
|
+
marker = agent_bootstrap.requirements_marker(project_root)
|
|
64
|
+
|
|
65
|
+
self.assertEqual(marker, project_root / ".venv" / agent_bootstrap.REQUIREMENTS_MARKER)
|
|
66
|
+
|
|
67
|
+
def test_waiting_installer_rechecks_marker_after_acquiring_lock(self) -> None:
|
|
68
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
69
|
+
project_root = Path(temp_dir)
|
|
70
|
+
requirements = project_root / "requirements.txt"
|
|
71
|
+
requirements.write_text("maafw==1.0.0\n", encoding="utf8")
|
|
72
|
+
|
|
73
|
+
with patch.object(agent_bootstrap, "requirements_install_lock", return_value=nullcontext()):
|
|
74
|
+
with patch.object(agent_bootstrap, "needs_requirement_install", return_value=False):
|
|
75
|
+
with patch.object(agent_bootstrap, "install_from_local_wheels") as install_local:
|
|
76
|
+
with patch.object(agent_bootstrap, "install_from_indexes") as install_indexes:
|
|
77
|
+
agent_bootstrap.ensure_requirements_installed(project_root, requirements, "digest")
|
|
78
|
+
|
|
79
|
+
install_local.assert_not_called()
|
|
80
|
+
install_indexes.assert_not_called()
|
|
81
|
+
|
|
82
|
+
def test_requirements_lock_retries_and_releases(self) -> None:
|
|
83
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
84
|
+
project_root = Path(temp_dir)
|
|
85
|
+
|
|
86
|
+
with patch.object(agent_bootstrap, "try_lock_file", side_effect=[False, True]):
|
|
87
|
+
with patch.object(agent_bootstrap, "unlock_file") as unlock:
|
|
88
|
+
with patch.object(agent_bootstrap.time, "monotonic", side_effect=[0.0, 0.0]):
|
|
89
|
+
with patch.object(agent_bootstrap.time, "sleep") as sleep:
|
|
90
|
+
with agent_bootstrap.requirements_install_lock(project_root, timeout_seconds=1.0):
|
|
91
|
+
pass
|
|
92
|
+
|
|
93
|
+
sleep.assert_called_once_with(0.1)
|
|
94
|
+
unlock.assert_called_once()
|
|
95
|
+
|
|
96
|
+
def test_requirements_lock_timeout_stops_bootstrap(self) -> None:
|
|
97
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
98
|
+
project_root = Path(temp_dir)
|
|
99
|
+
|
|
100
|
+
with patch.object(agent_bootstrap, "try_lock_file", return_value=False):
|
|
101
|
+
with patch.object(agent_bootstrap.time, "monotonic", side_effect=[0.0, 2.0]):
|
|
102
|
+
with patch.object(agent_bootstrap, "warn") as warn:
|
|
103
|
+
with self.assertRaises(SystemExit):
|
|
104
|
+
with agent_bootstrap.requirements_install_lock(project_root, timeout_seconds=1.0):
|
|
105
|
+
pass
|
|
106
|
+
|
|
107
|
+
warn.assert_called_once()
|
|
108
|
+
|
|
109
|
+
def test_requirements_lock_serializes_processes(self) -> None:
|
|
110
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
111
|
+
project_root = Path(temp_dir)
|
|
112
|
+
touched_path = project_root / "second-process-acquired"
|
|
113
|
+
process = multiprocessing.get_context("spawn").Process(
|
|
114
|
+
target=acquire_requirements_lock_and_touch,
|
|
115
|
+
args=(str(project_root), str(touched_path)),
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
with agent_bootstrap.requirements_install_lock(project_root, timeout_seconds=5.0):
|
|
119
|
+
process.start()
|
|
120
|
+
time.sleep(0.3)
|
|
121
|
+
self.assertFalse(touched_path.exists())
|
|
122
|
+
|
|
123
|
+
process.join(timeout=5.0)
|
|
124
|
+
self.assertEqual(process.exitcode, 0)
|
|
125
|
+
self.assertTrue(touched_path.exists())
|
|
126
|
+
|
|
127
|
+
def test_requirements_marker_is_written_atomically(self) -> None:
|
|
128
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
129
|
+
project_root = Path(temp_dir)
|
|
130
|
+
with patch.object(agent_bootstrap, "is_running_in_project_venv", return_value=False):
|
|
131
|
+
with patch.object(agent_bootstrap, "is_running_in_embedded_python", return_value=False):
|
|
132
|
+
agent_bootstrap.write_requirements_marker(project_root, "digest")
|
|
133
|
+
|
|
134
|
+
marker = project_root / "debug" / agent_bootstrap.REQUIREMENTS_MARKER
|
|
135
|
+
self.assertEqual(marker.read_text(encoding="utf8"), "digest\n")
|
|
136
|
+
self.assertFalse(marker.with_name(marker.name + ".tmp").exists())
|
|
137
|
+
|
|
138
|
+
def test_empty_package_version_is_not_installed(self) -> None:
|
|
139
|
+
with patch.object(agent_bootstrap.importlib.metadata, "version", return_value=None):
|
|
140
|
+
self.assertFalse(agent_bootstrap.is_package_installed("maafw"))
|
|
141
|
+
|
|
142
|
+
def test_empty_maafw_version_reports_invalid_metadata(self) -> None:
|
|
143
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
144
|
+
project_root = Path(temp_dir)
|
|
145
|
+
with patch.object(agent_bootstrap.importlib.metadata, "version", return_value=None):
|
|
146
|
+
with patch.object(agent_bootstrap, "warn") as warn:
|
|
147
|
+
agent_bootstrap.check_maafw(project_root)
|
|
148
|
+
|
|
149
|
+
warn.assert_called_once_with(project_root, "Python package maafw has invalid or incomplete metadata")
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
if __name__ == "__main__":
|
|
153
|
+
unittest.main()
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "1.2.2"
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import importlib.util
|
|
4
|
-
import tempfile
|
|
5
|
-
import unittest
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
from unittest.mock import patch
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
BOOTSTRAP_PATH = Path(__file__).resolve().parents[1] / "templates" / "agent" / "agent" / "bootstrap.py"
|
|
11
|
-
SPEC = importlib.util.spec_from_file_location("agent_bootstrap_template", BOOTSTRAP_PATH)
|
|
12
|
-
if SPEC is None or SPEC.loader is None:
|
|
13
|
-
raise RuntimeError("unable to load Agent bootstrap template")
|
|
14
|
-
agent_bootstrap = importlib.util.module_from_spec(SPEC)
|
|
15
|
-
SPEC.loader.exec_module(agent_bootstrap)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class AgentBootstrapRequirementsTest(unittest.TestCase):
|
|
19
|
-
def test_external_maafw_without_marker_does_not_skip_requirements(self) -> None:
|
|
20
|
-
with tempfile.TemporaryDirectory() as temp_dir:
|
|
21
|
-
project_root = Path(temp_dir)
|
|
22
|
-
with patch.object(agent_bootstrap, "is_package_installed", return_value=True):
|
|
23
|
-
with patch.object(agent_bootstrap, "is_running_in_project_venv", return_value=False):
|
|
24
|
-
self.assertTrue(agent_bootstrap.needs_requirement_install(project_root, "digest"))
|
|
25
|
-
|
|
26
|
-
def test_matching_marker_skips_reinstall_when_maafw_is_available(self) -> None:
|
|
27
|
-
with tempfile.TemporaryDirectory() as temp_dir:
|
|
28
|
-
project_root = Path(temp_dir)
|
|
29
|
-
marker = project_root / "debug" / agent_bootstrap.REQUIREMENTS_MARKER
|
|
30
|
-
marker.parent.mkdir()
|
|
31
|
-
marker.write_text("digest\n", encoding="utf8")
|
|
32
|
-
|
|
33
|
-
with patch.object(agent_bootstrap, "is_package_installed", return_value=True):
|
|
34
|
-
with patch.object(agent_bootstrap, "is_running_in_project_venv", return_value=False):
|
|
35
|
-
self.assertFalse(agent_bootstrap.needs_requirement_install(project_root, "digest"))
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if __name__ == "__main__":
|
|
39
|
-
unittest.main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/py-wrapper/create_maa_project/__main__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/community/CONTRIBUTING.md
RENAMED
|
File without changes
|
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/community/bug_report.yml
RENAMED
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/community/feature_request.yml
RENAMED
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/community/issue_config.yml
RENAMED
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/community/other_issue.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/dev-tools/.vscode/tasks.json
RENAMED
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/dev-tools/package.json
RENAMED
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/dev-tools/pnpm-workspace.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/git-cliff/.github/cliff.toml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/addons/github/tools/sync-runtime.mjs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/agent_runtime.py
RENAMED
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/custom/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/custom/action/general.py
RENAMED
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/custom/reco/__init__.py
RENAMED
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/custom/reco/general.py
RENAMED
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/custom/sink/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/utils/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/utils/maa_types.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/agent/agent/utils/runtime_paths.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/licenses/AGPL-3.0-or-later.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{create_maa_project-1.2.2 → create_maa_project-1.2.3}/templates/base/resource/base/image/empty.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|