capability-compiler 0.1.0__py3-none-any.whl

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 (88) hide show
  1. capability_compiler/__init__.py +76 -0
  2. capability_compiler/_version.py +8 -0
  3. capability_compiler/adapters/__init__.py +70 -0
  4. capability_compiler/adapters/base.py +166 -0
  5. capability_compiler/adapters/browser/__init__.py +7 -0
  6. capability_compiler/adapters/browser/adapter.py +474 -0
  7. capability_compiler/adapters/browser/aria.py +147 -0
  8. capability_compiler/adapters/browser/elements.py +185 -0
  9. capability_compiler/adapters/desktop/__init__.py +9 -0
  10. capability_compiler/adapters/desktop/base.py +90 -0
  11. capability_compiler/adapters/fake_adapter.py +242 -0
  12. capability_compiler/benchmark/__init__.py +42 -0
  13. capability_compiler/benchmark/data/capability_bench.json +81 -0
  14. capability_compiler/benchmark/data/seed.json +148 -0
  15. capability_compiler/benchmark/report.py +164 -0
  16. capability_compiler/benchmark/spec.py +249 -0
  17. capability_compiler/benchmark/suite.py +396 -0
  18. capability_compiler/cli/__init__.py +5 -0
  19. capability_compiler/cli/_common.py +135 -0
  20. capability_compiler/cli/_register.py +35 -0
  21. capability_compiler/cli/benchmark_cmd.py +284 -0
  22. capability_compiler/cli/config_cmds.py +230 -0
  23. capability_compiler/cli/execute_cmd.py +196 -0
  24. capability_compiler/cli/learn_cmd.py +134 -0
  25. capability_compiler/cli/main.py +184 -0
  26. capability_compiler/cli/registry_cmds.py +127 -0
  27. capability_compiler/cli/serve_cmd.py +124 -0
  28. capability_compiler/compiler.py +203 -0
  29. capability_compiler/config.py +282 -0
  30. capability_compiler/errors.py +348 -0
  31. capability_compiler/exploration/__init__.py +33 -0
  32. capability_compiler/exploration/effects.py +227 -0
  33. capability_compiler/exploration/engine.py +347 -0
  34. capability_compiler/exploration/semantics.py +257 -0
  35. capability_compiler/logging.py +228 -0
  36. capability_compiler/models/__init__.py +127 -0
  37. capability_compiler/models/action.py +216 -0
  38. capability_compiler/models/capability.py +389 -0
  39. capability_compiler/models/observation.py +281 -0
  40. capability_compiler/models/state.py +49 -0
  41. capability_compiler/models/transition.py +124 -0
  42. capability_compiler/models/verification.py +85 -0
  43. capability_compiler/models/versioning.py +77 -0
  44. capability_compiler/perception/__init__.py +22 -0
  45. capability_compiler/perception/pipeline.py +70 -0
  46. capability_compiler/perception/semantic.py +245 -0
  47. capability_compiler/providers/__init__.py +60 -0
  48. capability_compiler/providers/anthropic.py +132 -0
  49. capability_compiler/providers/base.py +185 -0
  50. capability_compiler/providers/http.py +216 -0
  51. capability_compiler/providers/mock.py +158 -0
  52. capability_compiler/providers/ollama.py +124 -0
  53. capability_compiler/providers/openai_compat.py +153 -0
  54. capability_compiler/recording/__init__.py +6 -0
  55. capability_compiler/recording/recorder.py +255 -0
  56. capability_compiler/recording/replay.py +174 -0
  57. capability_compiler/refinement/__init__.py +11 -0
  58. capability_compiler/refinement/engine.py +188 -0
  59. capability_compiler/refinement/repair.py +254 -0
  60. capability_compiler/registry/__init__.py +24 -0
  61. capability_compiler/registry/permissions.py +191 -0
  62. capability_compiler/registry/registry.py +251 -0
  63. capability_compiler/runtime/__init__.py +17 -0
  64. capability_compiler/runtime/assertions.py +114 -0
  65. capability_compiler/runtime/executor.py +422 -0
  66. capability_compiler/server/__init__.py +114 -0
  67. capability_compiler/server/auth.py +141 -0
  68. capability_compiler/server/executor_factory.py +75 -0
  69. capability_compiler/server/server.py +555 -0
  70. capability_compiler/server/tool_defs.py +98 -0
  71. capability_compiler/storage/__init__.py +7 -0
  72. capability_compiler/storage/base.py +62 -0
  73. capability_compiler/storage/filesystem.py +236 -0
  74. capability_compiler/storage/sqlite.py +284 -0
  75. capability_compiler/synthesis/__init__.py +20 -0
  76. capability_compiler/synthesis/engine.py +549 -0
  77. capability_compiler/synthesis/templating.py +84 -0
  78. capability_compiler/types.py +97 -0
  79. capability_compiler/verification/__init__.py +42 -0
  80. capability_compiler/verification/base.py +97 -0
  81. capability_compiler/verification/file_visual.py +224 -0
  82. capability_compiler/verification/runner.py +79 -0
  83. capability_compiler/verification/verifiers.py +292 -0
  84. capability_compiler-0.1.0.dist-info/METADATA +261 -0
  85. capability_compiler-0.1.0.dist-info/RECORD +88 -0
  86. capability_compiler-0.1.0.dist-info/WHEEL +4 -0
  87. capability_compiler-0.1.0.dist-info/entry_points.txt +2 -0
  88. capability_compiler-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,76 @@
1
+ """Capability Compiler — turn any software into an API for AI.
2
+
3
+ Observe software, explore it, compile interaction trajectories into verified
4
+ reusable capabilities, and expose them to any LLM through Python, a CLI, and
5
+ MCP. Fully local-first: the default configuration runs offline.
6
+
7
+ Stable public API (import from the package root)::
8
+
9
+ from capability_compiler import Compiler, CompilerSettings
10
+ from capability_compiler import Capability, Observation, Action, Trajectory
11
+ from capability_compiler import MockProvider, load_settings
12
+
13
+ Submodule namespaces (``capability_compiler.models``, ``.adapters``,
14
+ ``.providers``, ``.verification``, ``.storage``) are also public but may
15
+ grow faster than the root API; the root re-exports below are the
16
+ backward-compatible surface.
17
+ """
18
+
19
+ from capability_compiler._version import __version__
20
+ from capability_compiler.compiler import Compiler
21
+ from capability_compiler.config import CompilerSettings, load_settings, settings_to_toml
22
+ from capability_compiler.errors import CapabilityCompilerError, FailureCategory
23
+ from capability_compiler.exploration import (
24
+ ActionSemanticsEngine,
25
+ ExplorationEngine,
26
+ SemanticActionHypothesis,
27
+ )
28
+ from capability_compiler.models import (
29
+ Action,
30
+ ActionResult,
31
+ Capability,
32
+ Episode,
33
+ Observation,
34
+ SoftwareState,
35
+ StateFingerprint,
36
+ Trajectory,
37
+ Transition,
38
+ VerificationOutcome,
39
+ VerificationSpec,
40
+ )
41
+ from capability_compiler.perception import PerceptionPipeline, SemanticState, StateDiff
42
+ from capability_compiler.providers import MockProvider
43
+ from capability_compiler.registry import CapabilityRegistry, CapabilitySummary, Permission
44
+ from capability_compiler.types import canonical_json_hash
45
+
46
+ __all__ = [
47
+ "Action",
48
+ "ActionResult",
49
+ "ActionSemanticsEngine",
50
+ "Capability",
51
+ "CapabilityCompilerError",
52
+ "CapabilityRegistry",
53
+ "CapabilitySummary",
54
+ "Compiler",
55
+ "CompilerSettings",
56
+ "Episode",
57
+ "ExplorationEngine",
58
+ "FailureCategory",
59
+ "MockProvider",
60
+ "Observation",
61
+ "PerceptionPipeline",
62
+ "Permission",
63
+ "SemanticActionHypothesis",
64
+ "SemanticState",
65
+ "SoftwareState",
66
+ "StateDiff",
67
+ "StateFingerprint",
68
+ "Trajectory",
69
+ "Transition",
70
+ "VerificationOutcome",
71
+ "VerificationSpec",
72
+ "__version__",
73
+ "canonical_json_hash",
74
+ "load_settings",
75
+ "settings_to_toml",
76
+ ]
@@ -0,0 +1,8 @@
1
+ """Single source of truth for the package version.
2
+
3
+ Kept in its own module so ``pip install -e .`` environments can read it
4
+ without importing the whole package (pyproject reads it at build time via
5
+ hatchling's version hook — see ``[tool.hatch.version]``).
6
+ """
7
+
8
+ __version__ = "0.1.0"
@@ -0,0 +1,70 @@
1
+ """Environment adapters: protocol, registry, and built-in registration.
2
+
3
+ Importing this package registers every built-in adapter whose dependencies
4
+ are installed. The browser adapter requires the ``browser`` extra
5
+ (Playwright); without it, ``create_adapter("browser")`` fails with an
6
+ actionable error instead of an import crash.
7
+
8
+ Third parties register their own via
9
+ :func:`capability_compiler.adapters.base.register_adapter`.
10
+ """
11
+
12
+ from capability_compiler.adapters.base import EnvironmentAdapter as Adapter # alias
13
+ from capability_compiler.adapters.base import (
14
+ available_adapters,
15
+ create_adapter,
16
+ register_adapter,
17
+ )
18
+
19
+
20
+ def _register_builtins() -> None:
21
+ # Fake adapter is dependency-free; always registered and used by tests,
22
+ # the CapabilityBench suite, and the default MCP executor.
23
+ from capability_compiler.adapters.fake_adapter import FakeAdapter
24
+
25
+ if "fake" not in available_adapters():
26
+ register_adapter(
27
+ "fake",
28
+ FakeAdapter,
29
+ description="Deterministic in-memory adapter for tests + benchmarks.",
30
+ )
31
+
32
+ # Desktop skeleton is dependency-free; always registered (fails loudly
33
+ # and honestly when used).
34
+ from capability_compiler.adapters.desktop import DesktopAdapterSkeleton
35
+
36
+ if "desktop" not in available_adapters():
37
+ register_adapter(
38
+ "desktop",
39
+ DesktopAdapterSkeleton,
40
+ description="desktop adapter skeleton (not yet functional — see docs)",
41
+ )
42
+
43
+ # Browser adapter needs Playwright; register only when importable.
44
+ try:
45
+ from capability_compiler.adapters.browser import BrowserAdapter
46
+
47
+ if "browser" not in available_adapters():
48
+ register_adapter(
49
+ "browser",
50
+ BrowserAdapter,
51
+ description="Playwright browser adapter (chromium/firefox/webkit)",
52
+ )
53
+ except ImportError: # pragma: no cover - exercised only without extra
54
+ from capability_compiler.logging import get_logger
55
+
56
+ get_logger("adapters").debug(
57
+ "browser adapter unavailable (install capability-compiler[browser])"
58
+ )
59
+
60
+
61
+ _register_builtins()
62
+
63
+
64
+ __all__ = [
65
+ "Adapter",
66
+ "EnvironmentAdapter",
67
+ "available_adapters",
68
+ "create_adapter",
69
+ "register_adapter",
70
+ ]
@@ -0,0 +1,166 @@
1
+ """The environment adapter boundary — how Capability Compiler touches software.
2
+
3
+ An :class:`EnvironmentAdapter` wraps one class of target software (a browser,
4
+ a desktop application, a CLI) behind four verbs:
5
+
6
+ * :meth:`connect` / :meth:`disconnect` — lifecycle
7
+ * :meth:`observe` — produce a normalized :class:`~capability_compiler.models.Observation`
8
+ * :meth:`execute` — apply an :class:`~capability_compiler.models.Action`, return an
9
+ :class:`~capability_compiler.models.ActionResult`
10
+ * :meth:`reset` — return the environment to its start state (best effort)
11
+
12
+ Adapters are protocols (structural typing): any object with these methods
13
+ works — subclassing nothing is required. Implementations MUST:
14
+
15
+ 1. Prefer semantic targets (ref/role/name) over coordinates when resolving
16
+ :class:`~capability_compiler.models.action.ActionTarget`.
17
+ 2. Never trust action parameters as instructions (they are data).
18
+ 3. Raise :class:`~capability_compiler.errors.AdapterError` subclasses, not
19
+ bare exceptions, so failures classify cleanly.
20
+
21
+ The adapter registry (:func:`register_adapter` / :func:`create_adapter`)
22
+ keeps adapters pluggable — third parties can ship their own.
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable
28
+
29
+ from capability_compiler.errors import UnknownAdapterError
30
+ from capability_compiler.logging import get_logger
31
+
32
+ if TYPE_CHECKING:
33
+ from capability_compiler.config import CompilerSettings
34
+ from capability_compiler.models import Action, ActionResult, Observation
35
+ from capability_compiler.models.action import ActionTarget
36
+
37
+ log = get_logger("adapters")
38
+
39
+
40
+ @runtime_checkable
41
+ class EnvironmentAdapter(Protocol):
42
+ """Protocol every environment adapter implements."""
43
+
44
+ @property
45
+ def kind(self) -> str:
46
+ """Short adapter kind name, e.g. ``browser`` (used as ``adapter_kind``)."""
47
+ ...
48
+
49
+ @property
50
+ def connected(self) -> bool:
51
+ """Whether the adapter currently holds a live environment session."""
52
+ ...
53
+
54
+ async def connect(self) -> None:
55
+ """Start the environment (launch browser, attach to app window).
56
+
57
+ Raises:
58
+ AdapterError: when the environment cannot be started/attached.
59
+ """
60
+ ...
61
+
62
+ async def disconnect(self) -> None:
63
+ """Release the environment session (idempotent)."""
64
+ ...
65
+
66
+ async def observe(self) -> Observation:
67
+ """Capture a normalized observation of the current state.
68
+
69
+ Raises:
70
+ ObservationError: when the environment cannot be read.
71
+ """
72
+ ...
73
+
74
+ async def execute(self, action: Action) -> ActionResult:
75
+ """Apply *action* and report the outcome (never raises for action-level
76
+ failures; transport/environment errors raise AdapterError)."""
77
+ ...
78
+
79
+ async def reset(self) -> None:
80
+ """Return the environment to its initial state (best effort)."""
81
+ ...
82
+
83
+ def capabilities_description(self) -> list[str]:
84
+ """Primitives this adapter supports, e.g. ``["click", "type", ...]``."""
85
+ ...
86
+
87
+ async def resolve_target(self, target: ActionTarget) -> Any:
88
+ """Resolve a semantic target to an adapter-native locator.
89
+
90
+ Used by verification/repair to re-find drifted elements. Adapters may
91
+ return any object meaningful to them (e.g. a Playwright Locator).
92
+ """
93
+ ...
94
+
95
+
96
+ class AdapterInfo:
97
+ """Registry entry describing an adapter factory."""
98
+
99
+ def __init__(self, kind: str, factory: Any, description: str = "") -> None:
100
+ self.kind = kind
101
+ self.factory = factory
102
+ self.description = description
103
+
104
+
105
+ _REGISTRY: dict[str, AdapterInfo] = {}
106
+
107
+
108
+ def register_adapter(
109
+ kind: str,
110
+ factory: Any,
111
+ *,
112
+ description: str = "",
113
+ replace: bool = False,
114
+ ) -> None:
115
+ """Register an adapter factory under *kind* (e.g. ``"browser"``).
116
+
117
+ The factory is called as ``factory(settings)`` and must return an object
118
+ satisfying :class:`EnvironmentAdapter`.
119
+ """
120
+ import re
121
+
122
+ if not re.fullmatch(r"[a-z][a-z0-9_]{0,30}", kind):
123
+ msg = f"adapter kind must be snake_case, got {kind!r}"
124
+ raise ValueError(msg)
125
+ if kind in _REGISTRY and not replace:
126
+ msg = f"adapter {kind!r} already registered"
127
+ raise ValueError(msg)
128
+ _REGISTRY[kind] = AdapterInfo(kind, factory, description)
129
+ log.debug("adapter.registered", extra={"extra_fields": {"kind": kind}})
130
+
131
+
132
+ def create_adapter(kind: str, settings: CompilerSettings | None = None) -> Any:
133
+ """Instantiate a registered adapter by kind.
134
+
135
+ Raises:
136
+ UnknownAdapterError: when *kind* was never registered.
137
+ """
138
+ info = _REGISTRY.get(kind)
139
+ if info is None:
140
+ raise UnknownAdapterError(
141
+ f"no adapter registered for {kind!r}",
142
+ context={"available": sorted(_REGISTRY)},
143
+ suggestions=[
144
+ "install the adapter's extra (e.g. pip install capability-compiler[browser])",
145
+ "check spelling of the adapter kind",
146
+ ],
147
+ )
148
+ if settings is None:
149
+ from capability_compiler.config import CompilerSettings
150
+
151
+ settings = CompilerSettings()
152
+ return info.factory(settings)
153
+
154
+
155
+ def available_adapters() -> list[str]:
156
+ """Sorted kind names of all registered adapters."""
157
+ return sorted(_REGISTRY)
158
+
159
+
160
+ __all__ = [
161
+ "AdapterInfo",
162
+ "EnvironmentAdapter",
163
+ "available_adapters",
164
+ "create_adapter",
165
+ "register_adapter",
166
+ ]
@@ -0,0 +1,7 @@
1
+ """Browser adapter package (Playwright-based)."""
2
+
3
+ from capability_compiler.adapters.browser.adapter import BrowserAdapter, register, url_allowed
4
+ from capability_compiler.adapters.browser.aria import parse_aria_snapshot
5
+ from capability_compiler.adapters.browser.elements import parse_scan
6
+
7
+ __all__ = ["BrowserAdapter", "parse_aria_snapshot", "parse_scan", "register", "url_allowed"]