Skip to content

Commit b355954

Browse files
committed
feat(bot): aiui in [bot]+[all]; onboard updates existing settings; _save_env_vars supports delete
- pyproject: add aiui to [bot] and [all] so the chat dashboard is available immediately after onboarding a messaging bot. - onboard: every setting (token, extra env vars, allowlist, home channel) now shows the existing (masked) value and lets the user update or keep it, mirroring hermes-agent setup. - onboard: support 'clear' keyword on allowlist prompt to restore open access. - _save_env_vars: None as a value now deletes the key from ~/.praisonai/.env (previously empty strings were silently skipped). - Bumps praisonaiagents to 1.6.11.
1 parent 4b1b17b commit b355954

File tree

4 files changed

+122
-28
lines changed

4 files changed

+122
-28
lines changed

src/praisonai-agents/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "praisonaiagents"
7-
version = "1.6.10"
7+
version = "1.6.11"
88
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
99
readme = "README.md"
1010
requires-python = ">=3.10"

src/praisonai-agents/uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/praisonai/praisonai/cli/features/onboard.py

Lines changed: 118 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,19 @@ def _praison_home() -> Path:
7575
return Path(override) if override else Path.home() / ".praisonai"
7676

7777

78-
def _save_env_vars(env_vars: Dict[str, str]) -> Optional[Path]:
78+
def _save_env_vars(env_vars: Dict[str, Optional[str]]) -> Optional[Path]:
7979
"""Atomically merge ``env_vars`` into ``~/.praisonai/.env`` (chmod 600).
8080
81-
Empty/None values are skipped. Existing keys not in ``env_vars`` are
82-
preserved. Written with a temp-then-rename to avoid partial writes.
81+
- Non-empty string values are written (updating existing keys).
82+
- ``None`` values **remove** the key from the file (supports "clear" updates
83+
so the user can drop an allowlist or home-channel).
84+
- Empty-string values are skipped.
85+
Existing keys not referenced in ``env_vars`` are preserved. Written with a
86+
temp-then-rename to avoid partial writes.
8387
"""
84-
filtered = {k: v for k, v in env_vars.items() if v}
85-
if not filtered:
88+
updates = {k: v for k, v in env_vars.items() if v}
89+
deletes = {k for k, v in env_vars.items() if v is None}
90+
if not updates and not deletes:
8691
return None
8792

8893
env_file = _praison_home() / ".env"
@@ -99,7 +104,9 @@ def _save_env_vars(env_vars: Dict[str, str]) -> Optional[Path]:
99104
if s and not s.startswith("#") and "=" in s:
100105
k, v = s.split("=", 1)
101106
existing[k.strip()] = v.strip()
102-
existing.update(filtered)
107+
existing.update(updates)
108+
for k in deletes:
109+
existing.pop(k, None)
103110

104111
body = ["# PraisonAI configuration",
105112
"# Managed by praisonai onboard / setup", ""]
@@ -204,16 +211,45 @@ def run(self) -> None:
204211
return
205212

206213
# Step 2: Token configuration (password-hidden; persisted to ~/.praisonai/.env)
214+
# Every setting can be updated even if already present — existing values are
215+
# shown as masked defaults; press Enter to keep, or type a new value to
216+
# overwrite (mirrors hermes-agent setup behaviour).
207217
console.print("\n[bold]Step 2: Configure tokens[/bold]\n")
208-
env_to_save: Dict[str, str] = {}
218+
console.print(
219+
" [dim]Press Enter to keep the existing value, or type a new one to update.[/dim]\n"
220+
)
221+
env_to_save: Dict[str, Optional[str]] = {}
222+
223+
def _mask(value: str) -> str:
224+
if not value:
225+
return ""
226+
if len(value) <= 6:
227+
return "*" * len(value)
228+
return f"{value[:2]}{'*' * (len(value) - 4)}{value[-2:]}"
229+
209230
for plat in self.selected_platforms:
210231
info = PLATFORMS[plat]
211232
env_var = info["token_env"]
212233
existing = os.environ.get(env_var, "")
213234

214235
if existing:
215-
console.print(f" [green]✓[/green] {info['name']}: {env_var} already set")
216-
self.tokens[plat] = existing
236+
console.print(
237+
f" [green]✓[/green] {info['name']}: {env_var} = [cyan]{_mask(existing)}[/cyan]"
238+
)
239+
console.print(f" [dim]{info['token_help']}[/dim]")
240+
new_token = Prompt.ask(
241+
f" Update {info['name']} token? (Enter = keep current)",
242+
password=True,
243+
default="",
244+
show_default=False,
245+
)
246+
if new_token:
247+
self.tokens[plat] = new_token
248+
os.environ[env_var] = new_token
249+
env_to_save[env_var] = new_token
250+
console.print(" [green]✓[/green] Token updated")
251+
else:
252+
self.tokens[plat] = existing
217253
else:
218254
console.print(f" [dim]{info['token_help']}[/dim]")
219255
token = Prompt.ask(
@@ -228,11 +264,28 @@ def run(self) -> None:
228264
env_to_save[env_var] = token
229265
console.print(" [green]✓[/green] Token captured")
230266
else:
231-
console.print(f" [yellow]⚠[/yellow] No token — you'll need to set {env_var} before starting")
267+
console.print(
268+
f" [yellow]⚠[/yellow] No token — you'll need to set {env_var} before starting"
269+
)
232270

233271
# Extra env vars (e.g., Slack app token) — also hidden by default
234272
for extra_env, extra_desc in info.get("extra_env", {}).items():
235-
if not os.environ.get(extra_env):
273+
existing_extra = os.environ.get(extra_env, "")
274+
if existing_extra:
275+
console.print(
276+
f" [green]✓[/green] {extra_env} = [cyan]{_mask(existing_extra)}[/cyan]"
277+
)
278+
new_extra = Prompt.ask(
279+
f" Update {extra_desc}? (Enter = keep current)",
280+
password=True,
281+
default="",
282+
show_default=False,
283+
)
284+
if new_extra:
285+
os.environ[extra_env] = new_extra
286+
env_to_save[extra_env] = new_extra
287+
console.print(f" [green]✓[/green] {extra_env} updated")
288+
else:
236289
extra_val = Prompt.ask(
237290
f" {extra_desc} ({extra_env})",
238291
password=True,
@@ -249,38 +302,77 @@ def run(self) -> None:
249302
if allowed_env:
250303
existing_allow = os.environ.get(allowed_env, "").strip()
251304
if existing_allow:
252-
console.print(f" [green]✓[/green] {allowed_env} already set")
305+
console.print(
306+
f" [green]✓[/green] {allowed_env} = [cyan]{existing_allow}[/cyan]"
307+
)
308+
console.print(
309+
f" [dim]{info.get('user_id_help', 'Comma-separated user IDs')}[/dim]"
310+
)
311+
new_allow = Prompt.ask(
312+
f" Update allowed users for {info['name']}? (Enter = keep, 'clear' = remove)",
313+
default="",
314+
show_default=False,
315+
).strip()
316+
if new_allow.lower() == "clear":
317+
os.environ.pop(allowed_env, None)
318+
env_to_save[allowed_env] = None
319+
console.print(
320+
" [yellow]✓ Allowlist cleared — open access restored[/yellow]"
321+
)
322+
elif new_allow:
323+
new_allow = new_allow.replace(" ", "")
324+
os.environ[allowed_env] = new_allow
325+
env_to_save[allowed_env] = new_allow
326+
console.print(" [green]✓[/green] Allowlist updated")
253327
else:
254-
console.print(f" [bold]🔒 Security — restrict who can use your {info['name']} bot[/bold]")
255-
console.print(f" [dim]{info.get('user_id_help', 'Enter comma-separated user IDs')}[/dim]")
328+
console.print(
329+
f" [bold]🔒 Security — restrict who can use your {info['name']} bot[/bold]"
330+
)
331+
console.print(
332+
f" [dim]{info.get('user_id_help', 'Enter comma-separated user IDs')}[/dim]"
333+
)
256334
allow_val = Prompt.ask(
257-
f" Allowed user IDs (comma-separated, empty = open access)",
335+
" Allowed user IDs (comma-separated, empty = open access)",
258336
default="",
259337
show_default=False,
260338
)
261339
allow_val = allow_val.replace(" ", "")
262340
if allow_val:
263341
os.environ[allowed_env] = allow_val
264342
env_to_save[allowed_env] = allow_val
265-
console.print(f" [green]✓[/green] Allowlist saved — only listed users can talk to the bot")
343+
console.print(
344+
" [green]✓[/green] Allowlist saved — only listed users can talk to the bot"
345+
)
266346
else:
267347
console.print(
268-
f" [yellow]⚠ Warning:[/yellow] no allowlist set — anyone who finds your bot can use it."
348+
" [yellow]⚠ Warning:[/yellow] no allowlist set — anyone who finds your bot can use it."
269349
)
270350

271-
# Home channel (default = first allowed user)
272-
if home_env and not os.environ.get(home_env):
351+
# Home channel (default = first allowed user) — also updatable
352+
if home_env:
353+
existing_home = os.environ.get(home_env, "").strip()
273354
first_allowed = ""
274355
saved_allow = env_to_save.get(allowed_env, existing_allow)
275-
if saved_allow:
356+
if isinstance(saved_allow, str) and saved_allow:
276357
first_allowed = saved_allow.split(",")[0].strip()
358+
default_home = existing_home or first_allowed
359+
if existing_home:
360+
console.print(
361+
f" [green]✓[/green] {home_env} = [cyan]{existing_home}[/cyan]"
362+
)
363+
prompt_label = (
364+
f" Update home channel for {info['name']}? (Enter = keep current)"
365+
)
366+
else:
367+
prompt_label = (
368+
f" Home channel / user ID for proactive messages ({home_env})"
369+
)
277370
home_val = Prompt.ask(
278-
f" Home channel / user ID for proactive messages ({home_env})",
279-
default=first_allowed,
280-
show_default=bool(first_allowed),
281-
)
282-
home_val = home_val.strip()
283-
if home_val:
371+
prompt_label,
372+
default=default_home,
373+
show_default=bool(default_home),
374+
).strip()
375+
if home_val and home_val != existing_home:
284376
os.environ[home_env] = home_val
285377
env_to_save[home_env] = home_val
286378
console.print(f" [green]✓[/green] Home channel set to {home_val}")

src/praisonai/pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ all = [
135135
"slack-bolt>=1.18.0",
136136
"brotlicffi>=1.0.0",
137137
"aiohttp>=3.8.0",
138+
"aiui>=0.3.100", # PraisonAI UI — dashboard + chat for onboarded bots
138139
# Storage backends
139140
"redis>=5.0.0",
140141
"pymongo>=4.6.0",
@@ -157,6 +158,7 @@ bot = [
157158
"slack-bolt>=1.18.0",
158159
"brotlicffi>=1.0.0",
159160
"aiohttp>=3.8.0",
161+
"aiui>=0.3.100", # PraisonAI UI — dashboard + chat for onboarded bots
160162
"ddgs>=9.0.0", # DuckDuckGo search for agent web tools
161163
"psutil>=5.9.0", # Shell tools (execute_command, list_processes, get_system_info)
162164
]

0 commit comments

Comments
 (0)