autourgos-core
Stdlib-only shared utility library for the Autourgos framework — the concrete functions and classes that today are copy-pasted (identically or near-identically) across multiple unrelated autourgos-* package families, extracted once so a fix in one place fixes everywhere.
Status: all 6 planned modules implemented. See autourgos-core-architecture-plan.md for the full design and rollout plan (further extraction candidates in its Section 3.5 stay in their own base packages, not here).
Design principles
- Zero third-party dependencies. Standard library only — safe for even the most dependency-light packages in the framework to depend on.
- No domain knowledge.
autourgos-coredoesn't know what a memory message is, what an OpenAI response looks like, or what a Tkinter widget is. It provides primitives; domain shape stays in the package that owns that domain. - Extraction only where 2+ unrelated package families already duplicate the same logic.
Modules
| Module | Provides | Status |
|---|---|---|
text.py |
extract_text(), parse_param_descriptions() |
✅ implemented |
imports.py |
try_import(), require_available() |
✅ implemented |
versioning.py |
package_version() |
✅ implemented |
concurrency.py |
warn_once_per_agent(), retry_with_backoff(), aretry_with_backoff(), PerAgentRegistry[T], RunScopedState[T] |
✅ implemented |
sqlite_utils.py |
open_sqlite(), row_cap_evict(), ensure_parent_dir() |
✅ implemented |
threading_utils.py |
PendingCallableQueue, LazyBackgroundThread |
✅ implemented |
imports.py
from autourgos_core import try_import, require_available
available, modules, error = try_import("sounddevice")
require_available(available, f"'sounddevice' is required: {error}", ImportError)
sd = modules["sounddevice"]
text.py
from autourgos_core import extract_text, parse_param_descriptions
text = extract_text(llm.invoke("...")) # handles both a plain string and a structured_output=True dict
descs = parse_param_descriptions(inspect.getdoc(my_func)) # requires an Args:/Arguments:/Parameters: header
concurrency.py
import weakref
from autourgos_core import warn_once_per_agent
_warned_agents: "weakref.WeakSet" = weakref.WeakSet()
warn_once_per_agent(_warned_agents, agent, logger, "this only fires once per agent")
from autourgos_core import retry_with_backoff
result = retry_with_backoff(
lambda: call_flaky_api(),
max_attempts=3, backoff_base=1.0, max_backoff=30.0,
should_retry=lambda exc: not isinstance(exc, PermissionError),
on_retry=lambda exc, attempt, delay: logger.info(f"retry {attempt} in {delay}s: {exc}"),
)
from autourgos_core import PerAgentRegistry
# for middleware shared across multiple agents -- keeps each agent's state
# isolated, dropped automatically when that agent is garbage collected
_runs: "PerAgentRegistry[dict]" = PerAgentRegistry()
_runs.set(agent, {"exposed": set()})
run_state = _runs.get(agent, default_factory=dict) # creates+stores if missing
_runs.peek(agent) # read without creating
_runs.pop(agent, None)
from autourgos_core import RunScopedState
# for middleware whose state must survive being offloaded across a
# hook-executor thread pool WITHIN one invoke()/ainvoke() call, without
# leaking into a concurrent run (two threads, or two interleaved asyncio
# tasks on the same event-loop thread)
_run_ctx: "RunScopedState[dict]" = RunScopedState(default_factory=dict)
_run_ctx.get()["query"] = "..." # creates the per-run dict on first access
_run_ctx.reset() # start a fresh run in the current context
sqlite_utils.py
from autourgos_core import open_sqlite, row_cap_evict
conn = open_sqlite(db_path) # creates db_path's parent dir, sets PRAGMA journal_mode=WAL
conn.execute("CREATE TABLE IF NOT EXISTS items (id INTEGER PRIMARY KEY AUTOINCREMENT, value TEXT)")
conn.execute("INSERT INTO items (value) VALUES (?)", ("x",))
row_cap_evict(conn, "items", "id", max_rows=500) # deletes oldest rows over the cap
conn.commit()
threading_utils.py
from autourgos_core import PendingCallableQueue, LazyBackgroundThread
# post callables from any thread, drain them from the one thread allowed
# to touch the resource (e.g. a GUI toolkit's own event loop)
queue = PendingCallableQueue()
queue.post(lambda: update_widget("hi"))
queue.drain(on_error=lambda exc: logger.exception("callback raised", exc_info=exc))
# lazily start one background thread, block callers until it's ready
def run(handle: LazyBackgroundThread) -> None:
try:
setup_resource()
except Exception as exc:
handle.mark_failed(exc)
return
handle.mark_ready()
blocking_event_loop()
bg = LazyBackgroundThread(run, timeout=5.0)
bg.ensure_started() # raises on failure/timeout, no-ops on later calls
versioning.py
from autourgos_core import package_version
__version__ = package_version("autourgos-mypackage", fallback="1.2.3")
Install
pip install -e .[dev]
Test
pytest
License
Apache 2.0
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file autourgos_core-0.10.0.tar.gz.
File metadata
- Download URL: autourgos_core-0.10.0.tar.gz
- Upload date:
- Size: 30.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0c301ff79308184c0ed99bef3f3bed6c94aac68063ef508dfe39d92aab2529ec
|
|
| MD5 |
9233d9450c69e824f05c457f6f633b7c
|
|
| BLAKE2b-256 |
a6e0c4e54762ae3acfbb03ddb524335d4d09771cb1235838e60f6d4a0d019904
|
File details
Details for the file autourgos_core-0.10.0-py3-none-any.whl.
File metadata
- Download URL: autourgos_core-0.10.0-py3-none-any.whl
- Upload date:
- Size: 23.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af59a2a1f405edb241dcfd9709f7ccda01980cb61beaf91a18e9de2b41045a01
|
|
| MD5 |
2be291008bd522bd3ffdaa40691e263e
|
|
| BLAKE2b-256 |
a135e1c5e9453d78336e5038387e09ccc06e3b88404c193d8d1b4d87a34f7ed6
|