solidx-sysadm 0.1.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.
Files changed (44) hide show
  1. solidx_sysadm-0.1.0/LICENSE +21 -0
  2. solidx_sysadm-0.1.0/PKG-INFO +356 -0
  3. solidx_sysadm-0.1.0/README.md +336 -0
  4. solidx_sysadm-0.1.0/pyproject.toml +25 -0
  5. solidx_sysadm-0.1.0/setup.cfg +4 -0
  6. solidx_sysadm-0.1.0/src/bash_minus_minus/__init__.py +17 -0
  7. solidx_sysadm-0.1.0/src/bash_minus_minus/__main__.py +3 -0
  8. solidx_sysadm-0.1.0/src/bash_minus_minus/cli.py +124 -0
  9. solidx_sysadm-0.1.0/src/bash_minus_minus/command_forms.py +140 -0
  10. solidx_sysadm-0.1.0/src/bash_minus_minus/policy.py +103 -0
  11. solidx_sysadm-0.1.0/src/bash_minus_minus/remote_policy.py +430 -0
  12. solidx_sysadm-0.1.0/src/bash_minus_minus/runner.py +181 -0
  13. solidx_sysadm-0.1.0/src/bash_minus_minus/session.py +97 -0
  14. solidx_sysadm-0.1.0/src/bash_minus_minus/suggestions.py +63 -0
  15. solidx_sysadm-0.1.0/src/bash_minus_minus/workflows.py +174 -0
  16. solidx_sysadm-0.1.0/src/solidx_sysadm.egg-info/PKG-INFO +356 -0
  17. solidx_sysadm-0.1.0/src/solidx_sysadm.egg-info/SOURCES.txt +42 -0
  18. solidx_sysadm-0.1.0/src/solidx_sysadm.egg-info/dependency_links.txt +1 -0
  19. solidx_sysadm-0.1.0/src/solidx_sysadm.egg-info/entry_points.txt +2 -0
  20. solidx_sysadm-0.1.0/src/solidx_sysadm.egg-info/requires.txt +8 -0
  21. solidx_sysadm-0.1.0/src/solidx_sysadm.egg-info/top_level.txt +2 -0
  22. solidx_sysadm-0.1.0/src/sysadm/__init__.py +15 -0
  23. solidx_sysadm-0.1.0/src/sysadm/__main__.py +3 -0
  24. solidx_sysadm-0.1.0/src/sysadm/agent.py +533 -0
  25. solidx_sysadm-0.1.0/src/sysadm/choices.py +45 -0
  26. solidx_sysadm-0.1.0/src/sysadm/cli.py +222 -0
  27. solidx_sysadm-0.1.0/src/sysadm/config.py +217 -0
  28. solidx_sysadm-0.1.0/src/sysadm/events.py +43 -0
  29. solidx_sysadm-0.1.0/src/sysadm/extensions.py +222 -0
  30. solidx_sysadm-0.1.0/src/sysadm/models.py +175 -0
  31. solidx_sysadm-0.1.0/src/sysadm/resources/skills/system-inspection/SKILL.md +26 -0
  32. solidx_sysadm-0.1.0/src/sysadm/resources/system_prompt.md +40 -0
  33. solidx_sysadm-0.1.0/src/sysadm/security.py +86 -0
  34. solidx_sysadm-0.1.0/src/sysadm/storage.py +80 -0
  35. solidx_sysadm-0.1.0/src/sysadm/tools.py +236 -0
  36. solidx_sysadm-0.1.0/src/sysadm/tui.py +789 -0
  37. solidx_sysadm-0.1.0/src/sysadm/ui.py +451 -0
  38. solidx_sysadm-0.1.0/src/sysadm/workflows_compat.py +10 -0
  39. solidx_sysadm-0.1.0/tests/test_file_commands.py +76 -0
  40. solidx_sysadm-0.1.0/tests/test_macos_execution.py +80 -0
  41. solidx_sysadm-0.1.0/tests/test_policy.py +53 -0
  42. solidx_sysadm-0.1.0/tests/test_remote_policy.py +197 -0
  43. solidx_sysadm-0.1.0/tests/test_session_workflows.py +216 -0
  44. solidx_sysadm-0.1.0/tests/test_sysadm_harness.py +470 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 bash-- contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,356 @@
1
+ Metadata-Version: 2.4
2
+ Name: solidx-sysadm
3
+ Version: 0.1.0
4
+ Summary: An embeddable macOS and Linux system administration agent harness
5
+ License: MIT
6
+ Classifier: Operating System :: POSIX :: Linux
7
+ Classifier: Operating System :: MacOS :: MacOS X
8
+ Classifier: Programming Language :: Python :: 3
9
+ Requires-Python: >=3.11
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: mini-swe-agent<2.5,>=2.4.6
13
+ Requires-Dist: litellm[mcp]==1.106.0
14
+ Requires-Dist: jsonschema<5,>=4.20
15
+ Requires-Dist: rich<15,>=13.7
16
+ Requires-Dist: textual<2,>=0.80
17
+ Provides-Extra: test
18
+ Requires-Dist: pytest<10,>=8; extra == "test"
19
+ Dynamic: license-file
20
+
21
+ # sysadm
22
+
23
+ A macOS and Linux system-administration agent harness. The main interface is a
24
+ full-screen, streaming terminal UI (TUI) with a conversation log, live status,
25
+ and a persistent input bar. The CLI manages configuration and extensions.
26
+
27
+ The harness uses **mini-swe-agent** for the query/action lifecycle and
28
+ **LiteLLM** for model requests. The reviewed command gateway is exposed through
29
+ the built-in bash tool.
30
+
31
+ ## Try the actual harness without a model key
32
+
33
+ Dependencies are installed in this checkout's .venv. From this directory:
34
+
35
+ ~~~console
36
+ ./sysadm --demo
37
+ ~~~
38
+
39
+ Enter a message, answer the confirmation, then report a result or type skip.
40
+ This explicitly labelled offline demo uses the real mini-swe-agent loop, gateway,
41
+ event stream, human gates, and checkpoints with a scripted model adapter.
42
+ It does not call a paid model API. Its example directory-creation command is
43
+ displayed only; the demo never executes it.
44
+
45
+ For a fresh installation:
46
+
47
+ ~~~console
48
+ python3 -m venv .venv
49
+ .venv/bin/python -m pip install -e .
50
+ .venv/bin/sysadm --version
51
+ ~~~
52
+
53
+ The tag-based GitHub Actions release SOP is in [docs/RELEASE.md](docs/RELEASE.md).
54
+ The isolated install procedure for a remote Linux machine is in
55
+ [the first-run guide](docs/releasing.md).
56
+
57
+ The installed executable is **sysadm**, replacing the generated bash-- entrypoint.
58
+ The source launcher automatically uses this checkout's .venv when available.
59
+ Python 3.11+ is required. Native inspection runs on macOS and Linux.
60
+
61
+ ## Configure models
62
+
63
+ ~~~console
64
+ ./sysadm --configure
65
+ ~~~
66
+
67
+ The wizard asks for main and fast models, provider IDs, streaming behavior,
68
+ provider endpoints, and API key environment variable names. You can instead
69
+ import a complete JSON configuration with `--configure --config-file PATH`.
70
+
71
+ A noninteractive example, replacing the model IDs with models available to you:
72
+
73
+ ~~~console
74
+ ./sysadm --configure \
75
+ --fast-model openai/YOUR_FAST_MODEL \
76
+ --fast-key-env SYSADM_FAST_API_KEY \
77
+ --main-model openai/YOUR_MAIN_MODEL \
78
+ --main-key-env SYSADM_MAIN_API_KEY
79
+ ~~~
80
+
81
+ Set those environment variables in your terminal before starting the agent.
82
+ The configuration stores model profiles separately from reusable providers:
83
+
84
+ ~~~json
85
+ {
86
+ "schema_version": 2,
87
+ "models": {
88
+ "main": {"providerId": "openrouter", "model": "openai/gpt-6-luna", "behavior": {"streaming": false}},
89
+ "fast": {"providerId": "openrouter", "model": "openai/gpt-6-luna", "behavior": {"streaming": false}}
90
+ },
91
+ "providers": {
92
+ "openrouter": {
93
+ "type": "openai-compatible",
94
+ "apiKeyEnv": "OPENROUTER_API_KEY",
95
+ "baseUrl": "https://openrouter.ai/api/v1"
96
+ }
97
+ }
98
+ }
99
+ ~~~
100
+
101
+ The [OpenRouter API reference](https://openrouter.ai/docs/api/api-reference/chat/send-chat-completion-request)
102
+ confirms that base URL. You may use `apiKey` instead of `apiKeyEnv` to store the
103
+ key inline; `config.json` is private (mode 0600), and `--show-config` redacts it.
104
+ An environment variable keeps the value out of the config file. Remote base URLs
105
+ require HTTPS, while loopback HTTP is allowed. `streaming: false` returns one
106
+ answer event after inference; `true` emits text as it arrives. Both modes retain
107
+ tool and human-interaction events in the TUI or line-oriented REPL.
108
+ OpenAI-compatible providers use
109
+ LiteLLM's `openai/` adapter internally while sending the configured model ID
110
+ unchanged to the provider. The older schema is migrated automatically.
111
+
112
+ ~~~console
113
+ ./sysadm --show-config
114
+ ./sysadm --configure --config-file examples/sysadm-openrouter-env.json
115
+ ~~~
116
+
117
+ The environment example references `SYSADM_REASONING_API_KEY`, as used in the
118
+ earlier setup. [The inline-key example](examples/sysadm-config.json) demonstrates
119
+ the `apiKey` field with a placeholder; replace that placeholder before importing.
120
+ The main profile is the default. The fast profile is available as a
121
+ consult_fast_model tool with no tool access of its own. You may explicitly switch
122
+ the main session to fast with /model fast.
123
+
124
+ ## Work in the terminal UI
125
+
126
+ ~~~console
127
+ ./sysadm
128
+ ~~~
129
+
130
+ Ask a normal question, such as “Inspect this machine and tell me which diagnostics
131
+ would help investigate low disk space.”
132
+
133
+ The TUI renders streamed answers, reviewed commands and their output, approval
134
+ cards, and status in a scrollable conversation. Approval replies go through the
135
+ same input bar. When a separately approved command needs sudo, sysadm suspends
136
+ the full-screen interface so sudo can securely read its password from the
137
+ controlling terminal, then restores the TUI when the operation and agent turn
138
+ finish.
139
+
140
+ Use `--plain` for the line-oriented REPL, or `--json` for NDJSON events. Both
141
+ remain available for scripts, redirected terminals, and troubleshooting.
142
+
143
+ | TUI control | Purpose |
144
+ | --- | --- |
145
+ | /help | Show controls. |
146
+ | /model fast or /model main | Select this session's model profile. |
147
+ | /skills, /tools | Inspect extension catalogs. |
148
+ | /commands | Show globally approved command forms. |
149
+ | /trust-paths | List saved executable-path trust approvals. |
150
+ | /untrust-path ID | Revoke a saved executable-path trust approval. |
151
+ | /status, /sessions | Inspect local session state. |
152
+ | /new, /resume UUID | Start or resume a conversation. |
153
+ | /cd PATH | Change this session's working directory without changing the host process directory. |
154
+ | /exec COMMAND | Run a globally or locally approved command directly. |
155
+ | /check COMMAND | Classify a command without executing it. |
156
+ | /answer REQUEST_ID TEXT | Answer a specific pending question. |
157
+ | /history, /history clear | Review or erase local prompt history. |
158
+ | /copy | Copy the most recently shown command to the clipboard. |
159
+ | /cancel | Cancel pending and queued work. |
160
+ | /exit | Leave; pending work stays resumable. |
161
+
162
+ Normal text answers the current pending request when the agent is paused.
163
+ Confirmations require an explicit yes/no response. The TUI saves up to 500
164
+ recent prompts in the private `input-history.json` file under the sysadm home
165
+ directory. Use Up/Down to browse, Ctrl+R to search, `/history clear` to clear
166
+ saved entries, or `--no-history` to keep entries in memory only. Approval replies,
167
+ `/exec` commands, and `/answer` payloads are excluded. EOF leaves a parked
168
+ session on disk; Ctrl+C requests cancellation. Sanitized conversation history
169
+ and events are stored as described below.
170
+
171
+ While an approval is open, use Y/N to approve or deny, O to approve this run,
172
+ and R to remember an executable directory when that option is offered. Choices
173
+ are case-insensitive. Press C to copy the command shown in the request; `/copy`
174
+ copies the most recently shown command.
175
+ For questions with a list of choices, each option is shown on its own line with
176
+ a unique key; pressing that key submits the complete matching option.
177
+
178
+ There is no task-execution CLI mode: positional prompts are rejected.
179
+ Work, inspection, and agent interactions happen inside the TUI, plain REPL, or
180
+ SDK. Use --json for NDJSON harness events; UI control responses are separate
181
+ ui.notice records. Gateway options and commands are documented in
182
+ [the gateway reference](docs/gateway.md).
183
+
184
+ ## Local configuration and sessions
185
+
186
+ The existing SolidX naming convention is followed:
187
+
188
+ ~~~text
189
+ ~/.solidx/sysadm/
190
+ config.json
191
+ system_prompt.md
192
+ input-history.json # TUI prompt history unless --no-history is used
193
+ skills/<name>/SKILL.md
194
+ skill-drafts/<name>/SKILL.md
195
+ tools/<name>.json
196
+ policy/policy-state.json
197
+ policy/local-allowlist.json
198
+ sessions/<uuid>/
199
+ checkpoint.json
200
+ events.jsonl
201
+ turn.lock
202
+ ~~~
203
+
204
+ Override the directory with `--home PATH` or `SYSADM_HOME`.
205
+
206
+ Checkpoints include conversation messages, model role, counters/cost, working
207
+ directory, pending human request, and remaining tool calls. They are atomically
208
+ replaced. A turn lock prevents two processes from advancing the same session.
209
+ Interrupted running turns are closed out rather than automatically retrying tools.
210
+
211
+ ~~~console
212
+ ./sysadm --resume SESSION_UUID
213
+ ~~~
214
+
215
+ Configuration, checkpoints, and event files are created with private permissions.
216
+ Known model keys and recognizable credential fields are redacted at model/event/
217
+ persistence boundaries. Do not paste secrets into chat. Redaction is not a
218
+ general-purpose secret scanner, and conversation files remain sensitive.
219
+
220
+ State is local by default. Model requests send the conversation, active prompt,
221
+ skill catalog/loaded skills, and selected tool results to your configured provider.
222
+ Choose the provider and local retention settings accordingly.
223
+
224
+ ## Skills and tools
225
+
226
+ ~~~console
227
+ ./sysadm --add-skill examples/skills/local-diagnostics
228
+ ./sysadm --list-skills
229
+ ./sysadm --remove-skill local-diagnostics
230
+ ./sysadm --list-skill-drafts
231
+ ./sysadm --add-skill-draft deployment-estate
232
+
233
+ ./sysadm --add-tool examples/tools/read_head.json
234
+ ./sysadm --add-tool examples/tools/create_directory_instruction.json
235
+ ./sysadm --list-tools
236
+ ./sysadm --remove-tool read_head
237
+
238
+ ./sysadm --set-system-prompt /path/to/system_prompt.md
239
+ ~~~
240
+
241
+ Start a new session or restart sysadm to pick up configuration/extension changes.
242
+ Skills are Markdown procedures with optional local reference files. They are not
243
+ executed as code. The agent lists skill descriptions and loads a relevant body
244
+ on demand.
245
+
246
+ To author an operational knowledge skill, ask in the TUI or REPL for a
247
+ draft—for example,
248
+ “Create a deployment-estate skill from this conversation and the NGINX/PM2 files
249
+ we inspect; distinguish verified facts from assumptions.” The agent can inspect
250
+ local evidence through the existing command gateway, then `save_skill_draft`
251
+ writes a Markdown draft under `skill-drafts/`. Drafts are not loaded by the agent.
252
+ Review the file, edit it as needed, and explicitly install the reviewed draft with
253
+ `sysadm --add-skill-draft deployment-estate`. The installed copy appears under
254
+ `skills/` and can be packaged and shared with other developers using `--add-skill`.
255
+ The draft records evidence notes, but those notes are not independent verification;
256
+ review claims and remove sensitive details before installing or sharing.
257
+
258
+ Installed tools are validated **declarative manifests**:
259
+ - command tools bind scalar arguments into an argv template and go through the
260
+ same reviewed gateway as the built-in bash tool;
261
+ - instruction tools display a command for another terminal and park the session;
262
+ - optional confirmation gates can protect command tools.
263
+
264
+ Installing a skill or declarative tool does not import or execute plugin code.
265
+ Commands explicitly approved by the user can run scripts as executables. Reserved
266
+ built-in names cannot be replaced. A skill or tool manifest cannot approve a
267
+ command: the gateway still requires a global grant or the user's approval of one
268
+ exact invocation. See [extension contracts](docs/extensions.md).
269
+
270
+ ### Agent-requested commands
271
+
272
+ The agent can request any single executable invocation not already enabled by
273
+ global policy. The TUI or REPL shows the exact command and asks before saving
274
+ or running it. Local approval applies only to that exact executable and argument vector,
275
+ survives remote policy refreshes, and can be revoked. Explicit global denials
276
+ always win. The runner does not parse shell operators; if a compound command is
277
+ needed, the agent may request an explicit shell invocation such as `sh -c '...'`,
278
+ which makes the full script visible in the approval prompt. Review all arguments
279
+ carefully: an approved command can modify files or services, use elevated access,
280
+ or expose sensitive output.
281
+
282
+ For example, ask sysadm to investigate disk usage. It can run the globally
283
+ enabled `df -h` and `du` forms, then request `pm2 list` if needed. A different
284
+ argument vector requires a separate approval unless the global policy contains
285
+ a broader form.
286
+
287
+ Inspect or revoke local approvals with:
288
+
289
+ ~~~console
290
+ sysadm --list-local-commands
291
+ sysadm --remove-local-command APPROVAL_ID
292
+ sysadm --list-local-paths
293
+ sysadm --remove-local-path PATH_APPROVAL_ID
294
+ ~~~
295
+
296
+ Executable directory trust is separate from command approval. When a path check
297
+ fails, approve it for one run or choose `remember` to save that exact directory
298
+ for the current operating system. Review saved entries with `/trust-paths` or
299
+ `sysadm --list-local-paths`; revoke one with `sysadm --remove-local-path ID`.
300
+
301
+ Commands needing interactive input can still be presented for you to run in
302
+ another SSH terminal. The harness waits for your report and will not claim that
303
+ it ran them.
304
+
305
+ Built-in tools are bash, request_command_access, list_commands, list_skills,
306
+ load_skill, consult_fast_model, request_human_input, request_confirmation, and
307
+ instruct_user.
308
+
309
+ Limits cover session steps, steps per turn, active turn time, context size, model
310
+ response size, and tool-output size. Cost is tracked when LiteLLM can price the
311
+ model; unknown pricing is not treated as a reliable spend cap.
312
+ Model calls have timeouts and a bounded retry count. No model API call is made by
313
+ configuration, extension-management commands, or the offline demo.
314
+
315
+ This remains a policy gateway, **not an OS sandbox**. It trusts installed
316
+ utilities and their dependencies. Reads/diagnostics can have incidental cache,
317
+ audit, automount, and access-time effects. Cancellation is cooperative between
318
+ model chunks/steps and subject to child-process limits. See the gateway reference.
319
+
320
+ ## Embedding the harness
321
+
322
+ ~~~python
323
+ from sysadm import SysadmSession
324
+
325
+ session = SysadmSession() # ~/.solidx/sysadm
326
+ session.subscribe(lambda event: print(event.as_dict()))
327
+ session.run_turn("Inspect disk usage and explain your findings.")
328
+
329
+ if session.pending:
330
+ request_id = session.pending["id"]
331
+ # Deliver this request to your UI and wait for a real human answer.
332
+ session.answer(request_id, "the human's actual answer")
333
+ ~~~
334
+
335
+ A pull-based adapter is also available:
336
+
337
+ ~~~python
338
+ for event in session.stream_turn("Inspect the current environment."):
339
+ deliver_to_ui(event.as_dict())
340
+ ~~~
341
+
342
+ Both adapters expose the same versioned event contract. A future web UI or
343
+ outer agent loop can subscribe and send answers by request ID. See
344
+ [architecture and event lifecycle](docs/architecture.md).
345
+
346
+ ## Development and verification
347
+
348
+ ~~~console
349
+ .venv/bin/python -W error::ResourceWarning -m unittest discover -s tests -v
350
+ ~~~
351
+
352
+ Tests exercise the actual mini-swe-agent lifecycle with scripted provider
353
+ boundaries, real macOS inspection binaries, local persistence, pause/resume,
354
+ remaining tool calls, limits, extensions, redaction, and provider streaming
355
+ assembly. Live paid-model inference requires your own configured model IDs and
356
+ credentials. Linux execution is covered by the CI workflow.