diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 096ded3..c124767 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -59,7 +59,7 @@ jobs: - name: Install sshd # The tests reach "the build VM" over real SSH, through a throwaway - # sshd the test fixture starts (nisse_core/testing.py). Skipped when the image has it; otherwise from + # sshd the test fixture starts (nisse_core/execution/testing.py). Skipped when the image has it; otherwise from # a kernel.org mirror: archive.ubuntu.com has been slow enough to add # minutes to every job. run: scripts/ci-sshd.sh diff --git a/conftest.py b/conftest.py index 2cc7e20..5e26e1f 100644 --- a/conftest.py +++ b/conftest.py @@ -5,8 +5,8 @@ from pathlib import Path import pytest -from nisse_core.execution import SSHHost -from nisse_core.testing import local_sshd +from nisse_core.execution.ssh import SSHHost +from nisse_core.execution.testing import local_sshd @pytest.fixture(scope="session") diff --git a/docs/Development-Plan.md b/docs/Development-Plan.md index 85c3deb..3cc2bfe 100644 --- a/docs/Development-Plan.md +++ b/docs/Development-Plan.md @@ -312,7 +312,7 @@ the live session's fixes in #119 and #122). `nisse-dev` runs only the loop. **M3.1 Action classes and the fast path.** *Needs discussion.* **Done** (this PR). Harmless, contained and dangerous actions per agent (P3, D6), static fast-path rules. -- `nisse_core.actions` (the shared part, `nisse-core`'s first code): `Action`, +- `nisse_core.authority.actions` (the shared part, `nisse-core`'s first code): `Action`, `Verdict`, and reading shell commands statically, segment by segment (`cd`, wrappers like `sudo` and `timeout`, `sh -c`); what can't be read that way is unknown, and a line is as bad as its worst command. @@ -567,7 +567,7 @@ the vault and memory, logging, `.env` loading, and the Gitea client (whole: L1 makes Gitea every agent's tracker). `nisse-core` never imports an agent (a test says so). -- `nisse_core.state.StateStore` holds the tables every agent has; an agent's +- `nisse_core.state.store.StateStore` holds the tables every agent has; an agent's subclass adds its own tables (with their schema version and migrations), its model roles, and what each role is shown of the others (`views`). `nisse_dev.state.StateStore` adds the build VM blocks (D3); stores already at @@ -578,6 +578,10 @@ says so). agent's `git`, delegation, `ask_expert`, executor tools and evaluation capture stay in `nisse-dev`. +**Core packages.** *Done.* `nisse-core`'s modules grouped into packages by +architecture section (`models`, `log`, `state`, `knowledge`, `conversation`, +`execution`, `authority`), as a pure move ahead of M7.2. + **M7.2 Share the loop.** *Needs discussion.* What of `nisse_dev.loop` and `config` is any agent's moves to `nisse-core`, shaped by what `nisse-review` needs; `nisse-dev` runs on it unchanged. diff --git a/nisse-core/README.md b/nisse-core/README.md index f9f8d95..172b8cc 100644 --- a/nisse-core/README.md +++ b/nisse-core/README.md @@ -1,22 +1,24 @@ # nisse-core The shared library the Nisse agents sit on (Part L of the architecture). It -never imports an agent. +never imports an agent. Packages follow the architecture's sections: -- **Transcript and models:** `canonical` (the log's events, L7), `render` and - `render_anthropic`, `llm` (the one client, L9), `catalog` and `probe` (what - the models are), `context` (fitting a request to its window, L6), `views` - (what each role is shown of the others). -- **Durability:** `state` (the store, L8; an agent subclasses it for its own - tables, roles and views), `reconcile`, `worker`, `cancel`, `dump`. -- **Conversation:** `transport`, `matrix` (L5). -- **Execution:** `execution` (SSH to a tool VM, L13); `testing` (a throwaway - sshd for tests). -- **Knowledge:** `vault` (L10), `memory` (L6.4). -- **Operations:** `oplog`, `envfile` (L12); `gitea` (the tracker and forge, L1). -- **Authority:** `actions` (P3, P4, L4): `Action`, `Verdict`, and static - reading of shell commands, which each agent's fast-path rules build on - (`nisse-dev`'s are in `nisse_dev.loop.actions`). +- `models` (L9, L7): `llm` (the one client), `catalog` and `probe` (what the + models are), `render` and `render_anthropic` (request bodies from the log), + `context` (fitting a request to its window, L6). +- `log` (L7, L6): `canonical` (the log's events), `views` (what each role is + shown of the others). +- `state` (L8): `store` (an agent subclasses `StateStore` for its own tables, + roles and views), `reconcile`, `worker`, `cancel`, `dump`. +- `knowledge` (L10, L6.4): `vault`, `memory`. +- `conversation` (L5): `transport`, `matrix`. +- `execution` (L13): `ssh` (SSH to a tool VM); `testing` (a throwaway sshd for + tests). +- `authority` (P3, P4, L4): `actions` (`Action`, `Verdict`, and static reading of + shell commands, which each agent's fast-path rules build on; `nisse-dev`'s are + in `nisse_dev.loop.actions`). +- At the top, until each gains a second module: `gitea` (the tracker and forge, + L1), `oplog` and `envfile` (L12). -The loop is still `nisse-dev`'s, until `nisse-ops` has one to share it with -(Development Plan M7.2). +The parts of a loop (`loop`) and shared configuration arrive with Development +Plan M7.2; each agent keeps its own scheduler. diff --git a/nisse-core/src/nisse_core/authority/__init__.py b/nisse-core/src/nisse_core/authority/__init__.py new file mode 100644 index 0000000..53a652e --- /dev/null +++ b/nisse-core/src/nisse_core/authority/__init__.py @@ -0,0 +1 @@ +"""Actions by their effects (architecture P3, P4, L3, L4).""" diff --git a/nisse-core/src/nisse_core/actions.py b/nisse-core/src/nisse_core/authority/actions.py similarity index 100% rename from nisse-core/src/nisse_core/actions.py rename to nisse-core/src/nisse_core/authority/actions.py diff --git a/nisse-core/src/nisse_core/conversation/__init__.py b/nisse-core/src/nisse_core/conversation/__init__.py new file mode 100644 index 0000000..98c6ffd --- /dev/null +++ b/nisse-core/src/nisse_core/conversation/__init__.py @@ -0,0 +1 @@ +"""Conversation with the operator (architecture L5).""" diff --git a/nisse-core/src/nisse_core/matrix.py b/nisse-core/src/nisse_core/conversation/matrix.py similarity index 99% rename from nisse-core/src/nisse_core/matrix.py rename to nisse-core/src/nisse_core/conversation/matrix.py index f4721b2..93dbf99 100644 --- a/nisse-core/src/nisse_core/matrix.py +++ b/nisse-core/src/nisse_core/conversation/matrix.py @@ -27,7 +27,7 @@ from urllib.parse import unquote import httpx -from nisse_core.transport import InboundMessage +from nisse_core.conversation.transport import InboundMessage # A mention pill at the start of an HTML body: the link holds the user ID, # the link text is what the plain body starts with. diff --git a/nisse-core/src/nisse_core/transport.py b/nisse-core/src/nisse_core/conversation/transport.py similarity index 100% rename from nisse-core/src/nisse_core/transport.py rename to nisse-core/src/nisse_core/conversation/transport.py diff --git a/nisse-core/src/nisse_core/execution/__init__.py b/nisse-core/src/nisse_core/execution/__init__.py new file mode 100644 index 0000000..5787202 --- /dev/null +++ b/nisse-core/src/nisse_core/execution/__init__.py @@ -0,0 +1 @@ +"""Running commands on tool VMs over SSH (architecture L13).""" diff --git a/nisse-core/src/nisse_core/execution.py b/nisse-core/src/nisse_core/execution/ssh.py similarity index 100% rename from nisse-core/src/nisse_core/execution.py rename to nisse-core/src/nisse_core/execution/ssh.py diff --git a/nisse-core/src/nisse_core/testing.py b/nisse-core/src/nisse_core/execution/testing.py similarity index 98% rename from nisse-core/src/nisse_core/testing.py rename to nisse-core/src/nisse_core/execution/testing.py index a0f2855..e6238f3 100644 --- a/nisse-core/src/nisse_core/testing.py +++ b/nisse-core/src/nisse_core/execution/testing.py @@ -14,7 +14,7 @@ from collections.abc import Iterator from contextlib import contextmanager from pathlib import Path -from nisse_core.execution import SSHHost +from nisse_core.execution.ssh import SSHHost SSHD = "/usr/sbin/sshd" diff --git a/nisse-core/src/nisse_core/gitea.py b/nisse-core/src/nisse_core/gitea.py index 49b4d0a..236b12d 100644 --- a/nisse-core/src/nisse_core/gitea.py +++ b/nisse-core/src/nisse_core/gitea.py @@ -16,8 +16,8 @@ from typing import Any import httpx -from nisse_core.reconcile import Reconciler -from nisse_core.state import Intent +from nisse_core.state.reconcile import Reconciler +from nisse_core.state.store import Intent PR_PAGE_SIZE = 50 MAX_PR_PAGES = 40 # 2000 PRs; beyond that, say so rather than guess diff --git a/nisse-core/src/nisse_core/knowledge/__init__.py b/nisse-core/src/nisse_core/knowledge/__init__.py new file mode 100644 index 0000000..d9836ce --- /dev/null +++ b/nisse-core/src/nisse_core/knowledge/__init__.py @@ -0,0 +1 @@ +"""The knowledge vault (architecture L10) and agent memory (L6.4).""" diff --git a/nisse-core/src/nisse_core/memory.py b/nisse-core/src/nisse_core/knowledge/memory.py similarity index 98% rename from nisse-core/src/nisse_core/memory.py rename to nisse-core/src/nisse_core/knowledge/memory.py index 2f99f97..949c347 100644 --- a/nisse-core/src/nisse_core/memory.py +++ b/nisse-core/src/nisse_core/knowledge/memory.py @@ -14,7 +14,7 @@ from dataclasses import dataclass import yaml -from nisse_core.vault import Vault, VaultError, split_frontmatter +from nisse_core.knowledge.vault import Vault, VaultError, split_frontmatter INDEX = "index" # the note the harness keeps; never the model's _NAME = re.compile(r"[a-z0-9][a-z0-9-]{0,63}") diff --git a/nisse-core/src/nisse_core/vault.py b/nisse-core/src/nisse_core/knowledge/vault.py similarity index 100% rename from nisse-core/src/nisse_core/vault.py rename to nisse-core/src/nisse_core/knowledge/vault.py diff --git a/nisse-core/src/nisse_core/log/__init__.py b/nisse-core/src/nisse_core/log/__init__.py new file mode 100644 index 0000000..6802c7a --- /dev/null +++ b/nisse-core/src/nisse_core/log/__init__.py @@ -0,0 +1,2 @@ +"""The canonical log (architecture L7) and what each role is shown of it +(L6).""" diff --git a/nisse-core/src/nisse_core/canonical.py b/nisse-core/src/nisse_core/log/canonical.py similarity index 100% rename from nisse-core/src/nisse_core/canonical.py rename to nisse-core/src/nisse_core/log/canonical.py diff --git a/nisse-core/src/nisse_core/views.py b/nisse-core/src/nisse_core/log/views.py similarity index 99% rename from nisse-core/src/nisse_core/views.py rename to nisse-core/src/nisse_core/log/views.py index c7cd109..d58e1f2 100644 --- a/nisse-core/src/nisse_core/views.py +++ b/nisse-core/src/nisse_core/log/views.py @@ -20,7 +20,7 @@ ranges still line up with the log. Everything not the viewer's own becomes a from collections.abc import Mapping from dataclasses import replace -from nisse_core.canonical import ( +from nisse_core.log.canonical import ( ActionVerdict, AssistantText, DelegationCompleted, diff --git a/nisse-core/src/nisse_core/models/__init__.py b/nisse-core/src/nisse_core/models/__init__.py new file mode 100644 index 0000000..9d8788c --- /dev/null +++ b/nisse-core/src/nisse_core/models/__init__.py @@ -0,0 +1,2 @@ +"""Talking to models (architecture L9): the client, what the models are, and +the request bodies built from the log (L7).""" diff --git a/nisse-core/src/nisse_core/catalog.py b/nisse-core/src/nisse_core/models/catalog.py similarity index 99% rename from nisse-core/src/nisse_core/catalog.py rename to nisse-core/src/nisse_core/models/catalog.py index 3af21b3..f225711 100644 --- a/nisse-core/src/nisse_core/catalog.py +++ b/nisse-core/src/nisse_core/models/catalog.py @@ -19,7 +19,7 @@ from typing import Any import httpx -from nisse_core.llm import LLMClient, LLMError +from nisse_core.models.llm import LLMClient, LLMError # LiteLLM's provider name for models we have a vendor-native adapter for. ANTHROPIC_PROVIDER = "anthropic" diff --git a/nisse-core/src/nisse_core/context.py b/nisse-core/src/nisse_core/models/context.py similarity index 98% rename from nisse-core/src/nisse_core/context.py rename to nisse-core/src/nisse_core/models/context.py index c812f27..8cd3d71 100644 --- a/nisse-core/src/nisse_core/context.py +++ b/nisse-core/src/nisse_core/models/context.py @@ -28,7 +28,7 @@ from collections.abc import Callable, Sequence from dataclasses import dataclass, replace from typing import Any -from nisse_core.canonical import ( +from nisse_core.log.canonical import ( AssistantText, CanonicalEvent, DelegationStarted, @@ -38,7 +38,7 @@ from nisse_core.canonical import ( ToolResult, UserMessage, ) -from nisse_core.llm import DEFAULT_MAX_OUTPUT_TOKENS, LLMError +from nisse_core.models.llm import DEFAULT_MAX_OUTPUT_TOKENS, LLMError # English and code run at about four characters a token. Three is deliberately # pessimistic, before any correction from what the server reports. diff --git a/nisse-core/src/nisse_core/llm.py b/nisse-core/src/nisse_core/models/llm.py similarity index 99% rename from nisse-core/src/nisse_core/llm.py rename to nisse-core/src/nisse_core/models/llm.py index 8ec99dc..d71b5ff 100644 --- a/nisse-core/src/nisse_core/llm.py +++ b/nisse-core/src/nisse_core/models/llm.py @@ -17,15 +17,15 @@ from typing import Any, ClassVar, Protocol import httpx -from nisse_core.canonical import ( +from nisse_core.log.canonical import ( AssistantText, CanonicalEvent, StoredEvent, ToolCall, mint_call_id, ) -from nisse_core.render import OpenAIChatRenderer -from nisse_core.render_anthropic import AnthropicMessagesRenderer +from nisse_core.models.render import OpenAIChatRenderer +from nisse_core.models.render_anthropic import AnthropicMessagesRenderer class LLMError(RuntimeError): diff --git a/nisse-core/src/nisse_core/probe.py b/nisse-core/src/nisse_core/models/probe.py similarity index 99% rename from nisse-core/src/nisse_core/probe.py rename to nisse-core/src/nisse_core/models/probe.py index acf515f..1c016c3 100644 --- a/nisse-core/src/nisse_core/probe.py +++ b/nisse-core/src/nisse_core/models/probe.py @@ -24,7 +24,7 @@ from dataclasses import dataclass import httpx -from nisse_core.catalog import ModelFacts +from nisse_core.models.catalog import ModelFacts # Of a probe's size, how much must come back for it to count as uncut. A # chat template adds a little, and a tokenizer counts a little differently. diff --git a/nisse-core/src/nisse_core/render.py b/nisse-core/src/nisse_core/models/render.py similarity index 99% rename from nisse-core/src/nisse_core/render.py rename to nisse-core/src/nisse_core/models/render.py index 16dd2dc..b3d5b23 100644 --- a/nisse-core/src/nisse_core/render.py +++ b/nisse-core/src/nisse_core/models/render.py @@ -11,7 +11,7 @@ this skeleton. import json from typing import Any -from nisse_core.canonical import ( +from nisse_core.log.canonical import ( AssistantText, Compaction, DelegationCompleted, diff --git a/nisse-core/src/nisse_core/render_anthropic.py b/nisse-core/src/nisse_core/models/render_anthropic.py similarity index 98% rename from nisse-core/src/nisse_core/render_anthropic.py rename to nisse-core/src/nisse_core/models/render_anthropic.py index 763ba67..faba15b 100644 --- a/nisse-core/src/nisse_core/render_anthropic.py +++ b/nisse-core/src/nisse_core/models/render_anthropic.py @@ -18,7 +18,7 @@ route and this renderer builds the vendor-native body. from typing import Any -from nisse_core.canonical import ( +from nisse_core.log.canonical import ( AssistantText, Compaction, DelegationCompleted, @@ -31,7 +31,7 @@ from nisse_core.canonical import ( ToolResult, UserMessage, ) -from nisse_core.render import effective_events +from nisse_core.models.render import effective_events DEFAULT_MAX_TOKENS = 4096 NO_RESULT_PLACEHOLDER = "[no result recorded]" diff --git a/nisse-core/src/nisse_core/state/__init__.py b/nisse-core/src/nisse_core/state/__init__.py new file mode 100644 index 0000000..3879133 --- /dev/null +++ b/nisse-core/src/nisse_core/state/__init__.py @@ -0,0 +1,2 @@ +"""Durability (architecture L8): the state store, reconciliation, the worker +thread and the kill switch.""" diff --git a/nisse-core/src/nisse_core/cancel.py b/nisse-core/src/nisse_core/state/cancel.py similarity index 91% rename from nisse-core/src/nisse_core/cancel.py rename to nisse-core/src/nisse_core/state/cancel.py index 8b03de4..2cae36b 100644 --- a/nisse-core/src/nisse_core/cancel.py +++ b/nisse-core/src/nisse_core/state/cancel.py @@ -8,8 +8,8 @@ record of a stop is written by the worker when the stopped work returns. import threading -from nisse_core.canonical import ToolCall, ToolResult -from nisse_core.state import Transcript +from nisse_core.log.canonical import ToolCall, ToolResult +from nisse_core.state.store import Transcript STOPPED_RESULT = "not run: the operator stopped the agent" diff --git a/nisse-core/src/nisse_core/dump.py b/nisse-core/src/nisse_core/state/dump.py similarity index 98% rename from nisse-core/src/nisse_core/dump.py rename to nisse-core/src/nisse_core/state/dump.py index 8575969..24590f4 100644 --- a/nisse-core/src/nisse_core/dump.py +++ b/nisse-core/src/nisse_core/state/dump.py @@ -1,6 +1,6 @@ """A readable dump of a state store, for bring-up runs and debugging. - python -m nisse_core.dump STATE_DB [--full] + python -m nisse_core.state.dump STATE_DB [--full] Opens the store read-only (SQLite `mode=ro`), so it is safe to run against a live agent's database: it never migrates, writes or locks it. Prints the work diff --git a/nisse-core/src/nisse_core/reconcile.py b/nisse-core/src/nisse_core/state/reconcile.py similarity index 97% rename from nisse-core/src/nisse_core/reconcile.py rename to nisse-core/src/nisse_core/state/reconcile.py index f7dbe6e..b6ca8cb 100644 --- a/nisse-core/src/nisse_core/reconcile.py +++ b/nisse-core/src/nisse_core/state/reconcile.py @@ -11,7 +11,7 @@ from collections.abc import Callable, Mapping from dataclasses import dataclass from typing import Literal -from nisse_core.state import Intent, StateStore +from nisse_core.state.store import Intent, StateStore # Returns True if the intent's external effect verifiably happened (do not # repeat it), False if it verifiably never started (safe to discard), or diff --git a/nisse-core/src/nisse_core/state.py b/nisse-core/src/nisse_core/state/store.py similarity index 99% rename from nisse-core/src/nisse_core/state.py rename to nisse-core/src/nisse_core/state/store.py index 18c2f55..f4e8a78 100644 --- a/nisse-core/src/nisse_core/state.py +++ b/nisse-core/src/nisse_core/state/store.py @@ -6,7 +6,7 @@ intent-log write is a single immediately-committed statement — in-memory state that hasn't hit disk is assumed lost. The intent log records a unit of work *before* it starts, so a restart knows -what was in flight (see ``nisse_core.reconcile`` for how pending intents are +what was in flight (see ``nisse_core.state.reconcile`` for how pending intents are resolved against external truth on boot). """ @@ -18,7 +18,7 @@ from datetime import UTC, datetime from pathlib import Path from typing import Any, Self -from nisse_core.canonical import ( +from nisse_core.log.canonical import ( CanonicalEvent, StoredEvent, UserMessage, @@ -26,8 +26,8 @@ from nisse_core.canonical import ( from_payload, to_payload, ) +from nisse_core.log.views import project from nisse_core.oplog import OpLog -from nisse_core.views import project # The tables every agent has. An agent's own tables come on top: a subclass # names them, the version they bring, and the migrations to it. diff --git a/nisse-core/src/nisse_core/worker.py b/nisse-core/src/nisse_core/state/worker.py similarity index 100% rename from nisse-core/src/nisse_core/worker.py rename to nisse-core/src/nisse_core/state/worker.py diff --git a/nisse-core/tests/test_actions.py b/nisse-core/tests/test_actions.py index 2afde14..ef45106 100644 --- a/nisse-core/tests/test_actions.py +++ b/nisse-core/tests/test_actions.py @@ -1,6 +1,6 @@ import pytest -from nisse_core.actions import ( +from nisse_core.authority.actions import ( CONTAINED, DANGEROUS, HARMLESS, diff --git a/nisse-core/tests/test_canonical.py b/nisse-core/tests/test_canonical.py index 40c2af1..b428c26 100644 --- a/nisse-core/tests/test_canonical.py +++ b/nisse-core/tests/test_canonical.py @@ -3,7 +3,7 @@ from pathlib import Path import pytest -from nisse_core.canonical import ( +from nisse_core.log.canonical import ( AssistantText, Compaction, DelegationCompleted, @@ -16,7 +16,7 @@ from nisse_core.canonical import ( from_payload, mint_call_id, ) -from nisse_core.state import StateSchemaError, StateStore +from nisse_core.state.store import StateSchemaError, StateStore ALL_EVENTS = [ UserMessage(text="use demo", source="matrix:$abc"), diff --git a/nisse-core/tests/test_catalog.py b/nisse-core/tests/test_catalog.py index e07f5e1..5a21874 100644 --- a/nisse-core/tests/test_catalog.py +++ b/nisse-core/tests/test_catalog.py @@ -8,7 +8,7 @@ route has to come from what LiteLLM says the model is. import httpx import pytest -from nisse_core.catalog import ( +from nisse_core.models.catalog import ( CatalogUnavailable, ModelCatalog, UnknownModel, diff --git a/nisse-core/tests/test_context.py b/nisse-core/tests/test_context.py index 12d7192..a52000e 100644 --- a/nisse-core/tests/test_context.py +++ b/nisse-core/tests/test_context.py @@ -6,7 +6,7 @@ from typing import Any import pytest -from nisse_core.canonical import ( +from nisse_core.log.canonical import ( AssistantText, CanonicalEvent, StoredEvent, @@ -14,8 +14,8 @@ from nisse_core.canonical import ( ToolResult, UserMessage, ) -from nisse_core.catalog import ModelCatalog, UnknownLimits -from nisse_core.context import ( +from nisse_core.models.catalog import ModelCatalog, UnknownLimits +from nisse_core.models.context import ( Budget, BudgetedClient, ContextOverflow, @@ -24,7 +24,7 @@ from nisse_core.context import ( head_and_tail, ) from nisse_core.oplog import OpLog -from nisse_core.state import StateStore +from nisse_core.state.store import StateStore from nisse_dev.loop.driver import Driver diff --git a/nisse-core/tests/test_dump.py b/nisse-core/tests/test_dump.py index 0e9eba1..fcda8a7 100644 --- a/nisse-core/tests/test_dump.py +++ b/nisse-core/tests/test_dump.py @@ -1,10 +1,16 @@ import io from pathlib import Path -from nisse_core.canonical import Fact, PlanSubmitted, ToolCall, ToolResult, UserMessage -from nisse_core.dump import main, render +from nisse_core.log.canonical import ( + Fact, + PlanSubmitted, + ToolCall, + ToolResult, + UserMessage, +) from nisse_core.oplog import OpLog -from nisse_core.state import StateStore +from nisse_core.state.dump import main, render +from nisse_core.state.store import StateStore def store_with_a_run(path: Path) -> None: diff --git a/nisse-core/tests/test_execution.py b/nisse-core/tests/test_execution.py index 60cec7a..d98563a 100644 --- a/nisse-core/tests/test_execution.py +++ b/nisse-core/tests/test_execution.py @@ -5,7 +5,7 @@ from pathlib import Path import pytest -from nisse_core.execution import REDACTED, HostUnavailable, SSHHost, redact +from nisse_core.execution.ssh import REDACTED, HostUnavailable, SSHHost, redact def test_exit_codes_and_streams_come_back(ssh_host: SSHHost) -> None: @@ -82,7 +82,7 @@ def test_a_changed_host_key_is_its_own_failure_and_only_forgetting_clears_it( ) -> None: import subprocess - from nisse_core.execution import HostKeyChanged + from nisse_core.execution.ssh import HostKeyChanged host = SSHHost( ssh_host.address, diff --git a/nisse-core/tests/test_gitea.py b/nisse-core/tests/test_gitea.py index c88fbbb..c644bba 100644 --- a/nisse-core/tests/test_gitea.py +++ b/nisse-core/tests/test_gitea.py @@ -10,7 +10,7 @@ from nisse_core.gitea import ( GiteaError, pull_request_reconciler, ) -from nisse_core.state import Intent +from nisse_core.state.store import Intent INTENT = Intent( id=1, diff --git a/nisse-core/tests/test_llm.py b/nisse-core/tests/test_llm.py index 65fe27e..46aad3c 100644 --- a/nisse-core/tests/test_llm.py +++ b/nisse-core/tests/test_llm.py @@ -5,14 +5,14 @@ from typing import Any import httpx import pytest -from nisse_core.canonical import ( +from nisse_core.envfile import load_env_file +from nisse_core.log.canonical import ( AssistantText, StoredEvent, ToolCall, UserMessage, ) -from nisse_core.envfile import load_env_file -from nisse_core.llm import ( +from nisse_core.models.llm import ( DEFAULT_MAX_OUTPUT_TOKENS, OUTAGE_BACKOFF_S, RATE_LIMIT_RETRY_S, diff --git a/nisse-core/tests/test_matrix.py b/nisse-core/tests/test_matrix.py index 7d59c0c..0e66985 100644 --- a/nisse-core/tests/test_matrix.py +++ b/nisse-core/tests/test_matrix.py @@ -4,8 +4,8 @@ import threading import httpx import pytest -from nisse_core.matrix import MatrixConfig, MatrixTransport, TransportError -from nisse_core.transport import InboundMessage +from nisse_core.conversation.matrix import MatrixConfig, MatrixTransport, TransportError +from nisse_core.conversation.transport import InboundMessage CONFIG = MatrixConfig( homeserver="https://matrix.test", @@ -349,7 +349,7 @@ def test_a_reply_to_the_operators_own_threaded_message_joins_the_thread() -> Non def test_in_memory_transport_plays_threads() -> None: - from nisse_core.transport import InMemoryTransport + from nisse_core.conversation.transport import InMemoryTransport transport = InMemoryTransport() seen: list[InboundMessage] = [] diff --git a/nisse-core/tests/test_memory.py b/nisse-core/tests/test_memory.py index 8659196..d88c565 100644 --- a/nisse-core/tests/test_memory.py +++ b/nisse-core/tests/test_memory.py @@ -5,8 +5,8 @@ from pathlib import Path import pytest -from nisse_core.memory import Memory -from nisse_core.vault import Vault, VaultError, split_frontmatter +from nisse_core.knowledge.memory import Memory +from nisse_core.knowledge.vault import Vault, VaultError, split_frontmatter FOLDER = "memory/nisse-dev" diff --git a/nisse-core/tests/test_oplog.py b/nisse-core/tests/test_oplog.py index 4be77be..fa4f612 100644 --- a/nisse-core/tests/test_oplog.py +++ b/nisse-core/tests/test_oplog.py @@ -9,8 +9,8 @@ from pathlib import Path import pytest from nisse_core.oplog import OpLog -from nisse_core.reconcile import reconcile_on_boot -from nisse_core.state import StateStore +from nisse_core.state.reconcile import reconcile_on_boot +from nisse_core.state.store import StateStore ENVELOPE_FIELDS = {"ts", "agent", "event", "task_id", "cause"} diff --git a/nisse-core/tests/test_probe.py b/nisse-core/tests/test_probe.py index 2991b7e..85085fc 100644 --- a/nisse-core/tests/test_probe.py +++ b/nisse-core/tests/test_probe.py @@ -2,7 +2,7 @@ import json import httpx -from nisse_core.probe import interpret, probe +from nisse_core.models.probe import interpret, probe def test_a_cut_at_the_declared_window_matches() -> None: diff --git a/nisse-core/tests/test_reconcile.py b/nisse-core/tests/test_reconcile.py index 4ad5f16..4a08501 100644 --- a/nisse-core/tests/test_reconcile.py +++ b/nisse-core/tests/test_reconcile.py @@ -2,8 +2,8 @@ from pathlib import Path import pytest -from nisse_core.reconcile import reconcile_on_boot -from nisse_core.state import Intent, StateStore +from nisse_core.state.reconcile import reconcile_on_boot +from nisse_core.state.store import Intent, StateStore @pytest.fixture diff --git a/nisse-core/tests/test_render.py b/nisse-core/tests/test_render.py index 87de5e2..06f5280 100644 --- a/nisse-core/tests/test_render.py +++ b/nisse-core/tests/test_render.py @@ -1,7 +1,7 @@ import json from itertools import pairwise -from nisse_core.canonical import ( +from nisse_core.log.canonical import ( AssistantText, Compaction, GateOpened, @@ -10,7 +10,7 @@ from nisse_core.canonical import ( ToolResult, UserMessage, ) -from nisse_core.render import OpenAIChatRenderer, effective_events +from nisse_core.models.render import OpenAIChatRenderer, effective_events def stored(events: list) -> list[StoredEvent]: diff --git a/nisse-core/tests/test_render_anthropic.py b/nisse-core/tests/test_render_anthropic.py index 79ea1a0..5d7345c 100644 --- a/nisse-core/tests/test_render_anthropic.py +++ b/nisse-core/tests/test_render_anthropic.py @@ -4,7 +4,7 @@ these tests pin the differences that a normalising middlebox would blur.""" import httpx import pytest -from nisse_core.canonical import ( +from nisse_core.log.canonical import ( AssistantText, Compaction, StoredEvent, @@ -12,8 +12,8 @@ from nisse_core.canonical import ( ToolResult, UserMessage, ) -from nisse_core.llm import AnthropicPassthroughClient, LLMError -from nisse_core.render_anthropic import ( +from nisse_core.models.llm import AnthropicPassthroughClient, LLMError +from nisse_core.models.render_anthropic import ( AnthropicMessagesRenderer, to_anthropic_tools, ) diff --git a/nisse-core/tests/test_state.py b/nisse-core/tests/test_state.py index 5a52ac3..6fce1ef 100644 --- a/nisse-core/tests/test_state.py +++ b/nisse-core/tests/test_state.py @@ -3,7 +3,7 @@ from pathlib import Path import pytest -from nisse_core.state import StateSchemaError, StateStore +from nisse_core.state.store import StateSchemaError, StateStore @pytest.fixture diff --git a/nisse-core/tests/test_vault.py b/nisse-core/tests/test_vault.py index b1430b0..0e39308 100644 --- a/nisse-core/tests/test_vault.py +++ b/nisse-core/tests/test_vault.py @@ -9,8 +9,8 @@ from pathlib import Path import pytest import yaml -from nisse_core import vault as vault_module -from nisse_core.vault import Vault, VaultError, split_frontmatter +from nisse_core.knowledge import vault as vault_module +from nisse_core.knowledge.vault import Vault, VaultError, split_frontmatter @pytest.fixture diff --git a/nisse-core/tests/test_views.py b/nisse-core/tests/test_views.py index 2470453..ee2ac17 100644 --- a/nisse-core/tests/test_views.py +++ b/nisse-core/tests/test_views.py @@ -4,7 +4,7 @@ import io from collections.abc import Mapping from pathlib import Path -from nisse_core.canonical import ( +from nisse_core.log.canonical import ( AssistantText, DelegationCompleted, DelegationStarted, @@ -15,10 +15,10 @@ from nisse_core.canonical import ( ToolResult, UserMessage, ) +from nisse_core.models.render import OpenAIChatRenderer +from nisse_core.models.render_anthropic import AnthropicMessagesRenderer from nisse_core.oplog import OpLog -from nisse_core.render import OpenAIChatRenderer -from nisse_core.render_anthropic import AnthropicMessagesRenderer -from nisse_core.state import StateStore +from nisse_core.state.store import StateStore class Store(StateStore): diff --git a/nisse-core/tests/test_worker.py b/nisse-core/tests/test_worker.py index 7eba8af..baad193 100644 --- a/nisse-core/tests/test_worker.py +++ b/nisse-core/tests/test_worker.py @@ -5,8 +5,8 @@ from pathlib import Path import pytest from nisse_core.oplog import OpLog -from nisse_core.state import StateStore -from nisse_core.worker import InlineWorker, SerialWorker +from nisse_core.state.store import StateStore +from nisse_core.state.worker import InlineWorker, SerialWorker @pytest.fixture diff --git a/nisse-dev/src/nisse_dev/bench/runner.py b/nisse-dev/src/nisse_dev/bench/runner.py index de80c7b..927ce9d 100644 --- a/nisse-dev/src/nisse_dev/bench/runner.py +++ b/nisse-dev/src/nisse_dev/bench/runner.py @@ -11,7 +11,8 @@ from datetime import UTC, datetime from pathlib import Path from typing import Any -from nisse_core.canonical import ( +from nisse_core.execution.ssh import SSHHost +from nisse_core.log.canonical import ( CanonicalEvent, Fact, StoredEvent, @@ -19,8 +20,7 @@ from nisse_core.canonical import ( ToolResult, UserMessage, ) -from nisse_core.catalog import ModelFacts -from nisse_core.execution import SSHHost +from nisse_core.models.catalog import ModelFacts from nisse_core.oplog import OpLog from nisse_dev.bench.tasks import Task from nisse_dev.config import Tuning diff --git a/nisse-dev/src/nisse_dev/config.py b/nisse-dev/src/nisse_dev/config.py index 8c6360d..6f85abf 100644 --- a/nisse-dev/src/nisse_dev/config.py +++ b/nisse-dev/src/nisse_dev/config.py @@ -23,9 +23,13 @@ from typing import Any import yaml -from nisse_core.llm import DEFAULT_MAX_OUTPUT_TOKENS, DEFAULT_REQUEST_TIMEOUT_S, RoleMap -from nisse_core.matrix import MatrixConfig -from nisse_core.vault import ACCESS, DEFAULT_IGNORE +from nisse_core.conversation.matrix import MatrixConfig +from nisse_core.knowledge.vault import ACCESS, DEFAULT_IGNORE +from nisse_core.models.llm import ( + DEFAULT_MAX_OUTPUT_TOKENS, + DEFAULT_REQUEST_TIMEOUT_S, + RoleMap, +) DEFAULT_CONFIG_FILE = "nisse-dev.yaml" diff --git a/nisse-dev/src/nisse_dev/delegation.py b/nisse-dev/src/nisse_dev/delegation.py index f54cda9..a579f8c 100644 --- a/nisse-dev/src/nisse_dev/delegation.py +++ b/nisse-dev/src/nisse_dev/delegation.py @@ -28,8 +28,7 @@ from collections.abc import Callable from dataclasses import dataclass, field from typing import Any, Literal -from nisse_core.cancel import Cancel, skip_calls -from nisse_core.canonical import ( +from nisse_core.log.canonical import ( AssistantText, DelegationCompleted, DelegationStarted, @@ -39,9 +38,10 @@ from nisse_core.canonical import ( ToolCall, ToolResult, ) -from nisse_core.llm import LLMClient, LLMError, UpstreamUnavailable -from nisse_core.reconcile import Reconciler -from nisse_core.state import Intent, Transcript +from nisse_core.models.llm import LLMClient, LLMError, UpstreamUnavailable +from nisse_core.state.cancel import Cancel, skip_calls +from nisse_core.state.reconcile import Reconciler +from nisse_core.state.store import Intent, Transcript from nisse_dev.git import GitError, GitRepo from nisse_dev.state import StateStore from nisse_dev.tools import EXECUTION_TOOLS, MUTATING_TOOLS, Workspace diff --git a/nisse-dev/src/nisse_dev/evals.py b/nisse-dev/src/nisse_dev/evals.py index 59e9f33..230114b 100644 --- a/nisse-dev/src/nisse_dev/evals.py +++ b/nisse-dev/src/nisse_dev/evals.py @@ -15,7 +15,7 @@ from collections.abc import Iterable from dataclasses import asdict, dataclass from typing import Any -from nisse_core.canonical import ( +from nisse_core.log.canonical import ( ActionVerdict, DelegationCompleted, DelegationStarted, diff --git a/nisse-dev/src/nisse_dev/expert.py b/nisse-dev/src/nisse_dev/expert.py index 801596e..b5784a5 100644 --- a/nisse-dev/src/nisse_dev/expert.py +++ b/nisse-dev/src/nisse_dev/expert.py @@ -26,14 +26,14 @@ import json import re from dataclasses import dataclass -from nisse_core.canonical import ( +from nisse_core.log.canonical import ( DelegationCompleted, DelegationStarted, StoredEvent, UserMessage, ) -from nisse_core.llm import LLMClient, LLMError, RoleMap -from nisse_core.state import Transcript +from nisse_core.models.llm import LLMClient, LLMError, RoleMap +from nisse_core.state.store import Transcript EXPERT_ROLE = "expert" DEFAULT_BUDGET = 3 diff --git a/nisse-dev/src/nisse_dev/git.py b/nisse-dev/src/nisse_dev/git.py index c576018..658b747 100644 --- a/nisse-dev/src/nisse_dev/git.py +++ b/nisse-dev/src/nisse_dev/git.py @@ -21,7 +21,7 @@ import shlex from dataclasses import dataclass, field from pathlib import Path -from nisse_core.execution import HostUnavailable, SSHHost +from nisse_core.execution.ssh import HostUnavailable, SSHHost TIMEOUT_S = 120 diff --git a/nisse-dev/src/nisse_dev/loop/actions.py b/nisse-dev/src/nisse_dev/loop/actions.py index 42d9963..3f37aef 100644 --- a/nisse-dev/src/nisse_dev/loop/actions.py +++ b/nisse-dev/src/nisse_dev/loop/actions.py @@ -17,13 +17,13 @@ do, judged by code before anything runs. and is logged. A rule never makes a command less severe than its worst part; what can't be -read statically is unknown (nisse_core.actions). +read statically is unknown (nisse_core.authority.actions). """ import posixpath from collections.abc import Callable -from nisse_core.actions import ( +from nisse_core.authority.actions import ( CONTAINED, DANGEROUS, HARMLESS, diff --git a/nisse-dev/src/nisse_dev/loop/agent.py b/nisse-dev/src/nisse_dev/loop/agent.py index 2fb8d7d..cf8702c 100644 --- a/nisse-dev/src/nisse_dev/loop/agent.py +++ b/nisse-dev/src/nisse_dev/loop/agent.py @@ -26,7 +26,7 @@ from dataclasses import dataclass, replace from datetime import UTC, datetime from typing import Any -from nisse_core.actions import ( +from nisse_core.authority.actions import ( CONTAINED, DANGEROUS, REFUSED, @@ -34,8 +34,12 @@ from nisse_core.actions import ( Action, Verdict, ) -from nisse_core.cancel import Cancel -from nisse_core.canonical import ( +from nisse_core.conversation.transport import InboundMessage, Transport +from nisse_core.execution.ssh import HostKeyChanged, HostUnavailable +from nisse_core.gitea import GiteaClient, GiteaError, Issue, PullRequest +from nisse_core.knowledge.memory import Memory +from nisse_core.knowledge.vault import Vault, VaultError +from nisse_core.log.canonical import ( ActionVerdict, DelegationCompleted, DelegationStarted, @@ -46,15 +50,11 @@ from nisse_core.canonical import ( ToolResult, UserMessage, ) -from nisse_core.execution import HostKeyChanged, HostUnavailable -from nisse_core.gitea import GiteaClient, GiteaError, Issue, PullRequest -from nisse_core.llm import LLMError, RoleMap -from nisse_core.memory import Memory +from nisse_core.models.llm import LLMError, RoleMap from nisse_core.oplog import OpLog -from nisse_core.state import WorkItem -from nisse_core.transport import InboundMessage, Transport -from nisse_core.vault import Vault, VaultError -from nisse_core.worker import Worker +from nisse_core.state.cancel import Cancel +from nisse_core.state.store import WorkItem +from nisse_core.state.worker import Worker from nisse_dev.config import GENERAL from nisse_dev.delegation import DELEGATION_INTENT, Delegation from nisse_dev.expert import BudgetExhausted, ExpertDesk diff --git a/nisse-dev/src/nisse_dev/loop/build.py b/nisse-dev/src/nisse_dev/loop/build.py index 8027c21..6c687e8 100644 --- a/nisse-dev/src/nisse_dev/loop/build.py +++ b/nisse-dev/src/nisse_dev/loop/build.py @@ -7,17 +7,17 @@ import threading from collections.abc import Callable from dataclasses import dataclass -from nisse_core.cancel import Cancel -from nisse_core.catalog import ModelCatalog, select_client -from nisse_core.context import BudgetedClient -from nisse_core.execution import SSHHost +from nisse_core.conversation.matrix import MatrixTransport +from nisse_core.execution.ssh import SSHHost from nisse_core.gitea import GiteaClient -from nisse_core.llm import AnthropicPassthroughClient, LiteLLMClient -from nisse_core.matrix import MatrixTransport -from nisse_core.memory import Memory +from nisse_core.knowledge.memory import Memory +from nisse_core.knowledge.vault import Vault +from nisse_core.models.catalog import ModelCatalog, select_client +from nisse_core.models.context import BudgetedClient +from nisse_core.models.llm import AnthropicPassthroughClient, LiteLLMClient from nisse_core.oplog import OpLog -from nisse_core.vault import Vault -from nisse_core.worker import SerialWorker +from nisse_core.state.cancel import Cancel +from nisse_core.state.worker import SerialWorker from nisse_dev.config import AgentConfig, ConfigError from nisse_dev.config import Project as ProjectEntry from nisse_dev.delegation import Caps diff --git a/nisse-dev/src/nisse_dev/loop/classifier.py b/nisse-dev/src/nisse_dev/loop/classifier.py index e09e2b9..58601c9 100644 --- a/nisse-dev/src/nisse_dev/loop/classifier.py +++ b/nisse-dev/src/nisse_dev/loop/classifier.py @@ -16,9 +16,9 @@ from collections.abc import Callable from dataclasses import dataclass from typing import Any -from nisse_core.actions import CONTAINED, DANGEROUS, Action, Verdict -from nisse_core.canonical import StoredEvent, ToolCall, UserMessage -from nisse_core.llm import LLMClient, LLMError +from nisse_core.authority.actions import CONTAINED, DANGEROUS, Action, Verdict +from nisse_core.log.canonical import StoredEvent, ToolCall, UserMessage +from nisse_core.models.llm import LLMClient, LLMError SAFE = "safe" IN_SCOPE = "in_scope" diff --git a/nisse-dev/src/nisse_dev/loop/driver.py b/nisse-dev/src/nisse_dev/loop/driver.py index 04cc93d..168c182 100644 --- a/nisse-dev/src/nisse_dev/loop/driver.py +++ b/nisse-dev/src/nisse_dev/loop/driver.py @@ -11,10 +11,10 @@ from collections.abc import Callable, Mapping from dataclasses import dataclass from typing import Any, Literal -from nisse_core.cancel import Cancel, skip_calls -from nisse_core.canonical import AssistantText, Fact, ToolCall, ToolResult -from nisse_core.llm import LLMClient, LLMError -from nisse_core.state import Transcript +from nisse_core.log.canonical import AssistantText, Fact, ToolCall, ToolResult +from nisse_core.models.llm import LLMClient, LLMError +from nisse_core.state.cancel import Cancel, skip_calls +from nisse_core.state.store import Transcript from nisse_dev.loop.tools import WAITING, names from nisse_dev.tools import Workspace diff --git a/nisse-dev/src/nisse_dev/loop/help.py b/nisse-dev/src/nisse_dev/loop/help.py index 26e79d9..f821a5b 100644 --- a/nisse-dev/src/nisse_dev/loop/help.py +++ b/nisse-dev/src/nisse_dev/loop/help.py @@ -11,7 +11,7 @@ half-edited tree). from collections.abc import Callable, Mapping from dataclasses import dataclass, field -from nisse_core.llm import LLMClient, RoleMap +from nisse_core.models.llm import LLMClient, RoleMap from nisse_dev.config import Profile from nisse_dev.delegation import Caps from nisse_dev.expert import DEFAULT_BUDGET diff --git a/nisse-dev/src/nisse_dev/loop/items.py b/nisse-dev/src/nisse_dev/loop/items.py index 018fa62..49f8869 100644 --- a/nisse-dev/src/nisse_dev/loop/items.py +++ b/nisse-dev/src/nisse_dev/loop/items.py @@ -8,7 +8,7 @@ agreement, what it is waiting for) is in ``data["loop"]``. from dataclasses import asdict, dataclass from typing import Any -from nisse_core.state import WorkItem +from nisse_core.state.store import WorkItem from nisse_dev.state import StateStore READY = "ready" diff --git a/nisse-dev/src/nisse_dev/loop/preflight.py b/nisse-dev/src/nisse_dev/loop/preflight.py index 76803db..aa0fe83 100644 --- a/nisse-dev/src/nisse_dev/loop/preflight.py +++ b/nisse-dev/src/nisse_dev/loop/preflight.py @@ -20,8 +20,8 @@ import shlex from dataclasses import dataclass, field from typing import Any -from nisse_core.actions import split_shell, unwrap -from nisse_core.execution import SSHHost +from nisse_core.authority.actions import split_shell, unwrap +from nisse_core.execution.ssh import SSHHost # What the harness itself runs on a build VM (L13, D4): part of the # template, never of a project's toolchain. diff --git a/nisse-dev/src/nisse_dev/loop/reader.py b/nisse-dev/src/nisse_dev/loop/reader.py index 585cc28..6298ef2 100644 --- a/nisse-dev/src/nisse_dev/loop/reader.py +++ b/nisse-dev/src/nisse_dev/loop/reader.py @@ -10,8 +10,8 @@ The driver's model reads for now; the classifier role takes over in M2.6. from typing import Any -from nisse_core.canonical import StoredEvent, ToolCall, UserMessage -from nisse_core.llm import LLMClient, LLMError +from nisse_core.log.canonical import StoredEvent, ToolCall, UserMessage +from nisse_core.models.llm import LLMClient, LLMError def command_form(text: str) -> str: diff --git a/nisse-dev/src/nisse_dev/state.py b/nisse-dev/src/nisse_dev/state.py index 5d761f4..c2bf0b6 100644 --- a/nisse-dev/src/nisse_dev/state.py +++ b/nisse-dev/src/nisse_dev/state.py @@ -5,8 +5,8 @@ import sqlite3 from collections.abc import Mapping from dataclasses import dataclass -from nisse_core import state -from nisse_core.state import Migration, utc_now +from nisse_core.state import store as state +from nisse_core.state.store import Migration, utc_now _VM_BLOCKS = """ CREATE TABLE vm_blocks ( @@ -48,7 +48,7 @@ class StateStore(state.StateStore): "toolchain", # the toolchain step (D3): the driver's model, apart "memory", # the memory pass at an item's close (L6.4), apart too } - # What each role is shown of the others' work (``nisse_core.views``). + # What each role is shown of the others' work (``nisse_core.log.views``). SHOWN: Mapping[str, Mapping[str, str]] = { "driver": {"helper": "report"}, "helper": {"driver": "narrate"}, diff --git a/nisse-dev/src/nisse_dev/tools.py b/nisse-dev/src/nisse_dev/tools.py index d22dcf5..b39a743 100644 --- a/nisse-dev/src/nisse_dev/tools.py +++ b/nisse-dev/src/nisse_dev/tools.py @@ -20,8 +20,8 @@ from dataclasses import dataclass from pathlib import Path from typing import Any -from nisse_core.context import head_and_tail -from nisse_core.execution import HostUnavailable, Result, SSHHost +from nisse_core.execution.ssh import HostUnavailable, Result, SSHHost +from nisse_core.models.context import head_and_tail # Tools that change or verify something. Reading a file or listing a # directory is a model looking around, not doing the work, so neither counts diff --git a/nisse-dev/tests/model_contract.py b/nisse-dev/tests/model_contract.py index 5154534..69a1084 100644 --- a/nisse-dev/tests/model_contract.py +++ b/nisse-dev/tests/model_contract.py @@ -10,8 +10,8 @@ unit tests and be rejected live; this makes it fail here. from typing import Any -from nisse_core.render import OpenAIChatRenderer -from nisse_core.render_anthropic import AnthropicMessagesRenderer +from nisse_core.models.render import OpenAIChatRenderer +from nisse_core.models.render_anthropic import AnthropicMessagesRenderer def assert_renderable(events: list[Any]) -> None: diff --git a/nisse-dev/tests/test_agent_build.py b/nisse-dev/tests/test_agent_build.py index 1e1a02c..faec514 100644 --- a/nisse-dev/tests/test_agent_build.py +++ b/nisse-dev/tests/test_agent_build.py @@ -11,9 +11,9 @@ import httpx import pytest from test_config import SECRETS, P, tree -from nisse_core.catalog import ModelCatalog, UnknownModel -from nisse_core.execution import SSHHost -from nisse_core.llm import AnthropicPassthroughClient, LiteLLMClient +from nisse_core.execution.ssh import SSHHost +from nisse_core.models.catalog import ModelCatalog, UnknownModel +from nisse_core.models.llm import AnthropicPassthroughClient, LiteLLMClient from nisse_core.oplog import OpLog from nisse_dev.config import AgentConfig from nisse_dev.loop.build import RunningLoop, build_loop_agent, discover_models @@ -143,7 +143,7 @@ def offline(monkeypatch: Any, origins: dict[str, str] | str, catalog=None) -> No """Only the network boundaries faked: Gitea, LiteLLM's model list, Matrix.""" # The proxy here doesn't exist: a call to it fails at once rather than # waiting out an outage's backoff (L5). - monkeypatch.setattr("nisse_core.llm.OUTAGE_BACKOFF_S", ()) + monkeypatch.setattr("nisse_core.models.llm.OUTAGE_BACKOFF_S", ()) monkeypatch.setattr( "nisse_dev.loop.build.GiteaClient.whoami", lambda self: "nisse-dev-testing" ) diff --git a/nisse-dev/tests/test_bench.py b/nisse-dev/tests/test_bench.py index b81f1f9..c4a518e 100644 --- a/nisse-dev/tests/test_bench.py +++ b/nisse-dev/tests/test_bench.py @@ -7,9 +7,9 @@ from typing import Any import pytest -from nisse_core.canonical import AssistantText, ToolCall -from nisse_core.catalog import ModelFacts -from nisse_core.execution import SSHHost +from nisse_core.execution.ssh import SSHHost +from nisse_core.log.canonical import AssistantText, ToolCall +from nisse_core.models.catalog import ModelFacts from nisse_dev.bench.results import ( append, load, diff --git a/nisse-dev/tests/test_config.py b/nisse-dev/tests/test_config.py index bb2adcb..72287cc 100644 --- a/nisse-dev/tests/test_config.py +++ b/nisse-dev/tests/test_config.py @@ -5,7 +5,7 @@ from typing import Any import pytest -from nisse_core.llm import DEFAULT_REQUEST_TIMEOUT_S +from nisse_core.models.llm import DEFAULT_REQUEST_TIMEOUT_S from nisse_dev.config import AgentConfig, ConfigError, Project # A complete config as the YAML file would give it, with secrets by reference. @@ -142,7 +142,7 @@ def test_request_timeout_is_configurable_and_checked() -> None: def test_the_request_timeout_reaches_both_clients() -> None: - from nisse_core.catalog import ModelCatalog + from nisse_core.models.catalog import ModelCatalog from nisse_dev.loop.build import make_llm_clients normalized, passthrough = make_llm_clients( diff --git a/nisse-dev/tests/test_delegation.py b/nisse-dev/tests/test_delegation.py index fcc8beb..6f5a5ce 100644 --- a/nisse-dev/tests/test_delegation.py +++ b/nisse-dev/tests/test_delegation.py @@ -4,8 +4,8 @@ from typing import Any import pytest -from nisse_core.cancel import STOPPED_RESULT, Cancel -from nisse_core.canonical import ( +from nisse_core.execution.ssh import SSHHost +from nisse_core.log.canonical import ( AssistantText, CanonicalEvent, DelegationCompleted, @@ -14,10 +14,10 @@ from nisse_core.canonical import ( ToolCall, ToolResult, ) -from nisse_core.execution import SSHHost -from nisse_core.llm import BudgetExhausted, LLMError, UpstreamUnavailable +from nisse_core.models.llm import BudgetExhausted, LLMError, UpstreamUnavailable from nisse_core.oplog import OpLog -from nisse_core.state import Transcript +from nisse_core.state.cancel import STOPPED_RESULT, Cancel +from nisse_core.state.store import Transcript from nisse_dev.delegation import ( DELEGATE_TOOLS, DELEGATION_INTENT, diff --git a/nisse-dev/tests/test_dev_state.py b/nisse-dev/tests/test_dev_state.py index 45d9373..eeb577e 100644 --- a/nisse-dev/tests/test_dev_state.py +++ b/nisse-dev/tests/test_dev_state.py @@ -5,8 +5,8 @@ from pathlib import Path import pytest -from nisse_core.canonical import ToolCall -from nisse_core.state import StateStore as CoreStore +from nisse_core.log.canonical import ToolCall +from nisse_core.state.store import StateStore as CoreStore from nisse_dev.state import StateStore diff --git a/nisse-dev/tests/test_evals.py b/nisse-dev/tests/test_evals.py index 972fbdb..7a19890 100644 --- a/nisse-dev/tests/test_evals.py +++ b/nisse-dev/tests/test_evals.py @@ -4,7 +4,7 @@ from pathlib import Path import pytest -from nisse_core.canonical import ( +from nisse_core.log.canonical import ( AssistantText, DelegationCompleted, DelegationStarted, diff --git a/nisse-dev/tests/test_expert.py b/nisse-dev/tests/test_expert.py index 52e4fdb..808d9c3 100644 --- a/nisse-dev/tests/test_expert.py +++ b/nisse-dev/tests/test_expert.py @@ -4,16 +4,16 @@ from typing import Any import pytest -from nisse_core.canonical import ( +from nisse_core.log.canonical import ( AssistantText, CanonicalEvent, DelegationCompleted, DelegationStarted, StoredEvent, ) -from nisse_core.llm import LLMError, RoleMap +from nisse_core.models.llm import LLMError, RoleMap from nisse_core.oplog import OpLog -from nisse_core.state import Transcript +from nisse_core.state.store import Transcript from nisse_dev.expert import ( DEFAULT_BUDGET, BudgetExhausted, diff --git a/nisse-dev/tests/test_git.py b/nisse-dev/tests/test_git.py index 080f2ac..9771b88 100644 --- a/nisse-dev/tests/test_git.py +++ b/nisse-dev/tests/test_git.py @@ -6,7 +6,7 @@ from pathlib import Path import pytest -from nisse_core.execution import SSHHost +from nisse_core.execution.ssh import SSHHost from nisse_dev.git import GitError, GitRepo, HTTPSToken, SSHKey @@ -170,7 +170,7 @@ class RecordingHost: self.calls: list[dict] = [] def execute(self, command: str, **kwargs): - from nisse_core.execution import Result + from nisse_core.execution.ssh import Result self.calls.append({"command": command, **kwargs}) return Result(0, "", "") diff --git a/nisse-dev/tests/test_loop.py b/nisse-dev/tests/test_loop.py index b99896e..d31b8ed 100644 --- a/nisse-dev/tests/test_loop.py +++ b/nisse-dev/tests/test_loop.py @@ -8,19 +8,19 @@ from typing import Any import pytest from model_contract import assert_renderable -from nisse_core.cancel import Cancel -from nisse_core.canonical import ( +from nisse_core.conversation.transport import InMemoryTransport +from nisse_core.gitea import Issue +from nisse_core.log.canonical import ( AssistantText, CanonicalEvent, Fact, ToolCall, ToolResult, ) -from nisse_core.gitea import Issue -from nisse_core.llm import LLMError +from nisse_core.models.llm import LLMError from nisse_core.oplog import OpLog -from nisse_core.transport import InMemoryTransport -from nisse_core.worker import InlineWorker +from nisse_core.state.cancel import Cancel +from nisse_core.state.worker import InlineWorker from nisse_dev.loop.agent import LoopAgent from nisse_dev.loop.driver import Driver from nisse_dev.loop.items import CLOSED, GO_AHEAD, READY, RUNNING, WAITING, loop_of @@ -250,7 +250,7 @@ def test_a_go_for_an_earlier_revision_is_not_applied(h: Harness) -> None: h.say("put it in its own module") # changes, so the driver restates rev-2 assert loop_of(h.item()).rev == 2 # A go sent while rev-1 was on screen, arriving now. - from nisse_core.transport import InboundMessage + from nisse_core.conversation.transport import InboundMessage h.agent.handle(InboundMessage(DON, "go", thread=h.thread()), about=1) assert not loop_of(h.item()).started diff --git a/nisse-dev/tests/test_loop_actions.py b/nisse-dev/tests/test_loop_actions.py index cb69f86..82a07cb 100644 --- a/nisse-dev/tests/test_loop_actions.py +++ b/nisse-dev/tests/test_loop_actions.py @@ -11,8 +11,8 @@ from test_loop_milestones import RESTATE, ScriptedModel, call, loop_agent, say from test_loop_milestones import item as the_item from test_loop_milestones import world as world # noqa: PLC0414 -- the fixture -from nisse_core.actions import Action -from nisse_core.canonical import ActionVerdict, ToolCall, ToolResult +from nisse_core.authority.actions import Action +from nisse_core.log.canonical import ActionVerdict, ToolCall, ToolResult from nisse_dev.loop.actions import classify, commits from nisse_dev.loop.items import ANSWER, loop_of diff --git a/nisse-dev/tests/test_loop_classifier.py b/nisse-dev/tests/test_loop_classifier.py index 881b896..2873b12 100644 --- a/nisse-dev/tests/test_loop_classifier.py +++ b/nisse-dev/tests/test_loop_classifier.py @@ -13,9 +13,9 @@ from test_loop_milestones import ScriptedModel, call, loop_agent, say from test_loop_milestones import item as the_item from test_loop_milestones import world as world # noqa: PLC0414 -- the fixture -from nisse_core.actions import Action -from nisse_core.canonical import ActionVerdict, ToolCall -from nisse_core.llm import LLMError +from nisse_core.authority.actions import Action +from nisse_core.log.canonical import ActionVerdict, ToolCall +from nisse_core.models.llm import LLMError from nisse_dev.loop.classifier import ActionClassifier, Scope from nisse_dev.loop.items import ANSWER, loop_of diff --git a/nisse-dev/tests/test_loop_conversations.py b/nisse-dev/tests/test_loop_conversations.py index bff96f1..89da9b0 100644 --- a/nisse-dev/tests/test_loop_conversations.py +++ b/nisse-dev/tests/test_loop_conversations.py @@ -9,8 +9,8 @@ from typing import Any from test_loop_milestones import DON, Forge, ScriptedModel, call, loop_agent from test_loop_milestones import world as world # noqa: PLC0414 -- the fixture -from nisse_core.canonical import Fact, ToolResult from nisse_core.gitea import Issue +from nisse_core.log.canonical import Fact, ToolResult from nisse_dev.loop.agent import FILE_ISSUE from nisse_dev.loop.items import CHAT, GO_AHEAD, MERGE, WAITING, loop_of diff --git a/nisse-dev/tests/test_loop_help.py b/nisse-dev/tests/test_loop_help.py index 562f025..536f975 100644 --- a/nisse-dev/tests/test_loop_help.py +++ b/nisse-dev/tests/test_loop_help.py @@ -18,14 +18,14 @@ from test_loop_milestones import ( ) from test_loop_milestones import world as world # noqa: PLC0414 -- the fixture -from nisse_core.canonical import ( +from nisse_core.log.canonical import ( AssistantText, DelegationStarted, Fact, ToolCall, ToolResult, ) -from nisse_core.llm import RoleMap +from nisse_core.models.llm import RoleMap from nisse_dev.config import Profile from nisse_dev.delegation import DELEGATION_INTENT, Caps from nisse_dev.loop.help import Helpers diff --git a/nisse-dev/tests/test_loop_labels.py b/nisse-dev/tests/test_loop_labels.py index b97bdfc..eb03476 100644 --- a/nisse-dev/tests/test_loop_labels.py +++ b/nisse-dev/tests/test_loop_labels.py @@ -9,8 +9,8 @@ import pytest from test_loop import DON, RESTATED, FakeGitea, Harness, ScriptedModel, call, issue from test_loop import h as h # noqa: PLC0414 -- the fixture -from nisse_core.canonical import Fact, ToolCall -from nisse_core.llm import LLMError +from nisse_core.log.canonical import Fact, ToolCall +from nisse_core.models.llm import LLMError from nisse_dev.loop.items import ANSWER, GO_AHEAD, READY, WAITING, loop_of from nisse_dev.loop.reader import GoAheadReader @@ -284,7 +284,7 @@ def test_an_unlabelled_issue_waits_for_go_with_no_countdown(h: Harness) -> None: def _msg(text: str, thread: str) -> Any: - from nisse_core.transport import InboundMessage + from nisse_core.conversation.transport import InboundMessage return InboundMessage(DON, text, thread=thread) diff --git a/nisse-dev/tests/test_loop_live_fixes.py b/nisse-dev/tests/test_loop_live_fixes.py index c5c678f..7674963 100644 --- a/nisse-dev/tests/test_loop_live_fixes.py +++ b/nisse-dev/tests/test_loop_live_fixes.py @@ -16,8 +16,8 @@ from test_loop_milestones import RESTATE, Forge, loop_agent, say from test_loop_milestones import item as the_item from test_loop_milestones import world as world # noqa: PLC0414 -- the fixture -from nisse_core.canonical import AssistantText, Fact from nisse_core.gitea import Comment +from nisse_core.log.canonical import AssistantText, Fact from nisse_dev.delegation import Caps from nisse_dev.loop.help import Helpers from nisse_dev.loop.items import GO_AHEAD, MERGE, WAITING, loop_of diff --git a/nisse-dev/tests/test_loop_memory.py b/nisse-dev/tests/test_loop_memory.py index 6ecd5e0..14b3e99 100644 --- a/nisse-dev/tests/test_loop_memory.py +++ b/nisse-dev/tests/test_loop_memory.py @@ -12,10 +12,10 @@ from test_loop_milestones import item as the_item from test_loop_milestones import world as world # noqa: PLC0414 -- the fixture from test_loop_notes import Spy -from nisse_core.canonical import AssistantText, Fact -from nisse_core.llm import RoleMap -from nisse_core.memory import Memory -from nisse_core.vault import Vault +from nisse_core.knowledge.memory import Memory +from nisse_core.knowledge.vault import Vault +from nisse_core.log.canonical import AssistantText, Fact +from nisse_core.models.llm import RoleMap FOLDER = "memory/nisse-dev" diff --git a/nisse-dev/tests/test_loop_milestones.py b/nisse-dev/tests/test_loop_milestones.py index 8029a5e..494ab81 100644 --- a/nisse-dev/tests/test_loop_milestones.py +++ b/nisse-dev/tests/test_loop_milestones.py @@ -10,9 +10,8 @@ from typing import Any import pytest from model_contract import assert_renderable -from nisse_core.cancel import Cancel -from nisse_core.canonical import ToolCall -from nisse_core.execution import SSHHost +from nisse_core.conversation.transport import InMemoryTransport +from nisse_core.execution.ssh import SSHHost from nisse_core.gitea import ( Approval, Comment, @@ -21,9 +20,10 @@ from nisse_core.gitea import ( PullRequest, ReviewNote, ) +from nisse_core.log.canonical import ToolCall from nisse_core.oplog import OpLog -from nisse_core.transport import InMemoryTransport -from nisse_core.worker import InlineWorker +from nisse_core.state.cancel import Cancel +from nisse_core.state.worker import InlineWorker from nisse_dev.git import GitRepo from nisse_dev.loop.agent import LoopAgent from nisse_dev.loop.driver import Driver diff --git a/nisse-dev/tests/test_loop_multi.py b/nisse-dev/tests/test_loop_multi.py index 43f5309..3c2f681 100644 --- a/nisse-dev/tests/test_loop_multi.py +++ b/nisse-dev/tests/test_loop_multi.py @@ -18,8 +18,8 @@ from test_loop_milestones import ( ) from test_loop_milestones import world as world # noqa: PLC0414 -- the fixture -from nisse_core.canonical import ToolCall, ToolResult from nisse_core.gitea import Issue +from nisse_core.log.canonical import ToolCall, ToolResult from nisse_dev.loop.items import MERGE, WAITING, loop_of diff --git a/nisse-dev/tests/test_loop_new_projects.py b/nisse-dev/tests/test_loop_new_projects.py index cfa42f3..6813a6f 100644 --- a/nisse-dev/tests/test_loop_new_projects.py +++ b/nisse-dev/tests/test_loop_new_projects.py @@ -14,11 +14,11 @@ import yaml from test_loop_milestones import DON, Forge, ScriptedModel, call, make_world from test_loop_projects import Router -from nisse_core.cancel import Cancel -from nisse_core.execution import SSHHost +from nisse_core.conversation.transport import InMemoryTransport +from nisse_core.execution.ssh import SSHHost from nisse_core.oplog import OpLog -from nisse_core.transport import InMemoryTransport -from nisse_core.worker import InlineWorker +from nisse_core.state.cancel import Cancel +from nisse_core.state.worker import InlineWorker from nisse_dev.config import _parse_projects from nisse_dev.loop.agent import LoopAgent, Project from nisse_dev.loop.driver import Driver diff --git a/nisse-dev/tests/test_loop_notes.py b/nisse-dev/tests/test_loop_notes.py index 619b683..0236e34 100644 --- a/nisse-dev/tests/test_loop_notes.py +++ b/nisse-dev/tests/test_loop_notes.py @@ -11,8 +11,8 @@ from test_loop_milestones import DON, RESTATE, ScriptedModel, call, loop_agent from test_loop_milestones import item as the_item from test_loop_milestones import world as world # noqa: PLC0414 -- the fixture -from nisse_core.canonical import ToolResult -from nisse_core.vault import Vault +from nisse_core.knowledge.vault import Vault +from nisse_core.log.canonical import ToolResult from nisse_dev.loop.items import GO_AHEAD, loop_of diff --git a/nisse-dev/tests/test_loop_projects.py b/nisse-dev/tests/test_loop_projects.py index 64f0041..76bc36c 100644 --- a/nisse-dev/tests/test_loop_projects.py +++ b/nisse-dev/tests/test_loop_projects.py @@ -10,11 +10,11 @@ from typing import Any import pytest from test_loop_milestones import DON, Forge, ScriptedModel, call, git, make_world -from nisse_core.cancel import Cancel -from nisse_core.execution import SSHHost +from nisse_core.conversation.transport import InMemoryTransport +from nisse_core.execution.ssh import SSHHost from nisse_core.oplog import OpLog -from nisse_core.transport import InMemoryTransport -from nisse_core.worker import InlineWorker +from nisse_core.state.cancel import Cancel +from nisse_core.state.worker import InlineWorker from nisse_dev.loop.agent import LoopAgent, Project from nisse_dev.loop.driver import Driver from nisse_dev.loop.items import ANSWER, GO_AHEAD, MERGE, item_for_issue, loop_of diff --git a/nisse-dev/tests/test_loop_properties.py b/nisse-dev/tests/test_loop_properties.py index 1c666a6..7b57afe 100644 --- a/nisse-dev/tests/test_loop_properties.py +++ b/nisse-dev/tests/test_loop_properties.py @@ -24,8 +24,12 @@ from test_loop_milestones import DON, Forge, call, make_world from test_loop_milestones import world as world # noqa: PLC0414 -- the fixture from test_loop_projects import Router -from nisse_core.cancel import Cancel -from nisse_core.canonical import ( +from nisse_core.conversation.transport import InboundMessage, InMemoryTransport +from nisse_core.execution.ssh import HostUnavailable, SSHHost +from nisse_core.gitea import Comment, Issue +from nisse_core.knowledge.memory import Memory +from nisse_core.knowledge.vault import Vault, split_frontmatter +from nisse_core.log.canonical import ( ActionVerdict, AssistantText, Fact, @@ -34,14 +38,10 @@ from nisse_core.canonical import ( ToolResult, UserMessage, ) -from nisse_core.execution import HostUnavailable, SSHHost -from nisse_core.gitea import Comment, Issue -from nisse_core.llm import LLMError, RoleMap -from nisse_core.memory import Memory +from nisse_core.models.llm import LLMError, RoleMap from nisse_core.oplog import OpLog -from nisse_core.transport import InboundMessage, InMemoryTransport -from nisse_core.vault import Vault, split_frontmatter -from nisse_core.worker import InlineWorker +from nisse_core.state.cancel import Cancel +from nisse_core.state.worker import InlineWorker from nisse_dev.delegation import DELEGATION_INTENT, Caps from nisse_dev.loop.agent import LoopAgent, Project from nisse_dev.loop.classifier import ActionClassifier diff --git a/nisse-dev/tests/test_loop_queue.py b/nisse-dev/tests/test_loop_queue.py index e41de95..ee71046 100644 --- a/nisse-dev/tests/test_loop_queue.py +++ b/nisse-dev/tests/test_loop_queue.py @@ -7,8 +7,8 @@ from typing import Any from test_loop_milestones import DON, Forge, ScriptedModel, call, git, loop_agent from test_loop_milestones import world as world # noqa: PLC0414 -- the fixture +from nisse_core.conversation.transport import InboundMessage, InMemoryTransport from nisse_core.gitea import Comment, Issue -from nisse_core.transport import InboundMessage, InMemoryTransport from nisse_dev.loop.items import ( ANSWER, BLOCKED, diff --git a/nisse-dev/tests/test_loop_talk.py b/nisse-dev/tests/test_loop_talk.py index 92fa855..c736061 100644 --- a/nisse-dev/tests/test_loop_talk.py +++ b/nisse-dev/tests/test_loop_talk.py @@ -8,7 +8,7 @@ from typing import Any from test_loop import DON, RESTATED, FakeGitea, Harness, ScriptedModel, call, issue -from nisse_core.canonical import AssistantText +from nisse_core.log.canonical import AssistantText from nisse_dev.loop.items import ANSWER, GO_AHEAD, WAITING, loop_of diff --git a/nisse-dev/tests/test_loop_toolchain.py b/nisse-dev/tests/test_loop_toolchain.py index a700146..b7f4d7c 100644 --- a/nisse-dev/tests/test_loop_toolchain.py +++ b/nisse-dev/tests/test_loop_toolchain.py @@ -26,13 +26,13 @@ from test_loop_milestones import ( from test_loop_milestones import item as the_item from test_loop_milestones import world as world # noqa: PLC0414 -- the fixture -from nisse_core.cancel import Cancel -from nisse_core.canonical import Fact, ToolResult -from nisse_core.execution import HostKeyChanged +from nisse_core.conversation.transport import InMemoryTransport +from nisse_core.execution.ssh import HostKeyChanged from nisse_core.gitea import Issue +from nisse_core.log.canonical import Fact, ToolResult from nisse_core.oplog import OpLog -from nisse_core.transport import InMemoryTransport -from nisse_core.worker import InlineWorker +from nisse_core.state.cancel import Cancel +from nisse_core.state.worker import InlineWorker from nisse_dev.loop import preflight from nisse_dev.loop.agent import LoopAgent, Project from nisse_dev.loop.driver import Driver @@ -194,7 +194,7 @@ def test_what_was_installed_or_is_missing_is_said( def test_an_unfinished_step_is_said_and_work_goes_on( world: dict[str, Any], project: str ) -> None: - from nisse_core.canonical import AssistantText + from nisse_core.log.canonical import AssistantText prose = [AssistantText(text="hmm", model="m")] model = ScriptedModel(prose, prose, RESTATE) diff --git a/nisse-dev/tests/test_loop_trust.py b/nisse-dev/tests/test_loop_trust.py index ac99a39..520d2f9 100644 --- a/nisse-dev/tests/test_loop_trust.py +++ b/nisse-dev/tests/test_loop_trust.py @@ -19,10 +19,10 @@ from test_loop_milestones import ( from test_loop_milestones import item as the_item from test_loop_milestones import world as world # noqa: PLC0414 -- the fixture -from nisse_core.cancel import Cancel +from nisse_core.conversation.transport import InMemoryTransport from nisse_core.oplog import OpLog -from nisse_core.transport import InMemoryTransport -from nisse_core.worker import InlineWorker +from nisse_core.state.cancel import Cancel +from nisse_core.state.worker import InlineWorker from nisse_dev.loop.agent import LoopAgent, Project from nisse_dev.loop.driver import Driver from nisse_dev.loop.items import MERGE, loop_of diff --git a/nisse-dev/tests/test_loop_vm.py b/nisse-dev/tests/test_loop_vm.py index 327c58c..e9e1fb4 100644 --- a/nisse-dev/tests/test_loop_vm.py +++ b/nisse-dev/tests/test_loop_vm.py @@ -19,9 +19,9 @@ from test_loop_toolchain import ( ) from test_loop_toolchain import project as project # noqa: PLC0414 -- the fixture -from nisse_core.canonical import ToolResult -from nisse_core.execution import HostKeyChanged, HostUnavailable +from nisse_core.execution.ssh import HostKeyChanged, HostUnavailable from nisse_core.gitea import Issue +from nisse_core.log.canonical import ToolResult from nisse_dev.loop.items import GO_AHEAD, READY, loop_of RETRY, SETTLE = 300.0, 180.0 diff --git a/nisse-dev/tests/test_preflight.py b/nisse-dev/tests/test_preflight.py index 79532d6..d6800fe 100644 --- a/nisse-dev/tests/test_preflight.py +++ b/nisse-dev/tests/test_preflight.py @@ -5,7 +5,7 @@ import uuid import pytest -from nisse_core.execution import SSHHost +from nisse_core.execution.ssh import SSHHost from nisse_dev.loop import preflight from nisse_dev.loop.preflight import Tool diff --git a/nisse-dev/tests/test_tools.py b/nisse-dev/tests/test_tools.py index 0a9d680..b405332 100644 --- a/nisse-dev/tests/test_tools.py +++ b/nisse-dev/tests/test_tools.py @@ -4,7 +4,7 @@ from pathlib import Path import pytest -from nisse_core.execution import REDACTED, SSHHost +from nisse_core.execution.ssh import REDACTED, SSHHost from nisse_dev.tools import EXECUTION_TOOLS, MAX_OUTPUT_CHARS, Workspace diff --git a/scripts/benchmark.py b/scripts/benchmark.py index aa35531..b70028d 100644 --- a/scripts/benchmark.py +++ b/scripts/benchmark.py @@ -14,8 +14,8 @@ import os import sys from pathlib import Path -from nisse_core.catalog import ModelCatalog from nisse_core.envfile import load_env_file +from nisse_core.models.catalog import ModelCatalog from nisse_dev.bench.results import append, load, render, results_file, summarise from nisse_dev.bench.runner import agent_commit, run_task from nisse_dev.bench.tasks import load_tasks diff --git a/scripts/bringup.sh b/scripts/bringup.sh index d79dba8..fd4d4de 100755 --- a/scripts/bringup.sh +++ b/scripts/bringup.sh @@ -133,7 +133,7 @@ cmd_logs() { journalctl -u "$UNIT" -f -o cat; } # The state store, read with the image's own code. dump() { docker run --rm --user 0 -v "$E2E:$E2E" --entrypoint python "$IMAGE" \ - -m nisse_core.dump "$@" + -m nisse_core.state.dump "$@" } cmd_collect() { diff --git a/scripts/ci-sshd.sh b/scripts/ci-sshd.sh index 8af4313..d8555c8 100755 --- a/scripts/ci-sshd.sh +++ b/scripts/ci-sshd.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# The throwaway sshd the tests need (nisse_core/testing.py), in a CI job. +# The throwaway sshd the tests need (nisse_core/execution/testing.py), in a CI job. # Skipped when the job's image already has it. Otherwise apt fetches from a # kernel.org mirror rather than archive.ubuntu.com, which has been slow # enough (a few KB/s) to add minutes to every job. diff --git a/scripts/classifier-evals.py b/scripts/classifier-evals.py index f39b7e3..140c303 100644 --- a/scripts/classifier-evals.py +++ b/scripts/classifier-evals.py @@ -19,7 +19,7 @@ import sys from dataclasses import asdict from pathlib import Path -from nisse_core.canonical import StoredEvent, from_payload +from nisse_core.log.canonical import StoredEvent, from_payload from nisse_dev.evals import classifier_cases diff --git a/scripts/e2e.sh b/scripts/e2e.sh index 8c18612..d55cce0 100755 --- a/scripts/e2e.sh +++ b/scripts/e2e.sh @@ -36,7 +36,7 @@ else export NISSE_E2E_BUILD_HOST=${NISSE_E2E_BUILD_HOST:-nisse-dev.garrett-hall.com} export NISSE_E2E_BUILD_KEY=${NISSE_E2E_BUILD_KEY:-/root/nisse-e2e/ssh/id_ed25519} fi -# Each run's state store is kept here, for nisse_core.dump after a failure. +# Each run's state store is kept here, for nisse_core.state.dump after a failure. export NISSE_E2E_RUNS=${NISSE_E2E_RUNS:-/root/nisse-e2e/test-runs} # What the run spent on the test key, read from LiteLLM (spend only). The diff --git a/scripts/probe_context.py b/scripts/probe_context.py index 3d249a0..74f4e4a 100644 --- a/scripts/probe_context.py +++ b/scripts/probe_context.py @@ -5,7 +5,7 @@ ALIAS is a LiteLLM model alias. The LiteLLM URL and token come from the agent config (NISSE_CONFIG, ./nisse-dev.yaml, or --config), with its secrets from the environment or .env. See docs/Tuning-Guide.md, "Declaring a local model's -limits", and nisse_core/probe.py for what the verdicts mean. +limits", and nisse_core/models/probe.py for what the verdicts mean. """ import argparse @@ -15,9 +15,9 @@ from pathlib import Path import httpx -from nisse_core.catalog import ModelCatalog from nisse_core.envfile import load_env_file -from nisse_core.probe import probe +from nisse_core.models.catalog import ModelCatalog +from nisse_core.models.probe import probe from nisse_dev.config import AgentConfig, ConfigError diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index a263b7e..233a6e5 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -15,7 +15,7 @@ import pytest from nisse_core.envfile import load_env_file from nisse_core.gitea import GiteaClient -from nisse_core.llm import AnthropicPassthroughClient, LiteLLMClient +from nisse_core.models.llm import AnthropicPassthroughClient, LiteLLMClient from nisse_dev.config import AgentConfig REPO = Path(__file__).resolve().parents[2] diff --git a/tests/integration/e2e_support.py b/tests/integration/e2e_support.py index 479fee4..0012d08 100644 --- a/tests/integration/e2e_support.py +++ b/tests/integration/e2e_support.py @@ -10,9 +10,9 @@ from collections.abc import Iterator from dataclasses import dataclass from pathlib import Path -from nisse_core.execution import SSHHost +from nisse_core.execution.ssh import SSHHost from nisse_core.gitea import GiteaClient, GiteaError -from nisse_core.llm import RoleMap +from nisse_core.models.llm import RoleMap from nisse_dev.config import BuildHost # The end-to-end tests run every role on a local model, which costs nothing diff --git a/tests/integration/test_benchmark_live.py b/tests/integration/test_benchmark_live.py index df87fd5..1d42608 100644 --- a/tests/integration/test_benchmark_live.py +++ b/tests/integration/test_benchmark_live.py @@ -5,8 +5,8 @@ from pathlib import Path import pytest -from nisse_core.catalog import ModelCatalog -from nisse_core.execution import SSHHost +from nisse_core.execution.ssh import SSHHost +from nisse_core.models.catalog import ModelCatalog from nisse_dev.bench.runner import run_task from nisse_dev.bench.tasks import load_tasks from nisse_dev.config import AgentConfig diff --git a/tests/integration/test_classifier_cases.py b/tests/integration/test_classifier_cases.py index 94febf8..9efc0af 100644 --- a/tests/integration/test_classifier_cases.py +++ b/tests/integration/test_classifier_cases.py @@ -15,8 +15,8 @@ from typing import Any import pytest import yaml -from nisse_core.actions import Action -from nisse_core.llm import LiteLLMClient +from nisse_core.authority.actions import Action +from nisse_core.models.llm import LiteLLMClient from nisse_dev.loop.classifier import ActionClassifier, Scope pytestmark = pytest.mark.integration diff --git a/tests/integration/test_crash_durability.py b/tests/integration/test_crash_durability.py index ed9c790..da6b305 100644 --- a/tests/integration/test_crash_durability.py +++ b/tests/integration/test_crash_durability.py @@ -7,7 +7,7 @@ from pathlib import Path import pytest -from nisse_core.reconcile import reconcile_on_boot +from nisse_core.state.reconcile import reconcile_on_boot from nisse_dev.state import StateStore pytestmark = pytest.mark.integration @@ -15,7 +15,7 @@ pytestmark = pytest.mark.integration CRASH_SCRIPT = """ import os import sys -from nisse_core.canonical import UserMessage +from nisse_core.log.canonical import UserMessage from nisse_dev.state import StateStore store = StateStore(sys.argv[1]) diff --git a/tests/integration/test_delegation_live.py b/tests/integration/test_delegation_live.py index 48e2495..2b95b9a 100644 --- a/tests/integration/test_delegation_live.py +++ b/tests/integration/test_delegation_live.py @@ -6,8 +6,8 @@ from pathlib import Path import pytest -from nisse_core.execution import SSHHost -from nisse_core.llm import AnthropicPassthroughClient +from nisse_core.execution.ssh import SSHHost +from nisse_core.models.llm import AnthropicPassthroughClient from nisse_core.oplog import OpLog from nisse_dev.delegation import Caps, Delegation from nisse_dev.git import GitRepo diff --git a/tests/integration/test_end_to_end_loop.py b/tests/integration/test_end_to_end_loop.py index 85de07e..c432d23 100644 --- a/tests/integration/test_end_to_end_loop.py +++ b/tests/integration/test_end_to_end_loop.py @@ -31,10 +31,10 @@ from e2e_support import ( task, ) -from nisse_core.canonical import ActionVerdict -from nisse_core.execution import SSHHost +from nisse_core.conversation.transport import InMemoryTransport +from nisse_core.execution.ssh import SSHHost from nisse_core.gitea import GiteaClient, GiteaError -from nisse_core.transport import InMemoryTransport +from nisse_core.log.canonical import ActionVerdict from nisse_dev.config import AgentConfig, LoopTuning from nisse_dev.loop import preflight from nisse_dev.loop.build import RunningLoop, build_loop_agent @@ -71,7 +71,7 @@ def running( run = uuid.uuid4().hex[:8] stack = contextlib.ExitStack() # Kept outside pytest's temp directories, which pytest prunes, so a - # failed run's transcript can be read afterwards (nisse_core.dump). + # failed run's transcript can be read afterwards (nisse_core.state.dump). keep = Path(os.environ.get("NISSE_E2E_RUNS", "/tmp/nisse-e2e-runs")) / run keep.mkdir(parents=True, exist_ok=True) print(f"\ne2e run {run}: state store in {keep}") diff --git a/tests/integration/test_expert_live.py b/tests/integration/test_expert_live.py index 9c86619..342ff94 100644 --- a/tests/integration/test_expert_live.py +++ b/tests/integration/test_expert_live.py @@ -9,7 +9,7 @@ from pathlib import Path import pytest -from nisse_core.llm import LiteLLMClient, RoleMap +from nisse_core.models.llm import LiteLLMClient, RoleMap from nisse_core.oplog import OpLog from nisse_dev.evals import collect from nisse_dev.expert import BudgetExhausted, ExpertDesk diff --git a/tests/integration/test_gitea_live.py b/tests/integration/test_gitea_live.py index a03920d..1b3bfe0 100644 --- a/tests/integration/test_gitea_live.py +++ b/tests/integration/test_gitea_live.py @@ -9,9 +9,9 @@ from pathlib import Path import pytest from e2e_support import fresh_repo, operator_gitea -from nisse_core.execution import SSHHost +from nisse_core.execution.ssh import SSHHost from nisse_core.gitea import GiteaClient, pull_request_reconciler -from nisse_core.state import Intent +from nisse_core.state.store import Intent from nisse_dev.config import AgentConfig from nisse_dev.git import GitError, GitRepo, SSHKey from nisse_dev.loop.build import remote_url diff --git a/tests/integration/test_llm_live.py b/tests/integration/test_llm_live.py index c16e4d2..5c2158f 100644 --- a/tests/integration/test_llm_live.py +++ b/tests/integration/test_llm_live.py @@ -2,10 +2,10 @@ import pytest -from nisse_core.canonical import AssistantText, StoredEvent, UserMessage -from nisse_core.catalog import ModelCatalog -from nisse_core.context import BudgetedClient -from nisse_core.llm import LiteLLMClient +from nisse_core.log.canonical import AssistantText, StoredEvent, UserMessage +from nisse_core.models.catalog import ModelCatalog +from nisse_core.models.context import BudgetedClient +from nisse_core.models.llm import LiteLLMClient from nisse_dev.config import AgentConfig pytestmark = pytest.mark.integration diff --git a/tests/integration/test_matrix_live.py b/tests/integration/test_matrix_live.py index cd3d870..5fe2693 100644 --- a/tests/integration/test_matrix_live.py +++ b/tests/integration/test_matrix_live.py @@ -5,7 +5,7 @@ import uuid import pytest -from nisse_core.matrix import MatrixConfig, MatrixTransport +from nisse_core.conversation.matrix import MatrixConfig, MatrixTransport from nisse_dev.config import AgentConfig pytestmark = pytest.mark.integration diff --git a/tests/integration/test_model_capability.py b/tests/integration/test_model_capability.py index abb43e4..20769b9 100644 --- a/tests/integration/test_model_capability.py +++ b/tests/integration/test_model_capability.py @@ -21,15 +21,15 @@ argument, not configuration. import pytest -from nisse_core.canonical import ( +from nisse_core.log.canonical import ( AssistantText, StoredEvent, ToolCall, ToolResult, UserMessage, ) -from nisse_core.catalog import ModelCatalog, select_client -from nisse_core.llm import AnthropicPassthroughClient, LiteLLMClient, LLMError +from nisse_core.models.catalog import ModelCatalog, select_client +from nisse_core.models.llm import AnthropicPassthroughClient, LiteLLMClient, LLMError from nisse_dev.config import AgentConfig from nisse_dev.expert import parse_answer from nisse_dev.loop.tools import ASK_HUMAN, FINISH_MILESTONE, RESTATE diff --git a/tests/integration/test_passthrough_live.py b/tests/integration/test_passthrough_live.py index f98b0a2..690ea6f 100644 --- a/tests/integration/test_passthrough_live.py +++ b/tests/integration/test_passthrough_live.py @@ -11,8 +11,8 @@ from pathlib import Path import httpx import pytest -from nisse_core.canonical import AssistantText, ToolCall, ToolResult, UserMessage -from nisse_core.llm import AnthropicPassthroughClient +from nisse_core.log.canonical import AssistantText, ToolCall, ToolResult, UserMessage +from nisse_core.models.llm import AnthropicPassthroughClient from nisse_core.oplog import OpLog from nisse_dev.config import AgentConfig from nisse_dev.state import StateStore