mirrorneuron-cli 1.2.6__tar.gz → 1.2.7__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.
- {mirrorneuron_cli-1.2.6/mirrorneuron_cli.egg-info → mirrorneuron_cli-1.2.7}/PKG-INFO +1 -1
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7/mirrorneuron_cli.egg-info}/PKG-INFO +1 -1
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mirrorneuron_cli.egg-info/SOURCES.txt +2 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/blueprint_cmds.py +3 -16
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/blueprint_observability.py +14 -44
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/event_relay.py +2 -18
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/run_cmds.py +117 -21
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/run_manifest.py +283 -39
- mirrorneuron_cli-1.2.7/mn_cli/libs/skill_dependencies.py +102 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/skill_runtime.py +162 -15
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/sys_cmds.py +42 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/main.py +2 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/schemas/workflow_manifest.schema.json +24 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/server_cmds.py +210 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_blueprint_cmds.py +2 -14
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_main.py +1 -0
- mirrorneuron_cli-1.2.7/tests/test_repo_hygiene.py +25 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_run_cmds.py +139 -15
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_run_helpers.py +283 -16
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_server_cmds.py +51 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/.github/workflows/ci.yml +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/.github/workflows/release.yml +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/.gitignore +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/.python-version +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/AGENTS.md +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/LICENSE +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/README.md +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/RELEASE.md +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mirrorneuron_cli.egg-info/dependency_links.txt +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mirrorneuron_cli.egg-info/entry_points.txt +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mirrorneuron_cli.egg-info/requires.txt +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mirrorneuron_cli.egg-info/top_level.txt +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/__init__.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/banner.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/config.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/error_handler.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/__init__.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/artifacts.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/backup_cmds.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/blueprint_models.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/blueprint_repository.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/blueprint_resources.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/bundles.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/deployment_cmds.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/job_cmds.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/model_cmds.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/resource_cmds.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/run_logs.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/runtime_health.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/schedule_cmds.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/service_cmds.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/ui.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/workflow_progress.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/libs/workflow_validation.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/logging_config.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/runtime_mode.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/runtime_state.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/sdk_path.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/shared.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/terminal.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/mn_cli/update_cmds.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/pyproject.toml +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/scripts/check-release-artifacts.sh +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/scripts/make-release-zip.sh +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/scripts/validate-version-tag.sh +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/setup.cfg +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/conftest.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_backup_cmds.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_blueprint_repository.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_blueprint_resources.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_deployment_cmds.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_docker_network_integration.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_job_cmds.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_model_cmds.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_resource_cmds.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_runtime_health.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_runtime_mode.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_runtime_state.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_schedule_cmds.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_service_cmds.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_shared.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_sys_cmds.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_terminal.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_ui.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_update_cmds.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/tests/test_workflow_validation.py +0 -0
- {mirrorneuron_cli-1.2.6 → mirrorneuron_cli-1.2.7}/uv.lock +0 -0
|
@@ -47,6 +47,7 @@ mn_cli/libs/run_manifest.py
|
|
|
47
47
|
mn_cli/libs/runtime_health.py
|
|
48
48
|
mn_cli/libs/schedule_cmds.py
|
|
49
49
|
mn_cli/libs/service_cmds.py
|
|
50
|
+
mn_cli/libs/skill_dependencies.py
|
|
50
51
|
mn_cli/libs/skill_runtime.py
|
|
51
52
|
mn_cli/libs/sys_cmds.py
|
|
52
53
|
mn_cli/libs/ui.py
|
|
@@ -66,6 +67,7 @@ tests/test_docker_network_integration.py
|
|
|
66
67
|
tests/test_job_cmds.py
|
|
67
68
|
tests/test_main.py
|
|
68
69
|
tests/test_model_cmds.py
|
|
70
|
+
tests/test_repo_hygiene.py
|
|
69
71
|
tests/test_resource_cmds.py
|
|
70
72
|
tests/test_run_cmds.py
|
|
71
73
|
tests/test_run_helpers.py
|
|
@@ -3,7 +3,6 @@ import copy
|
|
|
3
3
|
import json
|
|
4
4
|
import shutil
|
|
5
5
|
import subprocess
|
|
6
|
-
import sys
|
|
7
6
|
import time
|
|
8
7
|
from pathlib import Path
|
|
9
8
|
from typing import Annotated, Any, Optional
|
|
@@ -59,6 +58,9 @@ from mn_cli.libs.model_cmds import (
|
|
|
59
58
|
remove_model_ref as _remove_model_ref,
|
|
60
59
|
)
|
|
61
60
|
from mn_sdk.runtime_config import resolve_mn_home
|
|
61
|
+
from mn_sdk.blueprint_support.python_workflow_bundle import (
|
|
62
|
+
generate_python_workflow_bundle_from_blueprint_dir,
|
|
63
|
+
)
|
|
62
64
|
from mn_sdk import (
|
|
63
65
|
cluster_provided_model as _cluster_provided_model,
|
|
64
66
|
docker_model_name as _docker_model_name,
|
|
@@ -81,16 +83,6 @@ human_app = typer.Typer(
|
|
|
81
83
|
_PATCH_COMPAT = (subprocess, _git_checkout, _git_fetch)
|
|
82
84
|
|
|
83
85
|
|
|
84
|
-
def _inject_local_blueprint_support_path() -> None:
|
|
85
|
-
repo_root = Path(
|
|
86
|
-
os.getenv("MN_WORKSPACE_ROOT")
|
|
87
|
-
or Path(__file__).resolve().parents[3]
|
|
88
|
-
).expanduser()
|
|
89
|
-
candidate = repo_root / "mn-skills" / "blueprint_support_skill" / "src"
|
|
90
|
-
if candidate.is_dir() and str(candidate) not in sys.path:
|
|
91
|
-
sys.path.insert(0, str(candidate))
|
|
92
|
-
|
|
93
|
-
|
|
94
86
|
@blueprint_app.callback()
|
|
95
87
|
def blueprint_callback(
|
|
96
88
|
ctx: typer.Context,
|
|
@@ -147,11 +139,6 @@ def _prepare_blueprint_bundle_for_run(
|
|
|
147
139
|
|
|
148
140
|
def _generate_python_source_bundle(blueprint_dir: Path, output_dir: Path) -> Path:
|
|
149
141
|
_load_observability_api()
|
|
150
|
-
_inject_local_blueprint_support_path()
|
|
151
|
-
from mn_blueprint_support.python_workflow_bundle import (
|
|
152
|
-
generate_python_workflow_bundle_from_blueprint_dir,
|
|
153
|
-
)
|
|
154
|
-
|
|
155
142
|
return generate_python_workflow_bundle_from_blueprint_dir(
|
|
156
143
|
blueprint_dir,
|
|
157
144
|
output_dir,
|
|
@@ -1,47 +1,33 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
import sys
|
|
6
4
|
import time
|
|
7
5
|
from typing import Any, Callable, Optional
|
|
8
6
|
|
|
9
7
|
import typer
|
|
8
|
+
from mn_sdk.blueprint_support import make_run_id
|
|
9
|
+
from mn_sdk.blueprint_support.observability import (
|
|
10
|
+
acknowledge_human_notice,
|
|
11
|
+
list_pending_human_requests,
|
|
12
|
+
list_runs,
|
|
13
|
+
load_run,
|
|
14
|
+
read_human_events,
|
|
15
|
+
read_run_events,
|
|
16
|
+
read_run_logs,
|
|
17
|
+
read_run_resources,
|
|
18
|
+
read_run_stream_records,
|
|
19
|
+
record_human_response,
|
|
20
|
+
)
|
|
21
|
+
from mn_sdk.blueprint_support.web_ui import write_static_run_report
|
|
10
22
|
|
|
11
23
|
from mn_cli.shared import console
|
|
12
24
|
|
|
13
25
|
|
|
14
26
|
def load_observability_api() -> tuple[Callable[..., list[dict[str, Any]]], Callable[..., dict[str, Any]], Callable[..., list[dict[str, Any]]]]:
|
|
15
|
-
_ensure_blueprint_support_path()
|
|
16
|
-
try:
|
|
17
|
-
from mn_blueprint_support.observability import list_runs, load_run, read_run_events
|
|
18
|
-
except ModuleNotFoundError:
|
|
19
|
-
console.print(
|
|
20
|
-
"[red]Blueprint observability support is unavailable. "
|
|
21
|
-
"Install the blueprint support package or run from the monorepo checkout.[/red]"
|
|
22
|
-
)
|
|
23
|
-
raise typer.Exit(1)
|
|
24
27
|
return list_runs, load_run, read_run_events
|
|
25
28
|
|
|
26
29
|
|
|
27
30
|
def load_observability_tools() -> dict[str, Callable[..., Any]]:
|
|
28
|
-
_ensure_blueprint_support_path()
|
|
29
|
-
try:
|
|
30
|
-
from mn_blueprint_support.observability import (
|
|
31
|
-
acknowledge_human_notice,
|
|
32
|
-
list_pending_human_requests,
|
|
33
|
-
read_human_events,
|
|
34
|
-
read_run_logs,
|
|
35
|
-
read_run_resources,
|
|
36
|
-
read_run_stream_records,
|
|
37
|
-
record_human_response,
|
|
38
|
-
)
|
|
39
|
-
except ModuleNotFoundError:
|
|
40
|
-
console.print(
|
|
41
|
-
"[red]Blueprint observability support is unavailable. "
|
|
42
|
-
"Install the blueprint support package or run from the monorepo checkout.[/red]"
|
|
43
|
-
)
|
|
44
|
-
raise typer.Exit(1)
|
|
45
31
|
return {
|
|
46
32
|
"acknowledge_human_notice": acknowledge_human_notice,
|
|
47
33
|
"list_pending_human_requests": list_pending_human_requests,
|
|
@@ -53,28 +39,12 @@ def load_observability_tools() -> dict[str, Callable[..., Any]]:
|
|
|
53
39
|
}
|
|
54
40
|
|
|
55
41
|
|
|
56
|
-
def _ensure_blueprint_support_path() -> None:
|
|
57
|
-
repo_root = Path(__file__).resolve().parents[3]
|
|
58
|
-
support_src = repo_root / "mn-skills" / "blueprint_support_skill" / "src"
|
|
59
|
-
if support_src.exists() and str(support_src) not in sys.path:
|
|
60
|
-
sys.path.insert(0, str(support_src))
|
|
61
|
-
|
|
62
|
-
|
|
63
42
|
def load_web_ui_api() -> Callable[..., Any]:
|
|
64
|
-
load_observability_api()
|
|
65
|
-
try:
|
|
66
|
-
from mn_blueprint_support.web_ui import write_static_run_report
|
|
67
|
-
except ModuleNotFoundError:
|
|
68
|
-
console.print("[red]Blueprint web UI support is unavailable.[/red]")
|
|
69
|
-
raise typer.Exit(1)
|
|
70
43
|
return write_static_run_report
|
|
71
44
|
|
|
72
45
|
|
|
73
46
|
def make_blueprint_run_id(blueprint_id: str) -> str:
|
|
74
47
|
try:
|
|
75
|
-
load_observability_api()
|
|
76
|
-
from mn_blueprint_support import make_run_id
|
|
77
|
-
|
|
78
48
|
return make_run_id(blueprint_id)
|
|
79
49
|
except Exception:
|
|
80
50
|
import uuid
|
|
@@ -2,25 +2,9 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
|
-
from
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def _ensure_blueprint_support_path() -> None:
|
|
9
|
-
import os
|
|
10
|
-
import sys
|
|
11
|
-
|
|
12
|
-
repo_root = Path(
|
|
13
|
-
os.getenv("MN_WORKSPACE_ROOT")
|
|
14
|
-
or Path(__file__).resolve().parents[3]
|
|
15
|
-
).expanduser()
|
|
16
|
-
support_src = repo_root / "mn-skills" / "blueprint_support_skill" / "src"
|
|
17
|
-
if support_src.is_dir() and str(support_src) not in sys.path:
|
|
18
|
-
sys.path.insert(0, str(support_src))
|
|
5
|
+
from mn_sdk.blueprint_support.event_relay import build_parser, run_event_relay
|
|
19
6
|
|
|
20
|
-
|
|
21
|
-
_ensure_blueprint_support_path()
|
|
22
|
-
|
|
23
|
-
from mn_blueprint_support.event_relay import build_parser, run_event_relay
|
|
7
|
+
from mn_cli.shared import client
|
|
24
8
|
|
|
25
9
|
|
|
26
10
|
def main(argv: list[str] | None = None) -> int:
|
|
@@ -8,6 +8,7 @@ import signal
|
|
|
8
8
|
import socket
|
|
9
9
|
import subprocess
|
|
10
10
|
import sys
|
|
11
|
+
import tempfile
|
|
11
12
|
import time
|
|
12
13
|
import urllib.parse
|
|
13
14
|
from pathlib import Path
|
|
@@ -43,12 +44,14 @@ from mn_cli.libs.run_manifest import (
|
|
|
43
44
|
runtime_web_ui_support_payloads_for_manifest,
|
|
44
45
|
run_mode_label as _run_mode_label,
|
|
45
46
|
stage_blueprint_support_payloads_for_manifest,
|
|
47
|
+
stage_skill_dependency_payloads_for_manifest,
|
|
46
48
|
stage_skill_runtime_support_payloads_for_manifest,
|
|
47
49
|
stage_local_input_payloads_for_manifest,
|
|
48
50
|
stage_upload_path_payloads_for_manifest,
|
|
49
51
|
with_shared_run_store_config as _with_shared_run_store_config,
|
|
50
52
|
)
|
|
51
53
|
from mn_cli.libs.skill_runtime import validate_skill_runtime_requirements
|
|
54
|
+
from mn_cli.libs.skill_dependencies import gar_requirements_text
|
|
52
55
|
from mn_cli.libs.workflow_validation import (
|
|
53
56
|
_is_workflow_manifest,
|
|
54
57
|
_manifest_workflow_id,
|
|
@@ -59,6 +62,7 @@ from mn_cli.libs.blueprint_observability import (
|
|
|
59
62
|
make_blueprint_run_id as _make_blueprint_run_id,
|
|
60
63
|
)
|
|
61
64
|
from mn_cli.libs.blueprint_resources import cleanup_blueprint_host_hooks
|
|
65
|
+
from mn_cli.server_cmds import ensure_context_engine_runtime
|
|
62
66
|
from mn_cli.shared import console, client, logger
|
|
63
67
|
from mn_cli.terminal import use_progress
|
|
64
68
|
from mn_cli.error_handler import handle_cli_error
|
|
@@ -75,6 +79,7 @@ from mn_sdk import (
|
|
|
75
79
|
validate_service_spec_issues,
|
|
76
80
|
workflow_progress_snapshot,
|
|
77
81
|
)
|
|
82
|
+
from mn_sdk.context_engine import blueprint_requires_context_engine
|
|
78
83
|
from mn_sdk.runtime_config import default_runs_root
|
|
79
84
|
|
|
80
85
|
FINAL_STATUSES = {"completed", "failed", "cancelled"}
|
|
@@ -84,6 +89,10 @@ POST_LAUNCH_SCRIPT = Path("scripts/post-launch.sh")
|
|
|
84
89
|
DEFAULT_BLUEPRINT_WEB_UI_PORT_START = 61000
|
|
85
90
|
DEFAULT_BLUEPRINT_WEB_UI_PORT_END = 61049
|
|
86
91
|
DETACHED_AFTER_INTERRUPT_MESSAGE = "Detached from workflow UI. Job is still running."
|
|
92
|
+
CONTEXT_ENGINE_EXPECTATION = (
|
|
93
|
+
"This blueprint uses context memory. First launch may download the context model "
|
|
94
|
+
"and start the Membrane context engine; keep Docker running and be patient."
|
|
95
|
+
)
|
|
87
96
|
_HELPER_COMPAT = (
|
|
88
97
|
_add_mn_llm_aliases,
|
|
89
98
|
_blueprint_runtime_environment,
|
|
@@ -93,6 +102,13 @@ _HELPER_COMPAT = (
|
|
|
93
102
|
)
|
|
94
103
|
|
|
95
104
|
|
|
105
|
+
def _print_launch_progress(label: str, detail: str | None = None) -> None:
|
|
106
|
+
if detail:
|
|
107
|
+
console.print(f"[cyan]Launch:[/cyan] {label} - {detail}")
|
|
108
|
+
else:
|
|
109
|
+
console.print(f"[cyan]Launch:[/cyan] {label}")
|
|
110
|
+
|
|
111
|
+
|
|
96
112
|
def fetch_and_save_results(job_id: str, data: dict = None):
|
|
97
113
|
log_dir = Path(f"/tmp/mn_{job_id}")
|
|
98
114
|
log_dir.mkdir(parents=True, exist_ok=True)
|
|
@@ -218,6 +234,48 @@ def _manifest_config(manifest: dict[str, Any]) -> dict[str, Any]:
|
|
|
218
234
|
return {}
|
|
219
235
|
|
|
220
236
|
|
|
237
|
+
def _ensure_context_engine_for_run_if_needed(
|
|
238
|
+
bundle_dir: Path,
|
|
239
|
+
manifest: dict[str, Any],
|
|
240
|
+
*,
|
|
241
|
+
env_overrides: Optional[dict[str, str]] = None,
|
|
242
|
+
config_overrides: Optional[dict[str, Any]] = None,
|
|
243
|
+
force: bool = False,
|
|
244
|
+
) -> dict[str, str] | None:
|
|
245
|
+
config = load_blueprint_config(bundle_dir, config_overrides=config_overrides)
|
|
246
|
+
effective_env = os.environ.copy()
|
|
247
|
+
effective_env.update(
|
|
248
|
+
{
|
|
249
|
+
str(key): str(value)
|
|
250
|
+
for key, value in (env_overrides or {}).items()
|
|
251
|
+
if value is not None
|
|
252
|
+
}
|
|
253
|
+
)
|
|
254
|
+
if not blueprint_requires_context_engine(manifest, config, env=effective_env):
|
|
255
|
+
return None
|
|
256
|
+
|
|
257
|
+
console.print(f"[cyan]{CONTEXT_ENGINE_EXPECTATION}[/cyan]")
|
|
258
|
+
with Progress(
|
|
259
|
+
SpinnerColumn(),
|
|
260
|
+
TextColumn("[progress.description]{task.description}"),
|
|
261
|
+
TimeElapsedColumn(),
|
|
262
|
+
console=console,
|
|
263
|
+
disable=not use_progress(),
|
|
264
|
+
) as progress:
|
|
265
|
+
task = progress.add_task(
|
|
266
|
+
"[cyan]Preparing context memory: checking Membrane and Docker Model Runner...",
|
|
267
|
+
total=None,
|
|
268
|
+
)
|
|
269
|
+
summary = ensure_context_engine_runtime(force=force)
|
|
270
|
+
progress.update(task, description="[green]Context memory is ready.")
|
|
271
|
+
console.print(
|
|
272
|
+
f"[green]Context memory ready:[/green] {summary.get('service', 'membrane-context-engine')} "
|
|
273
|
+
f"using {summary.get('model', 'configured model')}"
|
|
274
|
+
)
|
|
275
|
+
logger.info("Context engine runtime ensured for %s: %s", bundle_dir, summary)
|
|
276
|
+
return summary
|
|
277
|
+
|
|
278
|
+
|
|
221
279
|
def _expand_user_output_path(value: str) -> Path:
|
|
222
280
|
text = str(value or "").strip()
|
|
223
281
|
home = (
|
|
@@ -1423,6 +1481,7 @@ def _stage_bundle_payloads(
|
|
|
1423
1481
|
payloads.update(runtime_web_ui_support_payloads_for_manifest(manifest_dict))
|
|
1424
1482
|
stage_blueprint_support_payloads_for_manifest(manifest_dict, payloads, bundle_dir=bundle_dir)
|
|
1425
1483
|
stage_skill_runtime_support_payloads_for_manifest(manifest_dict, payloads, bundle_dir=bundle_dir)
|
|
1484
|
+
stage_skill_dependency_payloads_for_manifest(manifest_dict, payloads, bundle_dir=bundle_dir)
|
|
1426
1485
|
return payloads
|
|
1427
1486
|
|
|
1428
1487
|
|
|
@@ -1514,6 +1573,10 @@ def run_bundle(
|
|
|
1514
1573
|
submission_metadata,
|
|
1515
1574
|
config_overrides=config_overrides,
|
|
1516
1575
|
)
|
|
1576
|
+
_print_launch_progress(
|
|
1577
|
+
"Check runtime resources",
|
|
1578
|
+
"confirming the runtime can satisfy this blueprint before submission.",
|
|
1579
|
+
)
|
|
1517
1580
|
_validate_manifest_hardware_or_exit(
|
|
1518
1581
|
manifest_dict,
|
|
1519
1582
|
force=force,
|
|
@@ -1536,6 +1599,10 @@ def run_bundle(
|
|
|
1536
1599
|
config_overrides=config_overrides,
|
|
1537
1600
|
)
|
|
1538
1601
|
if not force:
|
|
1602
|
+
_print_launch_progress(
|
|
1603
|
+
"Validate inputs and dependencies",
|
|
1604
|
+
"checking services, models, local inputs, and non-hard requirements.",
|
|
1605
|
+
)
|
|
1539
1606
|
_validate_manifest_services_or_exit(
|
|
1540
1607
|
bundle_dir,
|
|
1541
1608
|
manifest_dict,
|
|
@@ -1558,6 +1625,10 @@ def run_bundle(
|
|
|
1558
1625
|
console.print(
|
|
1559
1626
|
"[yellow]Validation skipped because --force was provided; service checks, model checks, input checks, and non-hard runtime requirements will be bypassed for this run.[/yellow]"
|
|
1560
1627
|
)
|
|
1628
|
+
_print_launch_progress(
|
|
1629
|
+
"Package workflow",
|
|
1630
|
+
"staging workflow files, local inputs, runtime helpers, and output wiring.",
|
|
1631
|
+
)
|
|
1561
1632
|
manifest_dict = prepare_manifest_for_submission(
|
|
1562
1633
|
bundle_dir,
|
|
1563
1634
|
manifest_dict,
|
|
@@ -1583,6 +1654,14 @@ def run_bundle(
|
|
|
1583
1654
|
)
|
|
1584
1655
|
return
|
|
1585
1656
|
|
|
1657
|
+
_ensure_context_engine_for_run_if_needed(
|
|
1658
|
+
bundle_dir,
|
|
1659
|
+
manifest_dict,
|
|
1660
|
+
env_overrides=env_overrides,
|
|
1661
|
+
config_overrides=config_overrides,
|
|
1662
|
+
force=force,
|
|
1663
|
+
)
|
|
1664
|
+
|
|
1586
1665
|
prepared_submission = prepare_job_submission(
|
|
1587
1666
|
manifest_dict,
|
|
1588
1667
|
payloads,
|
|
@@ -1599,6 +1678,10 @@ def run_bundle(
|
|
|
1599
1678
|
else None
|
|
1600
1679
|
)
|
|
1601
1680
|
submitted_run_dir = blueprint_run_dir
|
|
1681
|
+
_print_launch_progress(
|
|
1682
|
+
"Submit runtime job",
|
|
1683
|
+
"handing the prepared bundle to MirrorNeuron core.",
|
|
1684
|
+
)
|
|
1602
1685
|
job_id = client.submit_job(manifest, payloads, force=force)
|
|
1603
1686
|
submitted_job_id = job_id
|
|
1604
1687
|
log_writer = JobLogWriter(job_id, run_dir=blueprint_run_dir)
|
|
@@ -1883,9 +1966,14 @@ def _prepare_openshell_custom_images(
|
|
|
1883
1966
|
if source_path is None:
|
|
1884
1967
|
continue
|
|
1885
1968
|
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1969
|
+
build_source = _openshell_skill_dependency_context(source_path, manifest_dict)
|
|
1970
|
+
try:
|
|
1971
|
+
config["from"] = _build_openshell_from_image(
|
|
1972
|
+
build_source, node.get("node_id") or "openshell"
|
|
1973
|
+
)
|
|
1974
|
+
finally:
|
|
1975
|
+
if build_source != source_path:
|
|
1976
|
+
shutil.rmtree(build_source, ignore_errors=True)
|
|
1889
1977
|
|
|
1890
1978
|
|
|
1891
1979
|
def _openshell_gateway_endpoint() -> str:
|
|
@@ -1981,6 +2069,30 @@ def _openshell_local_from_path(bundle_dir: Path, source: Any) -> Path | None:
|
|
|
1981
2069
|
return None
|
|
1982
2070
|
|
|
1983
2071
|
|
|
2072
|
+
def _openshell_skill_dependency_context(source_path: Path, manifest: dict[str, Any]) -> Path:
|
|
2073
|
+
requirements_text = gar_requirements_text(manifest)
|
|
2074
|
+
if not requirements_text:
|
|
2075
|
+
return source_path
|
|
2076
|
+
|
|
2077
|
+
source_root = source_path.parent if source_path.is_file() else source_path
|
|
2078
|
+
temp_context = Path(tempfile.mkdtemp(prefix=f"mn-openshell-skill-deps-{source_root.name}."))
|
|
2079
|
+
shutil.copytree(source_root, temp_context, dirs_exist_ok=True)
|
|
2080
|
+
dockerfile = temp_context / "Dockerfile"
|
|
2081
|
+
requirements = temp_context / "__mn_skill_dependencies" / "requirements.txt"
|
|
2082
|
+
requirements.parent.mkdir(parents=True, exist_ok=True)
|
|
2083
|
+
requirements.write_text(requirements_text, encoding="utf-8")
|
|
2084
|
+
dockerfile.write_text(
|
|
2085
|
+
dockerfile.read_text(encoding="utf-8").rstrip()
|
|
2086
|
+
+ "\n\n"
|
|
2087
|
+
+ "COPY __mn_skill_dependencies/requirements.txt /tmp/mn-skill-dependencies/requirements.txt\n"
|
|
2088
|
+
+ "RUN if [ -s /tmp/mn-skill-dependencies/requirements.txt ]; then \\\n"
|
|
2089
|
+
+ " python3 -m pip install --break-system-packages --no-cache-dir -r /tmp/mn-skill-dependencies/requirements.txt; \\\n"
|
|
2090
|
+
+ " fi\n",
|
|
2091
|
+
encoding="utf-8",
|
|
2092
|
+
)
|
|
2093
|
+
return temp_context
|
|
2094
|
+
|
|
2095
|
+
|
|
1984
2096
|
def _build_openshell_from_image(source_path: Path, node_id: Any) -> str:
|
|
1985
2097
|
console.print(
|
|
1986
2098
|
f"[yellow]Building OpenShell sandbox image for {node_id} from {source_path}...[/yellow]"
|
|
@@ -2451,7 +2563,7 @@ def _start_background_event_relay_if_needed(
|
|
|
2451
2563
|
command = [
|
|
2452
2564
|
sys.executable,
|
|
2453
2565
|
"-m",
|
|
2454
|
-
"
|
|
2566
|
+
"mn_sdk.blueprint_support.event_relay",
|
|
2455
2567
|
"--job-id",
|
|
2456
2568
|
job_id,
|
|
2457
2569
|
"--run-dir",
|
|
@@ -2464,7 +2576,6 @@ def _start_background_event_relay_if_needed(
|
|
|
2464
2576
|
|
|
2465
2577
|
env = os.environ.copy()
|
|
2466
2578
|
env["MN_RUN_EVENT_RELAY_CHILD"] = "1"
|
|
2467
|
-
_inject_local_blueprint_support_pythonpath(env)
|
|
2468
2579
|
with open(log_path, "a", encoding="utf-8") as relay_log:
|
|
2469
2580
|
process = subprocess.Popen(
|
|
2470
2581
|
command,
|
|
@@ -2598,7 +2709,7 @@ def _web_ui_registration_module(
|
|
|
2598
2709
|
|
|
2599
2710
|
adapter = str(output.get("adapter") or web_ui.get("kind") or "").lower()
|
|
2600
2711
|
if adapter == "gradio" and output.get("auto_generate", True) is not False:
|
|
2601
|
-
return "
|
|
2712
|
+
return "mn_sdk.blueprint_support.gradio_dashboard"
|
|
2602
2713
|
return None
|
|
2603
2714
|
|
|
2604
2715
|
|
|
@@ -2764,21 +2875,6 @@ def _launch_blueprint_web_ui_command(
|
|
|
2764
2875
|
)
|
|
2765
2876
|
|
|
2766
2877
|
|
|
2767
|
-
def _inject_local_blueprint_support_pythonpath(env: dict[str, str]) -> None:
|
|
2768
|
-
repo_root = Path(
|
|
2769
|
-
os.getenv("MN_WORKSPACE_ROOT")
|
|
2770
|
-
or Path(__file__).resolve().parents[3]
|
|
2771
|
-
).expanduser()
|
|
2772
|
-
support_src = repo_root / "mn-skills" / "blueprint_support_skill" / "src"
|
|
2773
|
-
if not support_src.is_dir():
|
|
2774
|
-
return
|
|
2775
|
-
current = env.get("PYTHONPATH")
|
|
2776
|
-
paths = [str(support_src)]
|
|
2777
|
-
if current:
|
|
2778
|
-
paths.append(current)
|
|
2779
|
-
env["PYTHONPATH"] = os.pathsep.join(paths)
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
2878
|
def _web_ui_bind_host(output: dict[str, Any], env_overrides: dict[str, str]) -> str:
|
|
2783
2879
|
for value in (
|
|
2784
2880
|
env_overrides.get("MN_BLUEPRINT_WEB_UI_BIND_HOST"),
|