milady 2.0.0a93__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.
- milady-2.0.0a93/.gitignore +140 -0
- milady-2.0.0a93/PKG-INFO +114 -0
- milady-2.0.0a93/README.md +83 -0
- milady-2.0.0a93/milady/__init__.py +35 -0
- milady-2.0.0a93/milady/__main__.py +5 -0
- milady-2.0.0a93/milady/cli.py +25 -0
- milady-2.0.0a93/milady/loader.py +275 -0
- milady-2.0.0a93/milady/py.typed +0 -0
- milady-2.0.0a93/pyproject.toml +56 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
node_modules
|
|
2
|
+
**/node_modules/
|
|
3
|
+
.env
|
|
4
|
+
dist
|
|
5
|
+
storybook-static
|
|
6
|
+
coverage
|
|
7
|
+
tmp/
|
|
8
|
+
apps/app/electron/build/
|
|
9
|
+
apps/app/electrobun/build/
|
|
10
|
+
.bun
|
|
11
|
+
.DS_Store
|
|
12
|
+
**/.DS_Store
|
|
13
|
+
|
|
14
|
+
# Build artifacts
|
|
15
|
+
*.bun-build
|
|
16
|
+
**/*.bun-build
|
|
17
|
+
*.tsbuildinfo
|
|
18
|
+
apps/app/electron/tsc-out/
|
|
19
|
+
|
|
20
|
+
# TypeScript declaration build outputs inside source dirs
|
|
21
|
+
packages/*/src/**/*.d.ts
|
|
22
|
+
packages/*/src/**/*.d.ts.map
|
|
23
|
+
src/plugins/**/*.d.ts
|
|
24
|
+
src/plugins/**/*.d.ts.map
|
|
25
|
+
|
|
26
|
+
# Lock files (managed at repo root)
|
|
27
|
+
package-lock.json
|
|
28
|
+
bun.lockb
|
|
29
|
+
pnpm-lock.yaml
|
|
30
|
+
!deploy/cloud-agent-template/package-lock.json
|
|
31
|
+
|
|
32
|
+
# Docker overrides
|
|
33
|
+
docker-compose.extra.yml
|
|
34
|
+
|
|
35
|
+
# UI test artifacts
|
|
36
|
+
apps/ui/src/ui/__screenshots__/
|
|
37
|
+
apps/ui/playwright-report/
|
|
38
|
+
apps/ui/test-results/
|
|
39
|
+
|
|
40
|
+
# Vendored repos (clone separately if needed)
|
|
41
|
+
vendor/
|
|
42
|
+
plugins/plugin-blooio/
|
|
43
|
+
|
|
44
|
+
# Local untracked files
|
|
45
|
+
.local/
|
|
46
|
+
.vscode/
|
|
47
|
+
.claude/settings.local.json
|
|
48
|
+
.claude/skills/
|
|
49
|
+
.git-workspace/
|
|
50
|
+
IDENTITY.md
|
|
51
|
+
USER.md
|
|
52
|
+
*.tgz
|
|
53
|
+
.eliza/
|
|
54
|
+
.eliza.broken.*/
|
|
55
|
+
.milady-repo-setup.lock
|
|
56
|
+
.turbo/
|
|
57
|
+
skills/*
|
|
58
|
+
!skills/README.md
|
|
59
|
+
!skills/integration-dod-map/
|
|
60
|
+
skills/integration-dod-map/*
|
|
61
|
+
!skills/integration-dod-map/SKILL.md
|
|
62
|
+
apps/app/electron/.eliza
|
|
63
|
+
apps/app/electron/skills/
|
|
64
|
+
|
|
65
|
+
# Local workspace clones / scratch dirs
|
|
66
|
+
milady-workspace/
|
|
67
|
+
assets/
|
|
68
|
+
|
|
69
|
+
# Temporary capture files
|
|
70
|
+
temp_capture_*.jpg
|
|
71
|
+
knip_output*.txt
|
|
72
|
+
src/benchmark/mock-plugin.ts
|
|
73
|
+
biome-report.json
|
|
74
|
+
|
|
75
|
+
# Test/build log files
|
|
76
|
+
*.log
|
|
77
|
+
!docs/**/*.log
|
|
78
|
+
|
|
79
|
+
# Local audit outputs
|
|
80
|
+
report/
|
|
81
|
+
|
|
82
|
+
# Agent learning docs & knowledge base
|
|
83
|
+
knowledge/
|
|
84
|
+
scripts/knowledge-loop.mjs
|
|
85
|
+
test/contracts/
|
|
86
|
+
apps/app/test-results/
|
|
87
|
+
# WhatsApp session files (Baileys auth state)
|
|
88
|
+
/auth/
|
|
89
|
+
:memory:/
|
|
90
|
+
benchmarks/
|
|
91
|
+
/plugins/
|
|
92
|
+
!docs/plugins/
|
|
93
|
+
|
|
94
|
+
# Electrobun compiled native binaries (built locally, not committed)
|
|
95
|
+
apps/app/electrobun/src/libMacWindowEffects.dylib
|
|
96
|
+
# Electrobun built webview bridge preload (generated by `bun run build:preload`)
|
|
97
|
+
apps/app/electrobun/src/preload.js
|
|
98
|
+
# Electrobun build artifacts (created by `electrobun build`)
|
|
99
|
+
apps/app/electrobun/artifacts/
|
|
100
|
+
|
|
101
|
+
# Electron build directories
|
|
102
|
+
apps/app/electron/app-build/
|
|
103
|
+
apps/app/electron/milady-dist/
|
|
104
|
+
dist-electron/
|
|
105
|
+
|
|
106
|
+
# Build artifacts - installers and archives
|
|
107
|
+
*.dmg
|
|
108
|
+
*.AppImage
|
|
109
|
+
*.exe
|
|
110
|
+
*.msi
|
|
111
|
+
*.deb
|
|
112
|
+
*.rpm
|
|
113
|
+
apps/app/electron/*.tar.gz
|
|
114
|
+
|
|
115
|
+
# Test output directories
|
|
116
|
+
test-output/
|
|
117
|
+
|
|
118
|
+
# External plugin repos (not submodules)
|
|
119
|
+
elizaos-plugins/
|
|
120
|
+
e2e-screenshots/
|
|
121
|
+
data/
|
|
122
|
+
.avatar-clone-tmp
|
|
123
|
+
|
|
124
|
+
# Debug PTY captures from plugin-agent-orchestrator (PARALLAX_DEBUG_CAPTURE=1)
|
|
125
|
+
.parallax/
|
|
126
|
+
.worktrees/
|
|
127
|
+
|
|
128
|
+
# Generated raw avatar/animation assets from local setup hooks (non-source)
|
|
129
|
+
apps/app/public/animations/**/*.fbx
|
|
130
|
+
apps/app/public/animations/**/*.glb
|
|
131
|
+
apps/app/public/animations/*.fbx
|
|
132
|
+
apps/app/public/animations/*.glb
|
|
133
|
+
apps/app/public/vrms/**/*.vrm
|
|
134
|
+
apps/app/public/vrms/*.vrm
|
|
135
|
+
apps/app/public/vrms/imported-avatars.json
|
|
136
|
+
apps/app/public/vrms/backgrounds/*.png
|
|
137
|
+
apps/app/public/vrms/previews/*.png
|
|
138
|
+
apps/app/public/vrms/backgrounds/*.jpg
|
|
139
|
+
apps/app/public/vrms/previews/*.jpg
|
|
140
|
+
apps/app/public/vrms/*.jpg
|
milady-2.0.0a93/PKG-INFO
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: milady
|
|
3
|
+
Version: 2.0.0a93
|
|
4
|
+
Summary: Dynamic loader for Milady — personal AI assistant built on elizaOS
|
|
5
|
+
Project-URL: Homepage, https://milady.ai
|
|
6
|
+
Project-URL: Repository, https://github.com/milady-ai/milady
|
|
7
|
+
Project-URL: Documentation, https://docs.milady.ai
|
|
8
|
+
Project-URL: Issues, https://github.com/milady-ai/milady/issues
|
|
9
|
+
Author-email: milady-ai <dev@milady.ai>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
Keywords: agent,ai,assistant,cli,elizaos,llm,milady
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: MacOS
|
|
18
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
19
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
20
|
+
Classifier: Programming Language :: Python :: 3
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
26
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
27
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
28
|
+
Classifier: Typing :: Typed
|
|
29
|
+
Requires-Python: >=3.9
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# milady
|
|
33
|
+
|
|
34
|
+
**Dynamic Python loader for [Milady](https://github.com/milady-ai/milady)** — a personal AI assistant built on [elizaOS](https://github.com/elizaos).
|
|
35
|
+
|
|
36
|
+
This package provides a `milady` command that automatically manages the Node.js-based Milady runtime. Install via pip, run like any CLI tool.
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install milady
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Or with [pipx](https://pipx.pypa.io/) for isolated CLI install:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pipx install milady
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Quick Start
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Start your personal AI agent (installs runtime automatically on first run)
|
|
54
|
+
milady start
|
|
55
|
+
|
|
56
|
+
# Or just run it — interactive onboarding guides you through setup
|
|
57
|
+
milady
|
|
58
|
+
|
|
59
|
+
# Show all commands
|
|
60
|
+
milady --help
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## How It Works
|
|
64
|
+
|
|
65
|
+
`milady` is a **dynamic loader** — a thin Python wrapper that:
|
|
66
|
+
|
|
67
|
+
1. Checks for Node.js >= 22.12.0 on your system
|
|
68
|
+
2. Ensures the `milady` npm package is installed globally
|
|
69
|
+
3. Forwards all CLI commands to the Node.js runtime
|
|
70
|
+
4. Installs the runtime automatically if not present
|
|
71
|
+
|
|
72
|
+
This means you get the full Milady experience through pip/pipx, without needing to interact with npm directly.
|
|
73
|
+
|
|
74
|
+
## Python API
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from milady import run, ensure_runtime, get_version
|
|
78
|
+
|
|
79
|
+
# Ensure the runtime is installed and ready
|
|
80
|
+
ensure_runtime()
|
|
81
|
+
|
|
82
|
+
# Run a milady command programmatically
|
|
83
|
+
exit_code = run(["start"])
|
|
84
|
+
|
|
85
|
+
# Check the installed version
|
|
86
|
+
version = get_version()
|
|
87
|
+
print(f"Milady {version}")
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Requirements
|
|
91
|
+
|
|
92
|
+
- **Python** >= 3.9
|
|
93
|
+
- **Node.js** >= 22.12.0 (the loader will tell you how to install it if missing)
|
|
94
|
+
|
|
95
|
+
## What is Milady?
|
|
96
|
+
|
|
97
|
+
Milady is a personal AI assistant you run on your own devices. It provides:
|
|
98
|
+
|
|
99
|
+
- Zero-config onboarding with interactive setup
|
|
100
|
+
- Support for multiple AI providers (Anthropic, OpenAI, Google, Ollama, etc.)
|
|
101
|
+
- Web dashboard at `http://localhost:18789`
|
|
102
|
+
- Plugin system for extensibility
|
|
103
|
+
- Web3 wallet integration (EVM + Solana)
|
|
104
|
+
- Desktop apps for macOS, Windows, and Linux
|
|
105
|
+
|
|
106
|
+
## Links
|
|
107
|
+
|
|
108
|
+
- [Documentation](https://docs.milady.ai)
|
|
109
|
+
- [GitHub](https://github.com/milady-ai/milady)
|
|
110
|
+
- [elizaOS](https://github.com/elizaos)
|
|
111
|
+
|
|
112
|
+
## License
|
|
113
|
+
|
|
114
|
+
MIT
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# milady
|
|
2
|
+
|
|
3
|
+
**Dynamic Python loader for [Milady](https://github.com/milady-ai/milady)** — a personal AI assistant built on [elizaOS](https://github.com/elizaos).
|
|
4
|
+
|
|
5
|
+
This package provides a `milady` command that automatically manages the Node.js-based Milady runtime. Install via pip, run like any CLI tool.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install milady
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or with [pipx](https://pipx.pypa.io/) for isolated CLI install:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pipx install milady
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Start your personal AI agent (installs runtime automatically on first run)
|
|
23
|
+
milady start
|
|
24
|
+
|
|
25
|
+
# Or just run it — interactive onboarding guides you through setup
|
|
26
|
+
milady
|
|
27
|
+
|
|
28
|
+
# Show all commands
|
|
29
|
+
milady --help
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## How It Works
|
|
33
|
+
|
|
34
|
+
`milady` is a **dynamic loader** — a thin Python wrapper that:
|
|
35
|
+
|
|
36
|
+
1. Checks for Node.js >= 22.12.0 on your system
|
|
37
|
+
2. Ensures the `milady` npm package is installed globally
|
|
38
|
+
3. Forwards all CLI commands to the Node.js runtime
|
|
39
|
+
4. Installs the runtime automatically if not present
|
|
40
|
+
|
|
41
|
+
This means you get the full Milady experience through pip/pipx, without needing to interact with npm directly.
|
|
42
|
+
|
|
43
|
+
## Python API
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from milady import run, ensure_runtime, get_version
|
|
47
|
+
|
|
48
|
+
# Ensure the runtime is installed and ready
|
|
49
|
+
ensure_runtime()
|
|
50
|
+
|
|
51
|
+
# Run a milady command programmatically
|
|
52
|
+
exit_code = run(["start"])
|
|
53
|
+
|
|
54
|
+
# Check the installed version
|
|
55
|
+
version = get_version()
|
|
56
|
+
print(f"Milady {version}")
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Requirements
|
|
60
|
+
|
|
61
|
+
- **Python** >= 3.9
|
|
62
|
+
- **Node.js** >= 22.12.0 (the loader will tell you how to install it if missing)
|
|
63
|
+
|
|
64
|
+
## What is Milady?
|
|
65
|
+
|
|
66
|
+
Milady is a personal AI assistant you run on your own devices. It provides:
|
|
67
|
+
|
|
68
|
+
- Zero-config onboarding with interactive setup
|
|
69
|
+
- Support for multiple AI providers (Anthropic, OpenAI, Google, Ollama, etc.)
|
|
70
|
+
- Web dashboard at `http://localhost:18789`
|
|
71
|
+
- Plugin system for extensibility
|
|
72
|
+
- Web3 wallet integration (EVM + Solana)
|
|
73
|
+
- Desktop apps for macOS, Windows, and Linux
|
|
74
|
+
|
|
75
|
+
## Links
|
|
76
|
+
|
|
77
|
+
- [Documentation](https://docs.milady.ai)
|
|
78
|
+
- [GitHub](https://github.com/milady-ai/milady)
|
|
79
|
+
- [elizaOS](https://github.com/elizaos)
|
|
80
|
+
|
|
81
|
+
## License
|
|
82
|
+
|
|
83
|
+
MIT
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""
|
|
2
|
+
milady — Dynamic loader for Milady, a personal AI assistant built on elizaOS.
|
|
3
|
+
|
|
4
|
+
This package provides a Python entry point that dynamically loads and runs
|
|
5
|
+
the Milady Node.js runtime. It handles Node.js detection, automatic
|
|
6
|
+
installation of the milady npm package, and seamless CLI delegation.
|
|
7
|
+
|
|
8
|
+
Usage (CLI):
|
|
9
|
+
$ milady start
|
|
10
|
+
$ milady setup
|
|
11
|
+
$ milady --help
|
|
12
|
+
|
|
13
|
+
Usage (Python API):
|
|
14
|
+
from milady import run, ensure_runtime, get_version
|
|
15
|
+
|
|
16
|
+
# Ensure the runtime is ready
|
|
17
|
+
ensure_runtime()
|
|
18
|
+
|
|
19
|
+
# Run a command
|
|
20
|
+
exit_code = run(["start"])
|
|
21
|
+
|
|
22
|
+
# Get the installed version
|
|
23
|
+
version = get_version()
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
__version__ = "2.0.0a93"
|
|
27
|
+
__all__ = ["run", "ensure_runtime", "get_version", "MiladyError", "NodeNotFoundError"]
|
|
28
|
+
|
|
29
|
+
from milady.loader import (
|
|
30
|
+
MiladyError,
|
|
31
|
+
NodeNotFoundError,
|
|
32
|
+
ensure_runtime,
|
|
33
|
+
get_version,
|
|
34
|
+
run,
|
|
35
|
+
)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CLI entry point for the milady dynamic loader.
|
|
3
|
+
|
|
4
|
+
Delegates all commands to the Milady Node.js runtime,
|
|
5
|
+
installing it automatically if needed.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import sys
|
|
11
|
+
|
|
12
|
+
from milady.loader import MiladyError, run
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def main() -> None:
|
|
16
|
+
"""Main CLI entry point — forwards all args to the Node.js milady CLI."""
|
|
17
|
+
try:
|
|
18
|
+
args = sys.argv[1:]
|
|
19
|
+
exit_code = run(args)
|
|
20
|
+
sys.exit(exit_code)
|
|
21
|
+
except MiladyError as exc:
|
|
22
|
+
print(f"milady: {exc}", file=sys.stderr)
|
|
23
|
+
sys.exit(1)
|
|
24
|
+
except KeyboardInterrupt:
|
|
25
|
+
sys.exit(130)
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Dynamic loader for the Milady Node.js runtime.
|
|
3
|
+
|
|
4
|
+
Responsibilities:
|
|
5
|
+
1. Detect a suitable Node.js installation (>= 22.12.0)
|
|
6
|
+
2. Detect or install the milady npm package
|
|
7
|
+
3. Delegate CLI invocations to the Node.js process
|
|
8
|
+
4. Provide a Python API for programmatic use
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import json
|
|
14
|
+
import os
|
|
15
|
+
import re
|
|
16
|
+
import shutil
|
|
17
|
+
import subprocess
|
|
18
|
+
import sys
|
|
19
|
+
from typing import Optional, Sequence, Tuple
|
|
20
|
+
|
|
21
|
+
# ── Constants ────────────────────────────────────────────────────────────────
|
|
22
|
+
|
|
23
|
+
REQUIRED_NODE_VERSION: Tuple[int, int, int] = (22, 12, 0)
|
|
24
|
+
NPM_PACKAGE = "milady"
|
|
25
|
+
_VERSION_RE = re.compile(r"v?(\d+)\.(\d+)\.(\d+)")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# ── Exceptions ───────────────────────────────────────────────────────────────
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class MiladyError(Exception):
|
|
32
|
+
"""Base exception for milady loader errors."""
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class NodeNotFoundError(MiladyError):
|
|
36
|
+
"""Raised when a suitable Node.js installation cannot be found."""
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class RuntimeInstallError(MiladyError):
|
|
40
|
+
"""Raised when the milady npm package cannot be installed."""
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# ── Node.js Detection ────────────────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _parse_version(version_str: str) -> Optional[Tuple[int, int, int]]:
|
|
47
|
+
"""Parse a semver string like 'v22.12.0' into a (major, minor, patch) tuple."""
|
|
48
|
+
match = _VERSION_RE.search(version_str)
|
|
49
|
+
if not match:
|
|
50
|
+
return None
|
|
51
|
+
return (int(match.group(1)), int(match.group(2)), int(match.group(3)))
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _find_node() -> Optional[str]:
|
|
55
|
+
"""Find a node binary on PATH."""
|
|
56
|
+
return shutil.which("node")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _get_node_version(node_bin: str) -> Optional[Tuple[int, int, int]]:
|
|
60
|
+
"""Get the version of a Node.js binary."""
|
|
61
|
+
try:
|
|
62
|
+
result = subprocess.run(
|
|
63
|
+
[node_bin, "--version"],
|
|
64
|
+
capture_output=True,
|
|
65
|
+
text=True,
|
|
66
|
+
timeout=10,
|
|
67
|
+
)
|
|
68
|
+
if result.returncode == 0:
|
|
69
|
+
return _parse_version(result.stdout.strip())
|
|
70
|
+
except (subprocess.SubprocessError, OSError):
|
|
71
|
+
pass
|
|
72
|
+
return None
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _check_node() -> str:
|
|
76
|
+
"""
|
|
77
|
+
Find and validate a Node.js installation.
|
|
78
|
+
|
|
79
|
+
Returns the path to the node binary.
|
|
80
|
+
Raises NodeNotFoundError if no suitable version is found.
|
|
81
|
+
"""
|
|
82
|
+
node_bin = _find_node()
|
|
83
|
+
if not node_bin:
|
|
84
|
+
req = ".".join(str(v) for v in REQUIRED_NODE_VERSION)
|
|
85
|
+
raise NodeNotFoundError(
|
|
86
|
+
f"Node.js not found. Milady requires Node.js >= {req}.\n"
|
|
87
|
+
"Install it from https://nodejs.org or via your package manager:\n"
|
|
88
|
+
" macOS: brew install node@22\n"
|
|
89
|
+
" Linux: curl -fsSL https://deb.nodesource.com/setup_22.x | sudo bash -\n"
|
|
90
|
+
" Windows: winget install OpenJS.NodeJS.LTS"
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
version = _get_node_version(node_bin)
|
|
94
|
+
if version is None:
|
|
95
|
+
raise NodeNotFoundError(
|
|
96
|
+
f"Could not determine version of Node.js at {node_bin}"
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
if version < REQUIRED_NODE_VERSION:
|
|
100
|
+
current = ".".join(str(v) for v in version)
|
|
101
|
+
req = ".".join(str(v) for v in REQUIRED_NODE_VERSION)
|
|
102
|
+
raise NodeNotFoundError(
|
|
103
|
+
f"Node.js {current} found, but >= {req} is required.\n"
|
|
104
|
+
"Please upgrade Node.js: https://nodejs.org"
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
return node_bin
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
# ── npm / npx Detection ─────────────────────────────────────────────────────
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _find_npx() -> Optional[str]:
|
|
114
|
+
"""Find npx on PATH."""
|
|
115
|
+
return shutil.which("npx")
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _find_npm() -> Optional[str]:
|
|
119
|
+
"""Find npm on PATH."""
|
|
120
|
+
return shutil.which("npm")
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _is_milady_installed_globally() -> bool:
|
|
124
|
+
"""Check if milady is installed as a global npm package."""
|
|
125
|
+
npm_bin = _find_npm()
|
|
126
|
+
if not npm_bin:
|
|
127
|
+
return False
|
|
128
|
+
try:
|
|
129
|
+
result = subprocess.run(
|
|
130
|
+
[npm_bin, "list", "-g", NPM_PACKAGE, "--json"],
|
|
131
|
+
capture_output=True,
|
|
132
|
+
text=True,
|
|
133
|
+
timeout=30,
|
|
134
|
+
)
|
|
135
|
+
if result.returncode == 0:
|
|
136
|
+
data = json.loads(result.stdout)
|
|
137
|
+
deps = data.get("dependencies", {})
|
|
138
|
+
return NPM_PACKAGE in deps
|
|
139
|
+
except (subprocess.SubprocessError, OSError, json.JSONDecodeError):
|
|
140
|
+
pass
|
|
141
|
+
return False
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _find_milady_bin() -> Optional[str]:
|
|
145
|
+
"""Find the milady CLI binary on PATH (from a global npm install)."""
|
|
146
|
+
return shutil.which("milady")
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _install_milady_global() -> None:
|
|
150
|
+
"""Install milady globally via npm."""
|
|
151
|
+
npm_bin = _find_npm()
|
|
152
|
+
if not npm_bin:
|
|
153
|
+
raise RuntimeInstallError(
|
|
154
|
+
"npm not found. Cannot install milady runtime.\n"
|
|
155
|
+
"Install Node.js (which includes npm) from https://nodejs.org"
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
print(
|
|
159
|
+
"milady: installing milady runtime (npm install -g miladyai)...",
|
|
160
|
+
file=sys.stderr,
|
|
161
|
+
)
|
|
162
|
+
try:
|
|
163
|
+
result = subprocess.run(
|
|
164
|
+
[npm_bin, "install", "-g", NPM_PACKAGE],
|
|
165
|
+
timeout=120,
|
|
166
|
+
)
|
|
167
|
+
if result.returncode != 0:
|
|
168
|
+
raise RuntimeInstallError(
|
|
169
|
+
f"Failed to install {NPM_PACKAGE} via npm (exit code {result.returncode}).\n"
|
|
170
|
+
"Try running manually: npm install -g miladyai"
|
|
171
|
+
)
|
|
172
|
+
print("milady: milady runtime installed successfully.", file=sys.stderr)
|
|
173
|
+
except subprocess.TimeoutExpired:
|
|
174
|
+
raise RuntimeInstallError(
|
|
175
|
+
f"Timed out installing {NPM_PACKAGE}. Check your network connection."
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
# ── Public API ───────────────────────────────────────────────────────────────
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def ensure_runtime() -> str:
|
|
183
|
+
"""
|
|
184
|
+
Ensure the Milady Node.js runtime is available.
|
|
185
|
+
|
|
186
|
+
Checks for Node.js, then checks for the milady npm package.
|
|
187
|
+
Installs milady globally if not found.
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
Path to the milady CLI binary or npx fallback.
|
|
191
|
+
|
|
192
|
+
Raises:
|
|
193
|
+
NodeNotFoundError: If Node.js is not installed or too old.
|
|
194
|
+
RuntimeInstallError: If milady cannot be installed.
|
|
195
|
+
"""
|
|
196
|
+
_check_node()
|
|
197
|
+
|
|
198
|
+
milady_bin = _find_milady_bin()
|
|
199
|
+
if milady_bin:
|
|
200
|
+
return milady_bin
|
|
201
|
+
|
|
202
|
+
# Not found on PATH — try installing globally
|
|
203
|
+
_install_milady_global()
|
|
204
|
+
|
|
205
|
+
milady_bin = _find_milady_bin()
|
|
206
|
+
if not milady_bin:
|
|
207
|
+
# Fall back to npx
|
|
208
|
+
npx_bin = _find_npx()
|
|
209
|
+
if npx_bin:
|
|
210
|
+
return npx_bin
|
|
211
|
+
raise RuntimeInstallError(
|
|
212
|
+
"milady was installed but the binary was not found on PATH.\n"
|
|
213
|
+
"Try: export PATH=\"$(npm config get prefix)/bin:$PATH\""
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
return milady_bin
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def run(args: Optional[Sequence[str]] = None) -> int:
|
|
220
|
+
"""
|
|
221
|
+
Run a milady CLI command.
|
|
222
|
+
|
|
223
|
+
Args:
|
|
224
|
+
args: CLI arguments to pass to milady (e.g. ["start", "--verbose"]).
|
|
225
|
+
If None, defaults to empty list.
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
The exit code from the milady process.
|
|
229
|
+
|
|
230
|
+
Raises:
|
|
231
|
+
MiladyError: If the runtime cannot be found or started.
|
|
232
|
+
"""
|
|
233
|
+
if args is None:
|
|
234
|
+
args = []
|
|
235
|
+
|
|
236
|
+
bin_path = ensure_runtime()
|
|
237
|
+
|
|
238
|
+
# If we got npx back (fallback), run via npx
|
|
239
|
+
if os.path.basename(bin_path) == "npx":
|
|
240
|
+
cmd = [bin_path, NPM_PACKAGE, *list(args)]
|
|
241
|
+
else:
|
|
242
|
+
cmd = [bin_path, *list(args)]
|
|
243
|
+
|
|
244
|
+
try:
|
|
245
|
+
result = subprocess.run(cmd)
|
|
246
|
+
return result.returncode
|
|
247
|
+
except FileNotFoundError:
|
|
248
|
+
raise MiladyError(f"Could not execute: {bin_path}")
|
|
249
|
+
except OSError as exc:
|
|
250
|
+
raise MiladyError(f"Failed to run milady: {exc}")
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def get_version() -> Optional[str]:
|
|
254
|
+
"""
|
|
255
|
+
Get the installed milady version.
|
|
256
|
+
|
|
257
|
+
Returns:
|
|
258
|
+
Version string (e.g. "2.0.0-alpha.7") or None if not installed.
|
|
259
|
+
"""
|
|
260
|
+
milady_bin = _find_milady_bin()
|
|
261
|
+
if not milady_bin:
|
|
262
|
+
return None
|
|
263
|
+
|
|
264
|
+
try:
|
|
265
|
+
result = subprocess.run(
|
|
266
|
+
[milady_bin, "--version"],
|
|
267
|
+
capture_output=True,
|
|
268
|
+
text=True,
|
|
269
|
+
timeout=10,
|
|
270
|
+
)
|
|
271
|
+
if result.returncode == 0:
|
|
272
|
+
return result.stdout.strip().split("\n")[-1]
|
|
273
|
+
except (subprocess.SubprocessError, OSError):
|
|
274
|
+
pass
|
|
275
|
+
return None
|
|
File without changes
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "milady"
|
|
7
|
+
version = "2.0.0a93"
|
|
8
|
+
description = "Dynamic loader for Milady — personal AI assistant built on elizaOS"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "milady-ai", email = "dev@milady.ai" },
|
|
14
|
+
]
|
|
15
|
+
keywords = [
|
|
16
|
+
"ai",
|
|
17
|
+
"assistant",
|
|
18
|
+
"agent",
|
|
19
|
+
"elizaos",
|
|
20
|
+
"milady",
|
|
21
|
+
"milady",
|
|
22
|
+
"llm",
|
|
23
|
+
"cli",
|
|
24
|
+
]
|
|
25
|
+
classifiers = [
|
|
26
|
+
"Development Status :: 3 - Alpha",
|
|
27
|
+
"Environment :: Console",
|
|
28
|
+
"Intended Audience :: Developers",
|
|
29
|
+
"Intended Audience :: End Users/Desktop",
|
|
30
|
+
"License :: OSI Approved :: MIT License",
|
|
31
|
+
"Operating System :: MacOS",
|
|
32
|
+
"Operating System :: POSIX :: Linux",
|
|
33
|
+
"Operating System :: Microsoft :: Windows",
|
|
34
|
+
"Programming Language :: Python :: 3",
|
|
35
|
+
"Programming Language :: Python :: 3.9",
|
|
36
|
+
"Programming Language :: Python :: 3.10",
|
|
37
|
+
"Programming Language :: Python :: 3.11",
|
|
38
|
+
"Programming Language :: Python :: 3.12",
|
|
39
|
+
"Programming Language :: Python :: 3.13",
|
|
40
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
41
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
42
|
+
"Typing :: Typed",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
[project.urls]
|
|
46
|
+
Homepage = "https://milady.ai"
|
|
47
|
+
Repository = "https://github.com/milady-ai/milady"
|
|
48
|
+
Documentation = "https://docs.milady.ai"
|
|
49
|
+
Issues = "https://github.com/milady-ai/milady/issues"
|
|
50
|
+
|
|
51
|
+
[project.scripts]
|
|
52
|
+
milady = "milady.cli:main"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
[tool.hatch.build.targets.wheel]
|
|
56
|
+
packages = ["milady"]
|