getbased-agent-stack 0.5.2__tar.gz → 0.5.4__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.
- {getbased_agent_stack-0.5.2/src/getbased_agent_stack.egg-info → getbased_agent_stack-0.5.4}/PKG-INFO +7 -6
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/README.md +4 -3
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/pyproject.toml +3 -3
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/src/getbased_agent_stack/__init__.py +1 -1
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/src/getbased_agent_stack/cli.py +21 -3
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/src/getbased_agent_stack/mcp_configs.py +4 -3
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/src/getbased_agent_stack/units.py +16 -1
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4/src/getbased_agent_stack.egg-info}/PKG-INFO +7 -6
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/src/getbased_agent_stack.egg-info/requires.txt +2 -2
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/tests/test_cli.py +7 -1
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/tests/test_units.py +3 -1
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/LICENSE +0 -0
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/setup.cfg +0 -0
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/src/getbased_agent_stack/env_file.py +0 -0
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/src/getbased_agent_stack/systemd/getbased-dashboard.service +0 -0
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/src/getbased_agent_stack/systemd/getbased-rag.service +0 -0
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/src/getbased_agent_stack.egg-info/SOURCES.txt +0 -0
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/src/getbased_agent_stack.egg-info/dependency_links.txt +0 -0
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/src/getbased_agent_stack.egg-info/entry_points.txt +0 -0
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/src/getbased_agent_stack.egg-info/top_level.txt +0 -0
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/tests/test_env_file.py +0 -0
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/tests/test_integration.py +0 -0
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/tests/test_mcp_configs.py +0 -0
- {getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/tests/test_systemd_units.py +0 -0
{getbased_agent_stack-0.5.2/src/getbased_agent_stack.egg-info → getbased_agent_stack-0.5.4}/PKG-INFO
RENAMED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: getbased-agent-stack
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.4
|
|
4
4
|
Summary: One-command install of the full getbased agent stack — getbased-mcp + getbased-rag + getbased-dashboard
|
|
5
5
|
License-Expression: AGPL-3.0-or-later
|
|
6
6
|
Requires-Python: >=3.10
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
License-File: LICENSE
|
|
9
|
-
Requires-Dist: getbased-mcp>=0.2.
|
|
9
|
+
Requires-Dist: getbased-mcp>=0.2.6
|
|
10
10
|
Requires-Dist: getbased-rag>=0.7.2
|
|
11
|
-
Requires-Dist: getbased-dashboard>=0.6.
|
|
11
|
+
Requires-Dist: getbased-dashboard>=0.6.4
|
|
12
12
|
Provides-Extra: full
|
|
13
13
|
Requires-Dist: getbased-rag[full]>=0.7.2; extra == "full"
|
|
14
14
|
Provides-Extra: test
|
|
@@ -79,7 +79,7 @@ getbased-stack init --yes
|
|
|
79
79
|
|
|
80
80
|
The wizard (~30 seconds):
|
|
81
81
|
|
|
82
|
-
1. Prompts for your `GETBASED_TOKEN` (skip if you don't use
|
|
82
|
+
1. Prompts for your `GETBASED_TOKEN` and `GETBASED_AGENT_CONTEXT_KEY` (skip if you don't use Agent Access; `--yes` keeps current values and lets you set them later with `getbased-stack set ...`)
|
|
83
83
|
2. Generates a rag API key if one doesn't exist
|
|
84
84
|
3. Writes `~/.config/getbased/env` (mode 0600) — the shared config file
|
|
85
85
|
4. Installs systemd user units for rag + dashboard, enables them, starts them
|
|
@@ -122,7 +122,8 @@ sudo loginctl enable-linger $USER
|
|
|
122
122
|
|
|
123
123
|
```bash
|
|
124
124
|
getbased-stack status # env file, unit state, linger
|
|
125
|
-
getbased-stack set GETBASED_TOKEN=new
|
|
125
|
+
getbased-stack set GETBASED_TOKEN=new
|
|
126
|
+
getbased-stack set GETBASED_AGENT_CONTEXT_KEY=new
|
|
126
127
|
getbased-stack install # re-apply unit files after package upgrade
|
|
127
128
|
getbased-stack uninstall # stop + disable + remove units
|
|
128
129
|
```
|
|
@@ -149,7 +150,7 @@ sync GW getbased-rag ◀──────────────┘ g
|
|
|
149
150
|
|
|
150
151
|
The MCP holds no persistent state; it's a thin translator between MCP tool calls and two HTTP backends:
|
|
151
152
|
|
|
152
|
-
- `sync.getbased.health/api/context` —
|
|
153
|
+
- `sync.getbased.health/api/context` — encrypted lab context pushed by your PWA session (authorized by Agent Access token, decrypted locally with Agent Context key)
|
|
153
154
|
- `localhost:8322` (getbased-rag) — your local research library
|
|
154
155
|
|
|
155
156
|
The dashboard is likewise stateless — it proxies rag for Knowledge operations, imports `getbased_mcp` to introspect env/config, and spawns the MCP binary on demand to verify it works.
|
|
@@ -60,7 +60,7 @@ getbased-stack init --yes
|
|
|
60
60
|
|
|
61
61
|
The wizard (~30 seconds):
|
|
62
62
|
|
|
63
|
-
1. Prompts for your `GETBASED_TOKEN` (skip if you don't use
|
|
63
|
+
1. Prompts for your `GETBASED_TOKEN` and `GETBASED_AGENT_CONTEXT_KEY` (skip if you don't use Agent Access; `--yes` keeps current values and lets you set them later with `getbased-stack set ...`)
|
|
64
64
|
2. Generates a rag API key if one doesn't exist
|
|
65
65
|
3. Writes `~/.config/getbased/env` (mode 0600) — the shared config file
|
|
66
66
|
4. Installs systemd user units for rag + dashboard, enables them, starts them
|
|
@@ -103,7 +103,8 @@ sudo loginctl enable-linger $USER
|
|
|
103
103
|
|
|
104
104
|
```bash
|
|
105
105
|
getbased-stack status # env file, unit state, linger
|
|
106
|
-
getbased-stack set GETBASED_TOKEN=new
|
|
106
|
+
getbased-stack set GETBASED_TOKEN=new
|
|
107
|
+
getbased-stack set GETBASED_AGENT_CONTEXT_KEY=new
|
|
107
108
|
getbased-stack install # re-apply unit files after package upgrade
|
|
108
109
|
getbased-stack uninstall # stop + disable + remove units
|
|
109
110
|
```
|
|
@@ -130,7 +131,7 @@ sync GW getbased-rag ◀──────────────┘ g
|
|
|
130
131
|
|
|
131
132
|
The MCP holds no persistent state; it's a thin translator between MCP tool calls and two HTTP backends:
|
|
132
133
|
|
|
133
|
-
- `sync.getbased.health/api/context` —
|
|
134
|
+
- `sync.getbased.health/api/context` — encrypted lab context pushed by your PWA session (authorized by Agent Access token, decrypted locally with Agent Context key)
|
|
134
135
|
- `localhost:8322` (getbased-rag) — your local research library
|
|
135
136
|
|
|
136
137
|
The dashboard is likewise stateless — it proxies rag for Knowledge operations, imports `getbased_mcp` to introspect env/config, and spawns the MCP binary on demand to verify it works.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "getbased-agent-stack"
|
|
7
|
-
version = "0.5.
|
|
7
|
+
version = "0.5.4"
|
|
8
8
|
description = "One-command install of the full getbased agent stack — getbased-mcp + getbased-rag + getbased-dashboard"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "AGPL-3.0-or-later"
|
|
@@ -12,9 +12,9 @@ requires-python = ">=3.10"
|
|
|
12
12
|
# Pulls every sibling package. Bump this meta when a sibling protocol
|
|
13
13
|
# bump requires coordinated release.
|
|
14
14
|
dependencies = [
|
|
15
|
-
"getbased-mcp>=0.2.
|
|
15
|
+
"getbased-mcp>=0.2.6",
|
|
16
16
|
"getbased-rag>=0.7.2",
|
|
17
|
-
"getbased-dashboard>=0.6.
|
|
17
|
+
"getbased-dashboard>=0.6.4",
|
|
18
18
|
]
|
|
19
19
|
|
|
20
20
|
[project.optional-dependencies]
|
|
@@ -100,20 +100,28 @@ def cmd_init(args: argparse.Namespace) -> int:
|
|
|
100
100
|
)
|
|
101
101
|
print()
|
|
102
102
|
|
|
103
|
-
# 1.
|
|
103
|
+
# 1. Agent Access secrets (optional)
|
|
104
104
|
existing = env_file.read_env_file()
|
|
105
105
|
current_token = existing.get("GETBASED_TOKEN", "")
|
|
106
|
+
current_context_key = existing.get("GETBASED_AGENT_CONTEXT_KEY", "")
|
|
106
107
|
masked = "****" + current_token[-4:] if current_token else "(unset)"
|
|
107
|
-
|
|
108
|
+
key_masked = "****" + current_context_key[-4:] if current_context_key else "(unset)"
|
|
109
|
+
print(f"[1/4] Agent Access token + context key (token: {masked}, key: {key_masked})")
|
|
108
110
|
if non_interactive:
|
|
109
111
|
token = current_token
|
|
110
|
-
|
|
112
|
+
context_key = current_context_key
|
|
113
|
+
print(" keeping current values (set with `getbased-stack set GETBASED_TOKEN=…` and `getbased-stack set GETBASED_AGENT_CONTEXT_KEY=…` later).")
|
|
111
114
|
else:
|
|
112
115
|
token = _prompt(
|
|
113
116
|
"Paste GETBASED_TOKEN (press Enter to keep current / skip)",
|
|
114
117
|
default=current_token,
|
|
115
118
|
secret=True,
|
|
116
119
|
)
|
|
120
|
+
context_key = _prompt(
|
|
121
|
+
"Paste GETBASED_AGENT_CONTEXT_KEY (press Enter to keep current / skip)",
|
|
122
|
+
default=current_context_key,
|
|
123
|
+
secret=True,
|
|
124
|
+
)
|
|
117
125
|
|
|
118
126
|
# 2. API key
|
|
119
127
|
key_path = Path(existing.get("LENS_API_KEY_FILE", str(_default_api_key_file())))
|
|
@@ -131,6 +139,8 @@ def cmd_init(args: argparse.Namespace) -> int:
|
|
|
131
139
|
merged["GETBASED_STACK_MANAGED"] = "1"
|
|
132
140
|
if token:
|
|
133
141
|
merged["GETBASED_TOKEN"] = token
|
|
142
|
+
if context_key:
|
|
143
|
+
merged["GETBASED_AGENT_CONTEXT_KEY"] = context_key
|
|
134
144
|
merged["LENS_API_KEY_FILE"] = str(key_path)
|
|
135
145
|
merged.setdefault("LENS_URL", "http://127.0.0.1:8322")
|
|
136
146
|
path = env_file.write_env_file(merged)
|
|
@@ -153,6 +163,14 @@ def cmd_init(args: argparse.Namespace) -> int:
|
|
|
153
163
|
_print_linger_hint(strict=False)
|
|
154
164
|
|
|
155
165
|
# 6. MCP config pointers
|
|
166
|
+
print("\nNext steps for Agent Access:")
|
|
167
|
+
print(" 1. In getbased, enable Cross-device Sync and Agent Access.")
|
|
168
|
+
print(" 2. Copy both values from Settings → Agent Access:")
|
|
169
|
+
print(" GETBASED_TOKEN and GETBASED_AGENT_CONTEXT_KEY.")
|
|
170
|
+
print(" 3. Save them here with:")
|
|
171
|
+
print(" getbased-stack set GETBASED_TOKEN=...")
|
|
172
|
+
print(" getbased-stack set GETBASED_AGENT_CONTEXT_KEY=...")
|
|
173
|
+
|
|
156
174
|
print("\nConfigure your MCP client(s):")
|
|
157
175
|
for client in mcp_configs.SUPPORTED_CLIENTS:
|
|
158
176
|
print(f" getbased-stack mcp-config {client}")
|
{getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/src/getbased_agent_stack/mcp_configs.py
RENAMED
|
@@ -133,9 +133,10 @@ def emit_hermes(resolver: Callable[[str], "str | None"] = shutil.which) -> str:
|
|
|
133
133
|
lines = [
|
|
134
134
|
"# Hermes Agent MCP configuration snippet for ~/.hermes/config.yaml",
|
|
135
135
|
"# See https://github.com/hermes-agent/hermes-agent for the full config schema.",
|
|
136
|
-
"# The getbased stack's shared env file carries GETBASED_TOKEN
|
|
137
|
-
"# api key path; only the
|
|
138
|
-
"#
|
|
136
|
+
"# The getbased stack's shared env file carries GETBASED_TOKEN,",
|
|
137
|
+
"# GETBASED_AGENT_CONTEXT_KEY, rag URL, and api key path; only the",
|
|
138
|
+
"# opt-in flag belongs in Hermes's config.",
|
|
139
|
+
"# (If your Hermes config already sets GETBASED_TOKEN / GETBASED_AGENT_CONTEXT_KEY / LENS_* explicitly,",
|
|
139
140
|
"# drop the env block entirely — the Python loader honors existing env.)",
|
|
140
141
|
]
|
|
141
142
|
if warning:
|
|
@@ -108,6 +108,17 @@ class UnitManager:
|
|
|
108
108
|
args.extend(SERVICE_NAMES)
|
|
109
109
|
return self._shell(args)
|
|
110
110
|
|
|
111
|
+
def restart(self) -> CommandResult:
|
|
112
|
+
"""Restart bundled services after an upgrade/reinstall.
|
|
113
|
+
|
|
114
|
+
`uv tool install` replaces files inside the tool environment. If the
|
|
115
|
+
services are already running, `systemctl enable --now …` is a no-op and
|
|
116
|
+
the old Python processes can keep serving from a half-replaced venv.
|
|
117
|
+
Restarting makes repeated `curl | bash` installs safe and starts the
|
|
118
|
+
units when they were previously inactive.
|
|
119
|
+
"""
|
|
120
|
+
return self._shell(["systemctl", "--user", "restart", *SERVICE_NAMES])
|
|
121
|
+
|
|
111
122
|
def disable(self, now: bool = True) -> CommandResult:
|
|
112
123
|
args = ["systemctl", "--user", "disable"]
|
|
113
124
|
if now:
|
|
@@ -154,7 +165,11 @@ class UnitManager:
|
|
|
154
165
|
else:
|
|
155
166
|
log.append("enabled " + ", ".join(SERVICE_NAMES))
|
|
156
167
|
if start:
|
|
157
|
-
|
|
168
|
+
r = self.restart()
|
|
169
|
+
if r.returncode != 0:
|
|
170
|
+
log.append(f"restart FAILED: {r.stderr.strip()}")
|
|
171
|
+
else:
|
|
172
|
+
log.append("restarted " + ", ".join(SERVICE_NAMES))
|
|
158
173
|
return log
|
|
159
174
|
|
|
160
175
|
def uninstall(self) -> "list[str]":
|
{getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4/src/getbased_agent_stack.egg-info}/PKG-INFO
RENAMED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: getbased-agent-stack
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.4
|
|
4
4
|
Summary: One-command install of the full getbased agent stack — getbased-mcp + getbased-rag + getbased-dashboard
|
|
5
5
|
License-Expression: AGPL-3.0-or-later
|
|
6
6
|
Requires-Python: >=3.10
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
License-File: LICENSE
|
|
9
|
-
Requires-Dist: getbased-mcp>=0.2.
|
|
9
|
+
Requires-Dist: getbased-mcp>=0.2.6
|
|
10
10
|
Requires-Dist: getbased-rag>=0.7.2
|
|
11
|
-
Requires-Dist: getbased-dashboard>=0.6.
|
|
11
|
+
Requires-Dist: getbased-dashboard>=0.6.4
|
|
12
12
|
Provides-Extra: full
|
|
13
13
|
Requires-Dist: getbased-rag[full]>=0.7.2; extra == "full"
|
|
14
14
|
Provides-Extra: test
|
|
@@ -79,7 +79,7 @@ getbased-stack init --yes
|
|
|
79
79
|
|
|
80
80
|
The wizard (~30 seconds):
|
|
81
81
|
|
|
82
|
-
1. Prompts for your `GETBASED_TOKEN` (skip if you don't use
|
|
82
|
+
1. Prompts for your `GETBASED_TOKEN` and `GETBASED_AGENT_CONTEXT_KEY` (skip if you don't use Agent Access; `--yes` keeps current values and lets you set them later with `getbased-stack set ...`)
|
|
83
83
|
2. Generates a rag API key if one doesn't exist
|
|
84
84
|
3. Writes `~/.config/getbased/env` (mode 0600) — the shared config file
|
|
85
85
|
4. Installs systemd user units for rag + dashboard, enables them, starts them
|
|
@@ -122,7 +122,8 @@ sudo loginctl enable-linger $USER
|
|
|
122
122
|
|
|
123
123
|
```bash
|
|
124
124
|
getbased-stack status # env file, unit state, linger
|
|
125
|
-
getbased-stack set GETBASED_TOKEN=new
|
|
125
|
+
getbased-stack set GETBASED_TOKEN=new
|
|
126
|
+
getbased-stack set GETBASED_AGENT_CONTEXT_KEY=new
|
|
126
127
|
getbased-stack install # re-apply unit files after package upgrade
|
|
127
128
|
getbased-stack uninstall # stop + disable + remove units
|
|
128
129
|
```
|
|
@@ -149,7 +150,7 @@ sync GW getbased-rag ◀──────────────┘ g
|
|
|
149
150
|
|
|
150
151
|
The MCP holds no persistent state; it's a thin translator between MCP tool calls and two HTTP backends:
|
|
151
152
|
|
|
152
|
-
- `sync.getbased.health/api/context` —
|
|
153
|
+
- `sync.getbased.health/api/context` — encrypted lab context pushed by your PWA session (authorized by Agent Access token, decrypted locally with Agent Context key)
|
|
153
154
|
- `localhost:8322` (getbased-rag) — your local research library
|
|
154
155
|
|
|
155
156
|
The dashboard is likewise stateless — it proxies rag for Knowledge operations, imports `getbased_mcp` to introspect env/config, and spawns the MCP binary on demand to verify it works.
|
|
@@ -96,10 +96,14 @@ def test_install_writes_units_and_enables(stack_home, fake_shell):
|
|
|
96
96
|
assert (unit_dir / "getbased-rag.service").exists()
|
|
97
97
|
assert (unit_dir / "getbased-dashboard.service").exists()
|
|
98
98
|
|
|
99
|
-
# daemon-reload
|
|
99
|
+
# daemon-reload, enable --now, and restart all run. The explicit restart
|
|
100
|
+
# matters for re-running install.sh over an active stack after uv replaces
|
|
101
|
+
# the tool environment: old Python processes must not keep serving from a
|
|
102
|
+
# half-replaced venv.
|
|
100
103
|
all_calls = [" ".join(cmd) for cmd in fake_shell]
|
|
101
104
|
assert any("daemon-reload" in c for c in all_calls)
|
|
102
105
|
assert any("enable --now" in c for c in all_calls)
|
|
106
|
+
assert any("restart getbased-rag.service getbased-dashboard.service" in c for c in all_calls)
|
|
103
107
|
|
|
104
108
|
|
|
105
109
|
def test_install_no_enable_flag(stack_home, fake_shell):
|
|
@@ -313,6 +317,8 @@ def test_init_yes_flag_skips_all_prompts(stack_home, fake_shell, monkeypatch):
|
|
|
313
317
|
assert rc == 0
|
|
314
318
|
# Banner reflects the mode so the user sees what happened
|
|
315
319
|
assert "non-interactive" in out.lower()
|
|
320
|
+
assert "GETBASED_TOKEN and GETBASED_AGENT_CONTEXT_KEY" in out
|
|
321
|
+
assert "getbased-stack set GETBASED_AGENT_CONTEXT_KEY" in out
|
|
316
322
|
# Env file + units still land
|
|
317
323
|
assert env_file.env_file_path().exists()
|
|
318
324
|
assert (stack_home / "config" / "systemd" / "user" / "getbased-rag.service").exists()
|
|
@@ -145,11 +145,13 @@ def test_install_full_sequence(tmp_path):
|
|
|
145
145
|
# systemctl called in the expected order
|
|
146
146
|
assert shell.calls[0] == ["systemctl", "--user", "daemon-reload"]
|
|
147
147
|
assert shell.calls[1] == ["systemctl", "--user", "enable", "--now", *SERVICE_NAMES]
|
|
148
|
+
assert shell.calls[2] == ["systemctl", "--user", "restart", *SERVICE_NAMES]
|
|
148
149
|
# Log mentions what happened
|
|
149
150
|
joined = "\n".join(log)
|
|
150
151
|
assert "wrote" in joined
|
|
151
152
|
assert "enabled" in joined
|
|
152
|
-
assert "
|
|
153
|
+
assert "restarted" in joined
|
|
154
|
+
assert not any(line.startswith("started ") for line in log)
|
|
153
155
|
|
|
154
156
|
|
|
155
157
|
def test_install_daemon_reload_failure_short_circuits(tmp_path):
|
|
File without changes
|
|
File without changes
|
{getbased_agent_stack-0.5.2 → getbased_agent_stack-0.5.4}/src/getbased_agent_stack/env_file.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|