msdev 0.10.0__tar.gz → 0.11.0__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.
- {msdev-0.10.0 → msdev-0.11.0}/PKG-INFO +93 -122
- msdev-0.11.0/README.md +236 -0
- {msdev-0.10.0 → msdev-0.11.0}/pyproject.toml +2 -1
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/__init__.py +1 -1
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/cli.py +213 -498
- msdev-0.11.0/src/msdev/core/__init__.py +1 -0
- msdev-0.11.0/src/msdev/core/compat.py +222 -0
- msdev-0.11.0/src/msdev/core/config.py +373 -0
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/container_helper.py +13 -6
- msdev-0.11.0/src/msdev/core/env_transfer.py +398 -0
- msdev-0.11.0/src/msdev/core/exec_argv.py +82 -0
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/host_mutations.py +1 -1
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/limits.py +2 -2
- msdev-0.11.0/src/msdev/core/local_rpc.py +85 -0
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/resources.py +4 -2
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/services/__init__.py +10 -22
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/services/capabilities.py +3 -23
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/services/context.py +0 -2
- msdev-0.11.0/src/msdev/core/services/environment.py +331 -0
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/services/execution.py +8 -0
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/services/node.py +2 -0
- msdev-0.11.0/src/msdev/core/ssh_auth.py +395 -0
- msdev-0.11.0/src/msdev/core/ssh_tunnel.py +558 -0
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/stream_server.py +14 -4
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/stream_transport.py +32 -15
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/transport.py +366 -90
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/daemon.py +116 -177
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev.egg-info/PKG-INFO +93 -122
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev.egg-info/SOURCES.txt +15 -13
- {msdev-0.10.0 → msdev-0.11.0}/tests/test_cli.py +26 -303
- {msdev-0.10.0 → msdev-0.11.0}/tests/test_cli_only_architecture.py +4 -7
- msdev-0.11.0/tests/test_compat.py +64 -0
- {msdev-0.10.0 → msdev-0.11.0}/tests/test_config.py +82 -1
- {msdev-0.10.0 → msdev-0.11.0}/tests/test_daemon.py +100 -59
- {msdev-0.10.0 → msdev-0.11.0}/tests/test_daemon_container_stream.py +1 -0
- {msdev-0.10.0 → msdev-0.11.0}/tests/test_docker_stream_dispatch.py +7 -2
- msdev-0.11.0/tests/test_env_put_get_scenario.py +134 -0
- msdev-0.11.0/tests/test_env_read_write_scenario.py +134 -0
- msdev-0.11.0/tests/test_env_transfer.py +88 -0
- msdev-0.11.0/tests/test_exec_argv.py +55 -0
- msdev-0.11.0/tests/test_exec_default_timeout_scenario.py +134 -0
- {msdev-0.10.0 → msdev-0.11.0}/tests/test_model_services.py +0 -2
- {msdev-0.10.0 → msdev-0.11.0}/tests/test_msdev_cli_skill.py +9 -9
- {msdev-0.10.0 → msdev-0.11.0}/tests/test_multiplex.py +12 -3
- msdev-0.11.0/tests/test_node_env_services.py +187 -0
- {msdev-0.10.0 → msdev-0.11.0}/tests/test_request_client.py +10 -4
- msdev-0.11.0/tests/test_ssh_auth.py +515 -0
- msdev-0.11.0/tests/test_ssh_tunnel.py +57 -0
- {msdev-0.10.0 → msdev-0.11.0}/tests/test_stream_server.py +10 -3
- {msdev-0.10.0 → msdev-0.11.0}/tests/test_stream_transport.py +9 -4
- {msdev-0.10.0 → msdev-0.11.0}/tests/test_target_exec_services.py +73 -4
- {msdev-0.10.0 → msdev-0.11.0}/tests/test_transport.py +212 -17
- msdev-0.11.0/tests/test_windows_local_scenario.py +124 -0
- msdev-0.10.0/README.md +0 -266
- msdev-0.10.0/src/msdev/core/__init__.py +0 -1
- msdev-0.10.0/src/msdev/core/config.py +0 -193
- msdev-0.10.0/src/msdev/core/services/environment.py +0 -84
- msdev-0.10.0/src/msdev/core/services/workspace.py +0 -567
- msdev-0.10.0/src/msdev/core/workspace/__init__.py +0 -43
- msdev-0.10.0/src/msdev/core/workspace/access.py +0 -1216
- msdev-0.10.0/src/msdev/core/workspace/client.py +0 -329
- msdev-0.10.0/src/msdev/core/workspace/paths.py +0 -65
- msdev-0.10.0/src/msdev/core/workspace/registry.py +0 -189
- msdev-0.10.0/src/msdev/session/__init__.py +0 -13
- msdev-0.10.0/src/msdev/session/export.py +0 -190
- msdev-0.10.0/src/msdev/session/log.py +0 -269
- msdev-0.10.0/tests/test_cli_session.py +0 -202
- msdev-0.10.0/tests/test_node_env_services.py +0 -63
- msdev-0.10.0/tests/test_workspace.py +0 -855
- msdev-0.10.0/tests/test_workspace_client.py +0 -321
- msdev-0.10.0/tests/test_workspace_services.py +0 -414
- {msdev-0.10.0 → msdev-0.11.0}/LICENSE +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/setup.cfg +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/guides.py +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/helper_deploy.py +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/host_files.py +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/inventory.py +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/multiplex.py +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/request_client.py +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/services/model.py +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/services/npu.py +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/services/results.py +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/stream_limits.py +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev/core/streamproto.py +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev.egg-info/dependency_links.txt +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev.egg-info/entry_points.txt +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/src/msdev.egg-info/top_level.txt +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/tests/test_container_helper.py +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/tests/test_helper_deploy.py +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/tests/test_inventory.py +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/tests/test_model_cli.py +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/tests/test_node_env_config.py +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/tests/test_streamproto.py +0 -0
- {msdev-0.10.0 → msdev-0.11.0}/tests/test_target_guides.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: msdev
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.11.0
|
|
4
4
|
Summary: Portable nodes and execution environments for msModelSlim development
|
|
5
5
|
Author: msModelSlim Agent Contributors
|
|
6
6
|
License-Expression: MulanPSL-2.0
|
|
@@ -15,6 +15,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.13
|
|
17
17
|
Classifier: Operating System :: MacOS
|
|
18
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
18
19
|
Classifier: Operating System :: POSIX :: Linux
|
|
19
20
|
Classifier: Topic :: Software Development :: Build Tools
|
|
20
21
|
Requires-Python: >=3.10
|
|
@@ -32,7 +33,6 @@ The CLI is intentionally stateless:
|
|
|
32
33
|
|
|
33
34
|
- Node-scoped NPU/model operations name `--node` or use `--all`;
|
|
34
35
|
- execution names `--env`;
|
|
35
|
-
- every workspace operation names the registered workspace;
|
|
36
36
|
- no harness conversation binding or implicit current Env exists;
|
|
37
37
|
- MCP is not part of the architecture.
|
|
38
38
|
|
|
@@ -47,6 +47,40 @@ msdev --help
|
|
|
47
47
|
|
|
48
48
|
The package installs `msdev` and `msdevd`.
|
|
49
49
|
|
|
50
|
+
## Windows client
|
|
51
|
+
|
|
52
|
+
The typical setup is a **Windows laptop talking to Linux Nodes** via OpenSSH
|
|
53
|
+
(`C:\Windows\System32\OpenSSH\ssh.exe`). Native Windows OpenSSH does not
|
|
54
|
+
implement ControlMaster multiplexing, so msdev:
|
|
55
|
+
|
|
56
|
+
- omits `ControlMaster`/`ControlPath` on Windows (override with
|
|
57
|
+
`MSDEV_SSH_CONTROL_MASTER=1` only if your SSH client actually supports mux);
|
|
58
|
+
- starts a persistent `ssh -L` LocalForward tunnel automatically on the first
|
|
59
|
+
RPC (same role as ControlMaster). Explicit `msdev node connect NODE` is
|
|
60
|
+
optional; disable persist with `MSDEV_SSH_LOCAL_FORWARD_PERSIST=0`;
|
|
61
|
+
- reuses that tunnel for captured RPC and default streaming `msdev exec`;
|
|
62
|
+
`env put`/`get` stay on scp/ssh streams (file bytes do not go through JSON RPC);
|
|
63
|
+
- hides SSH console windows (`CREATE_NO_WINDOW`) and kills process trees with
|
|
64
|
+
`taskkill /T` on timeout or cancel;
|
|
65
|
+
- SSH is non-interactive: `BatchMode` unless a password is supplied, host keys
|
|
66
|
+
use `accept-new`, and there is no password/passphrase/yes-no prompt. When a
|
|
67
|
+
password is known, injects OpenSSH `SSH_ASKPASS` so `node connect` (and later
|
|
68
|
+
ssh/scp) can authenticate without a TTY; the local public key is then
|
|
69
|
+
installed on the Node so later logins are passwordless. The password is
|
|
70
|
+
never written to the node registry;
|
|
71
|
+
- serves a TCP loopback endpoint for local `msdevd` when this Python build has
|
|
72
|
+
no `AF_UNIX` sockets.
|
|
73
|
+
|
|
74
|
+
Install with `python -m pip install -e .`. `install-user.py` writes
|
|
75
|
+
`msdev.cmd` / `msdevd.cmd` under `%USERPROFILE%\.local\bin`.
|
|
76
|
+
|
|
77
|
+
Remote paths inside a Linux Env remain POSIX (`/srv/...`). Local `env put`/`get`
|
|
78
|
+
on Windows accept Windows absolute paths (`C:\...`).
|
|
79
|
+
|
|
80
|
+
Local `exec` on Windows wraps Conda with `conda run` and venvs with
|
|
81
|
+
`Scripts\activate.bat` (remote Linux Nodes still use POSIX `sh`/`bash` wrappers).
|
|
82
|
+
If `ssh` is not on PATH, msdev looks in `%SystemRoot%\System32\OpenSSH\`.
|
|
83
|
+
|
|
50
84
|
## Nodes and execution environments
|
|
51
85
|
|
|
52
86
|
Register a host from `~/.ssh/config`:
|
|
@@ -64,10 +98,23 @@ the remote user daemon:
|
|
|
64
98
|
msdev node bootstrap dev-122
|
|
65
99
|
```
|
|
66
100
|
|
|
67
|
-
Persistent OpenSSH masters are optional
|
|
101
|
+
Persistent OpenSSH masters are optional. All SSH from msdev is
|
|
102
|
+
non-interactive: host keys use `accept-new`, and password/passphrase prompts
|
|
103
|
+
are disabled. Supply a password via environment or file (never a prompt);
|
|
104
|
+
connect then installs the local public key (`~/.ssh/id_ed25519`, generated
|
|
105
|
+
if missing) so later connections are passwordless:
|
|
68
106
|
|
|
69
107
|
```bash
|
|
108
|
+
# Environment (also used by exec / env put after connect if persist is off)
|
|
109
|
+
export MSDEV_SSH_PASSWORD='...'
|
|
110
|
+
export MSDEV_SSH_PASSWORD_DEV_122='...' # per-node override
|
|
111
|
+
|
|
70
112
|
msdev node connect dev-122
|
|
113
|
+
msdev node connect dev-122 --password-file FILE
|
|
114
|
+
msdev node connect dev-122 --password-env VAR
|
|
115
|
+
msdev node connect dev-122 --password PASSWORD # non-interactive; visible in ps
|
|
116
|
+
msdev node connect dev-122 --identity FILE # choose which key to install
|
|
117
|
+
msdev node connect dev-122 --no-install-key # password only, do not copy key
|
|
71
118
|
msdev node disconnect dev-122
|
|
72
119
|
```
|
|
73
120
|
|
|
@@ -107,6 +154,33 @@ msdev env add dev-122-vllm \
|
|
|
107
154
|
--layer venv:/srv/project/.venv
|
|
108
155
|
```
|
|
109
156
|
|
|
157
|
+
## File put, get, read, and write
|
|
158
|
+
|
|
159
|
+
Bulk transfer copies a local file into an Env filesystem, or fetches one back:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
msdev env put dev-122 ./config.yaml /srv/project/config.yaml
|
|
163
|
+
msdev env get dev-122 /srv/project/config.yaml --output ./config.yaml
|
|
164
|
+
msdev env get dev-122 /srv/project/config.yaml > ./config.yaml
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Editing uses content-oriented read/write. Paths inside the Env must be
|
|
168
|
+
absolute. Host Envs use direct filesystem copy locally and ``scp``/``ssh``
|
|
169
|
+
streams remotely. Docker Envs stage through the node with ``docker cp``.
|
|
170
|
+
File bytes never pass through JSON RPC.
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
msdev env read dev-122 /srv/project/config.yaml
|
|
174
|
+
msdev env read dev-122 /srv/project/config.yaml --json
|
|
175
|
+
msdev env write dev-122 /srv/project/note.md --file /tmp/note.md
|
|
176
|
+
msdev env write dev-122 /srv/project/note.md < /tmp/note.md
|
|
177
|
+
msdev env write dev-122 /srv/project/note.md --file /tmp/note.md \
|
|
178
|
+
--expected-sha256 <digest>
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Read before replacing an existing file. `--expected-sha256` is compare-and-swap
|
|
182
|
+
replacement that refuses to overwrite a changed remote file.
|
|
183
|
+
|
|
110
184
|
## NPU inventory
|
|
111
185
|
|
|
112
186
|
```bash
|
|
@@ -130,8 +204,15 @@ msdev exec \
|
|
|
130
204
|
-- python3 run.py
|
|
131
205
|
```
|
|
132
206
|
|
|
133
|
-
|
|
134
|
-
|
|
207
|
+
Quoted pipelines and `|` tokens are executed through a remote POSIX shell
|
|
208
|
+
(`sh -c`), so they run on the Node instead of being treated as a single
|
|
209
|
+
executable name. On a Windows `local` Env they use `cmd.exe /s /c`. Prefer
|
|
210
|
+
`sh -c '…'` for complex scripts. Default streaming writes POSIX newlines as
|
|
211
|
+
CRLF on a Windows console so remote line output does not staircase; piped
|
|
212
|
+
CLI output keeps LF.
|
|
213
|
+
|
|
214
|
+
`--timeout-seconds` defaults to `-1` (no deadline). Any positive finite duration
|
|
215
|
+
is also accepted. A positive timeout kills the complete command
|
|
135
216
|
process group and returns exit code 124. Cancelling the local CLI closes the RPC
|
|
136
217
|
connection, causing `msdevd` to kill and reap the remote process group. Finite
|
|
137
218
|
SSH/Unix RPC deadlines include a short completion grace for output drain and
|
|
@@ -140,66 +221,6 @@ serialization.
|
|
|
140
221
|
`--result-json` selects captured, non-streaming execution and prints one
|
|
141
222
|
structured JSON result containing stdout and stderr.
|
|
142
223
|
|
|
143
|
-
## Remote workspaces
|
|
144
|
-
|
|
145
|
-
A workspace gives a stable name to an Env and filesystem root:
|
|
146
|
-
|
|
147
|
-
```bash
|
|
148
|
-
msdev workspace add project \
|
|
149
|
-
--env dev-122 \
|
|
150
|
-
--root /srv/project
|
|
151
|
-
|
|
152
|
-
msdev workspace list
|
|
153
|
-
msdev workspace inspect project
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
Workspace operations are file- and Git-oriented. There is no
|
|
157
|
-
`msdev workspace exec`; use `msdev exec --env ... --cwd ...` for commands.
|
|
158
|
-
|
|
159
|
-
### Read and inspect
|
|
160
|
-
|
|
161
|
-
```bash
|
|
162
|
-
msdev workspace stat project README.md
|
|
163
|
-
msdev workspace read project README.md
|
|
164
|
-
msdev workspace read project weights.bin --output /tmp/weights.bin
|
|
165
|
-
msdev workspace list project src --json
|
|
166
|
-
msdev workspace glob project '**/*.py' --json
|
|
167
|
-
msdev workspace search project 'TODO' src tests --json
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
### Write safely
|
|
171
|
-
|
|
172
|
-
For non-trivial content, use stdin or `--file` rather than shell-escaped
|
|
173
|
-
`--content`:
|
|
174
|
-
|
|
175
|
-
```bash
|
|
176
|
-
msdev workspace write project docs/note.md < /tmp/note.md
|
|
177
|
-
msdev workspace write project docs/note.md --file /tmp/note.md
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
Compare-and-swap replacement prevents overwriting a changed remote file:
|
|
181
|
-
|
|
182
|
-
```bash
|
|
183
|
-
msdev workspace apply-patch project docs/note.md \
|
|
184
|
-
--file /tmp/note.md \
|
|
185
|
-
--expected-sha256 <digest>
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
Delete an explicit remote file:
|
|
189
|
-
|
|
190
|
-
```bash
|
|
191
|
-
msdev workspace delete project docs/obsolete.md
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
### Git
|
|
195
|
-
|
|
196
|
-
```bash
|
|
197
|
-
msdev workspace git-status project --result-json
|
|
198
|
-
msdev workspace git-diff project --result-json -- --stat
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
Git diff rejects options that can write files or invoke external diff helpers.
|
|
202
|
-
|
|
203
224
|
## Model inventory
|
|
204
225
|
|
|
205
226
|
Examples:
|
|
@@ -216,59 +237,6 @@ msdev model audit --node dev-122
|
|
|
216
237
|
Use `msdev model --help` and the individual subcommand help for register,
|
|
217
238
|
update, replicas, refresh, verify, export, import, and rebind.
|
|
218
239
|
|
|
219
|
-
## Explicit CLI sessions and runbooks
|
|
220
|
-
|
|
221
|
-
Create a session before a reproducible workflow:
|
|
222
|
-
|
|
223
|
-
```bash
|
|
224
|
-
msdev session begin --name qwen3-quant --json
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
Pass the returned ID explicitly or set it in a persistent terminal:
|
|
228
|
-
|
|
229
|
-
```bash
|
|
230
|
-
export MSDEV_SESSION_ID=<session-id>
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
Intent metadata is global and must appear before the subcommand:
|
|
234
|
-
|
|
235
|
-
```bash
|
|
236
|
-
msdev \
|
|
237
|
-
--session-id <session-id> \
|
|
238
|
-
--intent-kind execution \
|
|
239
|
-
--intent-summary 'Run Qwen3 quantization' \
|
|
240
|
-
--intent-phase quantization \
|
|
241
|
-
--intent-step-id quant-1 \
|
|
242
|
-
exec --env dev-122 --timeout-seconds 1800 -- python3 quant.py
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
Intent kinds:
|
|
246
|
-
|
|
247
|
-
- `execution`: core reproduction step;
|
|
248
|
-
- `verification`: optional confirmation;
|
|
249
|
-
- `diagnostic`: troubleshooting, excluded from core steps;
|
|
250
|
-
- `exploration`: discovery, excluded from core steps.
|
|
251
|
-
|
|
252
|
-
Each invocation receives a unique `operation_id`. `session_id` groups CLI
|
|
253
|
-
operations only; it never supplies a Node, Env, or workspace default.
|
|
254
|
-
|
|
255
|
-
Logs are private JSONL files under:
|
|
256
|
-
|
|
257
|
-
```text
|
|
258
|
-
${XDG_STATE_HOME:-~/.local/state}/msdev/sessions/
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
They retain sanitized logical arguments, preview, explicit resource, intent,
|
|
262
|
-
exit code, and elapsed time. Command stdout/stderr and environment values are
|
|
263
|
-
not duplicated into logs.
|
|
264
|
-
|
|
265
|
-
```bash
|
|
266
|
-
msdev session list
|
|
267
|
-
msdev session export --session-id <session-id> --output runbook.md
|
|
268
|
-
msdev session export --latest --detail normal --output runbook.md
|
|
269
|
-
msdev session export --input /path/to/session.jsonl --detail full
|
|
270
|
-
```
|
|
271
|
-
|
|
272
240
|
## Architecture
|
|
273
241
|
|
|
274
242
|
```text
|
|
@@ -276,15 +244,18 @@ msdev CLI
|
|
|
276
244
|
-> typed core service
|
|
277
245
|
-> UnixRpcTransport or SshRpcTransport
|
|
278
246
|
-> per-user msdevd
|
|
279
|
-
-> host/container command,
|
|
247
|
+
-> host/container command, env file transfer, NPU, or inventory
|
|
280
248
|
```
|
|
281
249
|
|
|
282
|
-
Remote RPC responses and command output are bounded.
|
|
283
|
-
|
|
284
|
-
compare-and-swap. Node/Env and workspace registries use locked atomic updates.
|
|
250
|
+
Remote RPC responses and command output are bounded. Node/Env registries use
|
|
251
|
+
locked atomic updates.
|
|
285
252
|
|
|
286
253
|
## Testing
|
|
287
254
|
|
|
288
255
|
```bash
|
|
289
256
|
python3 -m unittest discover -s tests -v
|
|
290
257
|
```
|
|
258
|
+
|
|
259
|
+
Feature work must include at least one actual scenario test on the real
|
|
260
|
+
control path (`msdev` CLI → service → transport → `msdevd` → effect). Unit
|
|
261
|
+
tests alone are not sufficient.
|
msdev-0.11.0/README.md
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
# msdev
|
|
2
|
+
|
|
3
|
+
`msdev` manages connection Nodes and execution Envs. A Node owns SSH and its
|
|
4
|
+
per-user `msdevd`; an Env references a Node and adds a host/Docker runtime plus
|
|
5
|
+
optional conda/venv/uv layers.
|
|
6
|
+
|
|
7
|
+
The CLI is intentionally stateless:
|
|
8
|
+
|
|
9
|
+
- Node-scoped NPU/model operations name `--node` or use `--all`;
|
|
10
|
+
- execution names `--env`;
|
|
11
|
+
- no harness conversation binding or implicit current Env exists;
|
|
12
|
+
- MCP is not part of the architecture.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
git clone https://gitcode.com/rookie_hongchuan/msdev.git
|
|
18
|
+
cd msdev
|
|
19
|
+
python3 -m pip install -e .
|
|
20
|
+
msdev --help
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The package installs `msdev` and `msdevd`.
|
|
24
|
+
|
|
25
|
+
## Windows client
|
|
26
|
+
|
|
27
|
+
The typical setup is a **Windows laptop talking to Linux Nodes** via OpenSSH
|
|
28
|
+
(`C:\Windows\System32\OpenSSH\ssh.exe`). Native Windows OpenSSH does not
|
|
29
|
+
implement ControlMaster multiplexing, so msdev:
|
|
30
|
+
|
|
31
|
+
- omits `ControlMaster`/`ControlPath` on Windows (override with
|
|
32
|
+
`MSDEV_SSH_CONTROL_MASTER=1` only if your SSH client actually supports mux);
|
|
33
|
+
- starts a persistent `ssh -L` LocalForward tunnel automatically on the first
|
|
34
|
+
RPC (same role as ControlMaster). Explicit `msdev node connect NODE` is
|
|
35
|
+
optional; disable persist with `MSDEV_SSH_LOCAL_FORWARD_PERSIST=0`;
|
|
36
|
+
- reuses that tunnel for captured RPC and default streaming `msdev exec`;
|
|
37
|
+
`env put`/`get` stay on scp/ssh streams (file bytes do not go through JSON RPC);
|
|
38
|
+
- hides SSH console windows (`CREATE_NO_WINDOW`) and kills process trees with
|
|
39
|
+
`taskkill /T` on timeout or cancel;
|
|
40
|
+
- SSH is non-interactive: `BatchMode` unless a password is supplied, host keys
|
|
41
|
+
use `accept-new`, and there is no password/passphrase/yes-no prompt. When a
|
|
42
|
+
password is known, injects OpenSSH `SSH_ASKPASS` so `node connect` (and later
|
|
43
|
+
ssh/scp) can authenticate without a TTY; the local public key is then
|
|
44
|
+
installed on the Node so later logins are passwordless. The password is
|
|
45
|
+
never written to the node registry;
|
|
46
|
+
- serves a TCP loopback endpoint for local `msdevd` when this Python build has
|
|
47
|
+
no `AF_UNIX` sockets.
|
|
48
|
+
|
|
49
|
+
Install with `python -m pip install -e .`. `install-user.py` writes
|
|
50
|
+
`msdev.cmd` / `msdevd.cmd` under `%USERPROFILE%\.local\bin`.
|
|
51
|
+
|
|
52
|
+
Remote paths inside a Linux Env remain POSIX (`/srv/...`). Local `env put`/`get`
|
|
53
|
+
on Windows accept Windows absolute paths (`C:\...`).
|
|
54
|
+
|
|
55
|
+
Local `exec` on Windows wraps Conda with `conda run` and venvs with
|
|
56
|
+
`Scripts\activate.bat` (remote Linux Nodes still use POSIX `sh`/`bash` wrappers).
|
|
57
|
+
If `ssh` is not on PATH, msdev looks in `%SystemRoot%\System32\OpenSSH\`.
|
|
58
|
+
|
|
59
|
+
## Nodes and execution environments
|
|
60
|
+
|
|
61
|
+
Register a host from `~/.ssh/config`:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
msdev node add dev-122 --ssh-host dev-122
|
|
65
|
+
msdev node list
|
|
66
|
+
msdev node status dev-122
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Adding a Node atomically creates a same-named host Env. Bootstrap or refresh
|
|
70
|
+
the remote user daemon:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
msdev node bootstrap dev-122
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Persistent OpenSSH masters are optional. All SSH from msdev is
|
|
77
|
+
non-interactive: host keys use `accept-new`, and password/passphrase prompts
|
|
78
|
+
are disabled. Supply a password via environment or file (never a prompt);
|
|
79
|
+
connect then installs the local public key (`~/.ssh/id_ed25519`, generated
|
|
80
|
+
if missing) so later connections are passwordless:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Environment (also used by exec / env put after connect if persist is off)
|
|
84
|
+
export MSDEV_SSH_PASSWORD='...'
|
|
85
|
+
export MSDEV_SSH_PASSWORD_DEV_122='...' # per-node override
|
|
86
|
+
|
|
87
|
+
msdev node connect dev-122
|
|
88
|
+
msdev node connect dev-122 --password-file FILE
|
|
89
|
+
msdev node connect dev-122 --password-env VAR
|
|
90
|
+
msdev node connect dev-122 --password PASSWORD # non-interactive; visible in ps
|
|
91
|
+
msdev node connect dev-122 --identity FILE # choose which key to install
|
|
92
|
+
msdev node connect dev-122 --no-install-key # password only, do not copy key
|
|
93
|
+
msdev node disconnect dev-122
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Nodes and Envs have separate private Markdown guides:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
msdev node guide dev-122
|
|
100
|
+
msdev node guide dev-122 --write ./dev-122-guide.md
|
|
101
|
+
msdev env guide dev-122
|
|
102
|
+
msdev env guide dev-122 --write ./host-env-guide.md
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Guides are stored under `~/.config/msdev/guides/nodes/` and
|
|
106
|
+
`~/.config/msdev/guides/environments/`, with private permissions and a 256 KiB
|
|
107
|
+
limit. Agents read the applicable guides once before first use in a session.
|
|
108
|
+
|
|
109
|
+
Open a human-operated interactive shell in an Env:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
msdev env shell dev-122
|
|
113
|
+
msdev env shell dev-122 --cwd /srv/project
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
The command allocates an OpenSSH PTY and enters the Env's Docker runtime and
|
|
117
|
+
conda/venv/uv layers. Exiting returns
|
|
118
|
+
to the local shell. Only the shell session start and final status are visible
|
|
119
|
+
to msdev; commands typed inside it are not individually logged. Agent
|
|
120
|
+
automation should continue using `msdev exec`.
|
|
121
|
+
|
|
122
|
+
Create another Env on the same Node for Docker and Python layers:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
msdev env add dev-122-vllm \
|
|
126
|
+
--node dev-122 \
|
|
127
|
+
--docker-container vllm-ascend \
|
|
128
|
+
--layer conda:base \
|
|
129
|
+
--layer venv:/srv/project/.venv
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## File put, get, read, and write
|
|
133
|
+
|
|
134
|
+
Bulk transfer copies a local file into an Env filesystem, or fetches one back:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
msdev env put dev-122 ./config.yaml /srv/project/config.yaml
|
|
138
|
+
msdev env get dev-122 /srv/project/config.yaml --output ./config.yaml
|
|
139
|
+
msdev env get dev-122 /srv/project/config.yaml > ./config.yaml
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Editing uses content-oriented read/write. Paths inside the Env must be
|
|
143
|
+
absolute. Host Envs use direct filesystem copy locally and ``scp``/``ssh``
|
|
144
|
+
streams remotely. Docker Envs stage through the node with ``docker cp``.
|
|
145
|
+
File bytes never pass through JSON RPC.
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
msdev env read dev-122 /srv/project/config.yaml
|
|
149
|
+
msdev env read dev-122 /srv/project/config.yaml --json
|
|
150
|
+
msdev env write dev-122 /srv/project/note.md --file /tmp/note.md
|
|
151
|
+
msdev env write dev-122 /srv/project/note.md < /tmp/note.md
|
|
152
|
+
msdev env write dev-122 /srv/project/note.md --file /tmp/note.md \
|
|
153
|
+
--expected-sha256 <digest>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Read before replacing an existing file. `--expected-sha256` is compare-and-swap
|
|
157
|
+
replacement that refuses to overwrite a changed remote file.
|
|
158
|
+
|
|
159
|
+
## NPU inventory
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
msdev npu list --node dev-122 --json
|
|
163
|
+
msdev npu list --all --json
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Command execution
|
|
167
|
+
|
|
168
|
+
Commands execute synchronously and stream stdout and stderr to the terminal as
|
|
169
|
+
they are produced. Cursor or Claude Code should use their native background
|
|
170
|
+
terminal support for long jobs. Long jobs may also write a persistent progress
|
|
171
|
+
log when later inspection is required.
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
msdev exec \
|
|
175
|
+
--env dev-122 \
|
|
176
|
+
--cwd /srv/project \
|
|
177
|
+
--timeout-seconds 1800 \
|
|
178
|
+
--env-var MODE=test \
|
|
179
|
+
-- python3 run.py
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Quoted pipelines and `|` tokens are executed through a remote POSIX shell
|
|
183
|
+
(`sh -c`), so they run on the Node instead of being treated as a single
|
|
184
|
+
executable name. On a Windows `local` Env they use `cmd.exe /s /c`. Prefer
|
|
185
|
+
`sh -c '…'` for complex scripts. Default streaming writes POSIX newlines as
|
|
186
|
+
CRLF on a Windows console so remote line output does not staircase; piped
|
|
187
|
+
CLI output keeps LF.
|
|
188
|
+
|
|
189
|
+
`--timeout-seconds` defaults to `-1` (no deadline). Any positive finite duration
|
|
190
|
+
is also accepted. A positive timeout kills the complete command
|
|
191
|
+
process group and returns exit code 124. Cancelling the local CLI closes the RPC
|
|
192
|
+
connection, causing `msdevd` to kill and reap the remote process group. Finite
|
|
193
|
+
SSH/Unix RPC deadlines include a short completion grace for output drain and
|
|
194
|
+
serialization.
|
|
195
|
+
|
|
196
|
+
`--result-json` selects captured, non-streaming execution and prints one
|
|
197
|
+
structured JSON result containing stdout and stderr.
|
|
198
|
+
|
|
199
|
+
## Model inventory
|
|
200
|
+
|
|
201
|
+
Examples:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
msdev model discover --node dev-122 --root /data/models
|
|
205
|
+
msdev model list --node dev-122 --json
|
|
206
|
+
msdev model list --all --json
|
|
207
|
+
msdev model inspect model://qwen/Qwen3-32B@main --node dev-122
|
|
208
|
+
msdev model validate model://qwen/Qwen3-32B@main --node dev-122
|
|
209
|
+
msdev model audit --node dev-122
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Use `msdev model --help` and the individual subcommand help for register,
|
|
213
|
+
update, replicas, refresh, verify, export, import, and rebind.
|
|
214
|
+
|
|
215
|
+
## Architecture
|
|
216
|
+
|
|
217
|
+
```text
|
|
218
|
+
msdev CLI
|
|
219
|
+
-> typed core service
|
|
220
|
+
-> UnixRpcTransport or SshRpcTransport
|
|
221
|
+
-> per-user msdevd
|
|
222
|
+
-> host/container command, env file transfer, NPU, or inventory
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Remote RPC responses and command output are bounded. Node/Env registries use
|
|
226
|
+
locked atomic updates.
|
|
227
|
+
|
|
228
|
+
## Testing
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
python3 -m unittest discover -s tests -v
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Feature work must include at least one actual scenario test on the real
|
|
235
|
+
control path (`msdev` CLI → service → transport → `msdevd` → effect). Unit
|
|
236
|
+
tests alone are not sufficient.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "msdev"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.11.0"
|
|
8
8
|
description = "Portable nodes and execution environments for msModelSlim development"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -23,6 +23,7 @@ classifiers = [
|
|
|
23
23
|
"Programming Language :: Python :: 3.12",
|
|
24
24
|
"Programming Language :: Python :: 3.13",
|
|
25
25
|
"Operating System :: MacOS",
|
|
26
|
+
"Operating System :: Microsoft :: Windows",
|
|
26
27
|
"Operating System :: POSIX :: Linux",
|
|
27
28
|
"Topic :: Software Development :: Build Tools",
|
|
28
29
|
]
|