ageri 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 (96) hide show
  1. ageri-0.1.0/PKG-INFO +61 -0
  2. ageri-0.1.0/README.md +33 -0
  3. ageri-0.1.0/ageri/__init__.py +2 -0
  4. ageri-0.1.0/ageri/__main__.py +161 -0
  5. ageri-0.1.0/ageri/biography.py +582 -0
  6. ageri-0.1.0/ageri/bootstrap.py +39 -0
  7. ageri-0.1.0/ageri/bundle.py +153 -0
  8. ageri-0.1.0/ageri/capability_proxy.py +382 -0
  9. ageri-0.1.0/ageri/config_loader.py +259 -0
  10. ageri-0.1.0/ageri/daily_life.py +247 -0
  11. ageri-0.1.0/ageri/device.py +14 -0
  12. ageri-0.1.0/ageri/main.py +230 -0
  13. ageri-0.1.0/ageri/memory.py +729 -0
  14. ageri-0.1.0/ageri/notifications.py +147 -0
  15. ageri-0.1.0/ageri/orchestrator.py +999 -0
  16. ageri-0.1.0/ageri/personas.py +334 -0
  17. ageri-0.1.0/ageri/proactive.py +337 -0
  18. ageri-0.1.0/ageri/profile_store.py +418 -0
  19. ageri-0.1.0/ageri/pronouns.py +29 -0
  20. ageri-0.1.0/ageri/setup_wizard.py +315 -0
  21. ageri-0.1.0/ageri/skill.py +41 -0
  22. ageri-0.1.0/ageri/skills/__init__.py +1 -0
  23. ageri-0.1.0/ageri/skills/core/__init__.py +0 -0
  24. ageri-0.1.0/ageri/skills/core/skill.py +483 -0
  25. ageri-0.1.0/ageri/skills/devops/__init__.py +0 -0
  26. ageri-0.1.0/ageri/skills/devops/boss.py +379 -0
  27. ageri-0.1.0/ageri/skills/httpapi/__init__.py +0 -0
  28. ageri-0.1.0/ageri/skills/httpapi/boss.py +266 -0
  29. ageri-0.1.0/ageri/skills/knowledge/__init__.py +0 -0
  30. ageri-0.1.0/ageri/skills/knowledge/boss.py +275 -0
  31. ageri-0.1.0/ageri/skills/messenger/__init__.py +0 -0
  32. ageri-0.1.0/ageri/skills/messenger/boss.py +345 -0
  33. ageri-0.1.0/ageri/skills/personal/__init__.py +1 -0
  34. ageri-0.1.0/ageri/skills/personal/boss.py +703 -0
  35. ageri-0.1.0/ageri/skills/research/__init__.py +1 -0
  36. ageri-0.1.0/ageri/skills/research/boss.py +421 -0
  37. ageri-0.1.0/ageri/skills/sentinel/__init__.py +1 -0
  38. ageri-0.1.0/ageri/skills/sentinel/boss.py +61 -0
  39. ageri-0.1.0/ageri/skills/telegram/__init__.py +0 -0
  40. ageri-0.1.0/ageri/skills/telegram/boss.py +401 -0
  41. ageri-0.1.0/ageri/skills/whatsapp/__init__.py +0 -0
  42. ageri-0.1.0/ageri/skills/whatsapp/boss.py +346 -0
  43. ageri-0.1.0/ageri/skills/zalo_oa/__init__.py +0 -0
  44. ageri-0.1.0/ageri/skills/zalo_oa/boss.py +388 -0
  45. ageri-0.1.0/ageri/slack_interface.py +244 -0
  46. ageri-0.1.0/ageri/tools.py +606 -0
  47. ageri-0.1.0/ageri/tunnel.py +143 -0
  48. ageri-0.1.0/ageri/web/__init__.py +1 -0
  49. ageri-0.1.0/ageri/web/app.py +61 -0
  50. ageri-0.1.0/ageri/web/auth.py +99 -0
  51. ageri-0.1.0/ageri/web/routes/__init__.py +0 -0
  52. ageri-0.1.0/ageri/web/routes/chat.py +366 -0
  53. ageri-0.1.0/ageri/web/routes/get_started.py +224 -0
  54. ageri-0.1.0/ageri/web/routes/login.py +50 -0
  55. ageri-0.1.0/ageri/web/routes/onboarding.py +187 -0
  56. ageri-0.1.0/ageri/web/templates/base.html +38 -0
  57. ageri-0.1.0/ageri/web/templates/chat.html +475 -0
  58. ageri-0.1.0/ageri/web/templates/get_started.html +191 -0
  59. ageri-0.1.0/ageri/web/templates/login.html +39 -0
  60. ageri-0.1.0/ageri/web/templates/onboarding.html +85 -0
  61. ageri-0.1.0/ageri/webhook.py +355 -0
  62. ageri-0.1.0/ageri/wizard.py +1280 -0
  63. ageri-0.1.0/ageri.egg-info/PKG-INFO +61 -0
  64. ageri-0.1.0/ageri.egg-info/SOURCES.txt +94 -0
  65. ageri-0.1.0/ageri.egg-info/dependency_links.txt +1 -0
  66. ageri-0.1.0/ageri.egg-info/entry_points.txt +2 -0
  67. ageri-0.1.0/ageri.egg-info/requires.txt +21 -0
  68. ageri-0.1.0/ageri.egg-info/top_level.txt +1 -0
  69. ageri-0.1.0/pyproject.toml +49 -0
  70. ageri-0.1.0/setup.cfg +4 -0
  71. ageri-0.1.0/tests/test_app_contract.py +317 -0
  72. ageri-0.1.0/tests/test_app_devops.py +572 -0
  73. ageri-0.1.0/tests/test_app_httpapi.py +397 -0
  74. ageri-0.1.0/tests/test_app_knowledge.py +425 -0
  75. ageri-0.1.0/tests/test_app_messenger.py +578 -0
  76. ageri-0.1.0/tests/test_app_personal.py +389 -0
  77. ageri-0.1.0/tests/test_app_registry.py +103 -0
  78. ageri-0.1.0/tests/test_app_research.py +704 -0
  79. ageri-0.1.0/tests/test_app_telegram.py +740 -0
  80. ageri-0.1.0/tests/test_app_whatsapp.py +638 -0
  81. ageri-0.1.0/tests/test_app_zalo_oa.py +752 -0
  82. ageri-0.1.0/tests/test_bootstrap.py +75 -0
  83. ageri-0.1.0/tests/test_bundle.py +178 -0
  84. ageri-0.1.0/tests/test_capability_proxy.py +462 -0
  85. ageri-0.1.0/tests/test_config_loader.py +410 -0
  86. ageri-0.1.0/tests/test_core_skill.py +518 -0
  87. ageri-0.1.0/tests/test_knowledge_engine.py +294 -0
  88. ageri-0.1.0/tests/test_memory.py +207 -0
  89. ageri-0.1.0/tests/test_orchestrator.py +964 -0
  90. ageri-0.1.0/tests/test_profile_store.py +307 -0
  91. ageri-0.1.0/tests/test_pronouns.py +47 -0
  92. ageri-0.1.0/tests/test_slack_interface.py +207 -0
  93. ageri-0.1.0/tests/test_tools.py +591 -0
  94. ageri-0.1.0/tests/test_webhook_messenger.py +272 -0
  95. ageri-0.1.0/tests/test_webhook_whatsapp.py +357 -0
  96. ageri-0.1.0/tests/test_wizard.py +812 -0
ageri-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,61 @@
1
+ Metadata-Version: 2.4
2
+ Name: ageri
3
+ Version: 0.1.0
4
+ Summary: Ageri — Personal AI Operating System
5
+ Author: Huy Do
6
+ License-Expression: LicenseRef-Proprietary
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: anthropic>=0.25
10
+ Requires-Dist: httpx>=0.27
11
+ Requires-Dist: requests>=2.31
12
+ Requires-Dist: ddgs>=7.0
13
+ Requires-Dist: schedule>=1.2
14
+ Requires-Dist: python-dotenv>=1.0
15
+ Requires-Dist: jinja2>=3.1
16
+ Requires-Dist: fastapi>=0.110
17
+ Requires-Dist: uvicorn>=0.29
18
+ Requires-Dist: websockets>=12.0
19
+ Requires-Dist: python-multipart>=0.0.9
20
+ Requires-Dist: itsdangerous>=2.1
21
+ Requires-Dist: pyyaml>=6.0
22
+ Provides-Extra: slack
23
+ Requires-Dist: slack-sdk>=3.27; extra == "slack"
24
+ Requires-Dist: slack-bolt>=1.18; extra == "slack"
25
+ Provides-Extra: docs
26
+ Requires-Dist: pypdf2>=3.0; extra == "docs"
27
+ Requires-Dist: python-docx>=1.0; extra == "docs"
28
+
29
+ # Ageri — Personal AI Operating System
30
+
31
+ Ageri is a self-hosted personal AI platform that runs 24/7, remembers everything across sessions, and coordinates specialist skills across every domain of your work and life.
32
+
33
+ ## Install
34
+
35
+ ```bash
36
+ curl -sSL https://get.ageri.ai/install.sh | bash
37
+ ```
38
+
39
+ Or on Windows (PowerShell):
40
+
41
+ ```powershell
42
+ irm https://get.ageri.ai/install.ps1 | iex
43
+ ```
44
+
45
+ ## Quick start
46
+
47
+ ```bash
48
+ ageri setup # first-time wizard (namespace → API key → password → tunnel)
49
+ ageri start # start the web server
50
+ ```
51
+
52
+ Then open **http://localhost:7821** in your browser.
53
+
54
+ ## Requirements
55
+
56
+ - Python 3.10+
57
+ - An [Anthropic API key](https://console.anthropic.com/) or Ageri hosted credits
58
+
59
+ ## Documentation
60
+
61
+ See [ageri.ai](https://ageri.ai) for full documentation.
ageri-0.1.0/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # Ageri — Personal AI Operating System
2
+
3
+ Ageri is a self-hosted personal AI platform that runs 24/7, remembers everything across sessions, and coordinates specialist skills across every domain of your work and life.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ curl -sSL https://get.ageri.ai/install.sh | bash
9
+ ```
10
+
11
+ Or on Windows (PowerShell):
12
+
13
+ ```powershell
14
+ irm https://get.ageri.ai/install.ps1 | iex
15
+ ```
16
+
17
+ ## Quick start
18
+
19
+ ```bash
20
+ ageri setup # first-time wizard (namespace → API key → password → tunnel)
21
+ ageri start # start the web server
22
+ ```
23
+
24
+ Then open **http://localhost:7821** in your browser.
25
+
26
+ ## Requirements
27
+
28
+ - Python 3.10+
29
+ - An [Anthropic API key](https://console.anthropic.com/) or Ageri hosted credits
30
+
31
+ ## Documentation
32
+
33
+ See [ageri.ai](https://ageri.ai) for full documentation.
@@ -0,0 +1,2 @@
1
+ # ageri — Personal AI Operating System
2
+ # Platform package. Apps import from ageri_sdk, not from here.
@@ -0,0 +1,161 @@
1
+ """ageri/__main__.py — Entry point for `python -m ageri [command]`.
2
+
3
+ Commands:
4
+ (none) — start the web server (default)
5
+ setup — interactive first-run wizard (namespace, key, password, tunnel)
6
+ tunnel — provision / restart the CF tunnel only
7
+ """
8
+ from __future__ import annotations
9
+
10
+ import asyncio
11
+ import logging
12
+ import os
13
+ import sys
14
+ import threading
15
+ from pathlib import Path
16
+
17
+ import uvicorn
18
+
19
+ from .config_loader import load_all
20
+ from .memory import MemoryStore
21
+ from .profile_store import ProfileStore
22
+ from .orchestrator import Orchestrator
23
+ from .bootstrap import ensure_ageri_profile
24
+ from .main import _build_registry
25
+ from .web.app import create_app
26
+ from .device import get_or_create_device_id
27
+
28
+ logger = logging.getLogger(__name__)
29
+
30
+
31
+ async def _setup_tunnel(config_dir: Path, namespace: str) -> None:
32
+ from . import tunnel
33
+ device_id = get_or_create_device_id(config_dir)
34
+
35
+ # Download cloudflared if not present
36
+ if not tunnel.is_installed(config_dir):
37
+ try:
38
+ tunnel.download_cloudflared(config_dir)
39
+ except Exception as exc:
40
+ logger.warning("Could not download cloudflared: %s", exc)
41
+ return
42
+
43
+ # Provision tunnel (idempotent — registry returns existing if already done)
44
+ try:
45
+ info = await tunnel.provision(config_dir, namespace, device_id)
46
+ tunnel.setup(config_dir, info)
47
+ tunnel.start(config_dir)
48
+ logger.info("Tunnel active: https://%s.ageri.ai", namespace)
49
+ except Exception as exc:
50
+ logger.warning("Tunnel setup failed: %s", exc)
51
+
52
+
53
+ def _run_tunnel_setup(config_dir: Path, namespace: str) -> None:
54
+ asyncio.run(_setup_tunnel(config_dir, namespace))
55
+
56
+
57
+ def main() -> None:
58
+ logging.basicConfig(
59
+ level=logging.INFO,
60
+ format="%(asctime)s %(levelname)-8s %(name)s — %(message)s",
61
+ )
62
+ config_dir = Path(os.environ.get("AGERI_HOME", Path.home() / "ageri"))
63
+ config_dir.mkdir(parents=True, exist_ok=True)
64
+
65
+ # Load config — tolerate missing properties on first run
66
+ try:
67
+ ageri_config, _ = load_all(config_dir)
68
+ except Exception:
69
+ from .config_loader import AgeriConfig
70
+ ageri_config = AgeriConfig()
71
+
72
+ port = int(os.environ.get("AGERI_PORT", getattr(ageri_config, "port", 7821)))
73
+
74
+ # Bootstrap core services
75
+ memory = MemoryStore(config_dir / "state.db")
76
+ memory.expire_working_memory()
77
+ profile_store = ProfileStore(config_dir / "state.db")
78
+ ensure_ageri_profile(profile_store)
79
+
80
+ registry = _build_registry(ageri_config)
81
+ orchestrator = Orchestrator(ageri_config, memory, registry.all(), profile_store=profile_store)
82
+
83
+ # Push notification service — enabled whenever Anthropic key is present
84
+ # (ProactiveMessenger needs it to generate messages).
85
+ from .notifications import PushService
86
+ push_service = PushService(memory) if getattr(ageri_config, "anthropic_api_key", "") else None
87
+
88
+ app = create_app(config_dir, orchestrator, memory, push_service=push_service)
89
+
90
+ # Start tunnel in background if namespace is configured
91
+ namespace = ageri_config.namespace or None
92
+ if namespace:
93
+ t = threading.Thread(target=_run_tunnel_setup, args=(config_dir, namespace), daemon=True)
94
+ t.start()
95
+
96
+ logger.info("Ageri web UI starting on http://localhost:%d", port)
97
+ uvicorn.run(app, host="0.0.0.0", port=port, log_level="warning")
98
+
99
+
100
+ def _cmd_setup() -> None:
101
+ """python -m ageri setup — run the interactive first-run wizard."""
102
+ from .setup_wizard import run as wizard_run
103
+ config_dir = Path(os.environ.get("AGERI_HOME", Path.home() / "ageri"))
104
+ wizard_run(config_dir)
105
+
106
+
107
+ def _cmd_tunnel() -> None:
108
+ """python -m ageri tunnel — provision / restart tunnel only."""
109
+ from . import tunnel as _tunnel
110
+ from .device import get_or_create_device_id
111
+ from .setup_wizard import _read_props, _green, _red, _bold, _ok, _err
112
+
113
+ config_dir = Path(os.environ.get("AGERI_HOME", Path.home() / "ageri"))
114
+ props = _read_props(config_dir)
115
+ namespace = props.get("NAMESPACE")
116
+ if not namespace:
117
+ print(_red(" ✗ No namespace configured — run: ageri setup"))
118
+ sys.exit(1)
119
+
120
+ print(f"\n {_bold('Tunnel setup')}")
121
+ if not _tunnel.is_installed(config_dir):
122
+ print(" Downloading cloudflared...", end=" ", flush=True)
123
+ try:
124
+ _tunnel.download_cloudflared(config_dir)
125
+ print(_green("done"))
126
+ except Exception as exc:
127
+ print(_red("failed"))
128
+ print(f" {_red(str(exc))}")
129
+ sys.exit(1)
130
+
131
+ print(" Provisioning...", end=" ", flush=True)
132
+ device_id = get_or_create_device_id(config_dir)
133
+ try:
134
+ info = asyncio.run(_tunnel.provision(config_dir, namespace, device_id))
135
+ _tunnel.setup(config_dir, info)
136
+ print(_green("done"))
137
+ _ok(f"https://{_bold(namespace)}.ageri.ai is live")
138
+ except Exception as exc:
139
+ print(_red("failed"))
140
+ print(f" {_red(str(exc))}")
141
+ sys.exit(1)
142
+
143
+
144
+ def cli() -> None:
145
+ """Dispatch subcommands: setup | tunnel | (default: start web server)."""
146
+ cmd = sys.argv[1] if len(sys.argv) > 1 else "start"
147
+ if cmd == "setup":
148
+ _cmd_setup()
149
+ elif cmd == "tunnel":
150
+ _cmd_tunnel()
151
+ elif cmd in ("start", "run"):
152
+ main()
153
+ elif cmd in ("-h", "--help", "help"):
154
+ print(__doc__)
155
+ else:
156
+ # Unknown arg — pass through to main (could be uvicorn flags etc.)
157
+ main()
158
+
159
+
160
+ if __name__ == "__main__":
161
+ cli()