capability-compiler 0.1.0__tar.gz → 0.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/PKG-INFO +1 -1
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/_version.py +1 -1
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/adapters/fake_adapter.py +56 -1
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/cli/_common.py +24 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/cli/execute_cmd.py +15 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/cli/learn_cmd.py +6 -1
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/server/executor_factory.py +6 -2
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/synthesis/engine.py +27 -2
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_mcp_server.py +57 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_synthesis.py +28 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/.gitignore +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/LICENSE +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/README.md +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/adapters/browser.md +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/architecture/README.md +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/architecture/mcp.md +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/architecture/registry.md +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/architecture.md +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/benchmarks.md +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/ci.md +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/cli/commands.md +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/concepts/exploration.md +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/concepts/local-first.md +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/master-plan.md +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/models.md +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/research/differentiation.md +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/research/landscape.md +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/research/sources/benchmarks-skill-learning.md +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/research/sources/desktop-automation.md +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/research/sources/gui-agents-vision.md +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/research/sources/mcp-ecosystem.md +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/research/sources/packaging-security.md +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/pyproject.toml +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/__init__.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/adapters/__init__.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/adapters/base.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/adapters/browser/__init__.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/adapters/browser/adapter.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/adapters/browser/aria.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/adapters/browser/elements.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/adapters/desktop/__init__.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/adapters/desktop/base.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/benchmark/__init__.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/benchmark/data/capability_bench.json +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/benchmark/data/seed.json +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/benchmark/report.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/benchmark/spec.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/benchmark/suite.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/cli/__init__.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/cli/_register.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/cli/benchmark_cmd.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/cli/config_cmds.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/cli/main.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/cli/registry_cmds.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/cli/serve_cmd.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/compiler.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/config.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/errors.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/exploration/__init__.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/exploration/effects.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/exploration/engine.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/exploration/semantics.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/logging.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/models/__init__.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/models/action.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/models/capability.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/models/observation.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/models/state.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/models/transition.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/models/verification.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/models/versioning.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/perception/__init__.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/perception/pipeline.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/perception/semantic.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/providers/__init__.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/providers/anthropic.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/providers/base.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/providers/http.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/providers/mock.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/providers/ollama.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/providers/openai_compat.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/recording/__init__.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/recording/recorder.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/recording/replay.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/refinement/__init__.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/refinement/engine.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/refinement/repair.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/registry/__init__.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/registry/permissions.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/registry/registry.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/runtime/__init__.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/runtime/assertions.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/runtime/executor.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/server/__init__.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/server/auth.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/server/server.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/server/tool_defs.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/storage/__init__.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/storage/base.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/storage/filesystem.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/storage/sqlite.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/synthesis/__init__.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/synthesis/templating.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/types.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/verification/__init__.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/verification/base.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/verification/file_visual.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/verification/runner.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/verification/verifiers.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/conftest.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/fixtures/site/index.html +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_action_semantics.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_aria_parser.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_benchmark.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_browser_adapter.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_browser_unit.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_cli.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_compile_e2e.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_compiler.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_config.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_e2e_record_replay.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_errors.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_executor.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_exploration.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_exploration_e2e.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_logging.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_models.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_perception.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_providers_http.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_recording.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_refinement.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_refinement_e2e.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_registry.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_state_consistency_eval.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_storage.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_types.py +0 -0
- {capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_verifiers.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: capability-compiler
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Turn any software into an API for AI: compile interaction trajectories into verified, reusable capabilities exposed via Python, CLI, and MCP.
|
|
5
5
|
Project-URL: Homepage, https://github.com/capability-compiler/capability-compiler
|
|
6
6
|
Project-URL: Documentation, https://github.com/capability-compiler/capability-compiler/tree/main/docs
|
|
@@ -96,6 +96,46 @@ class FakeAdapter:
|
|
|
96
96
|
|
|
97
97
|
# -- test/Bench helpers -----------------------------------------------------
|
|
98
98
|
|
|
99
|
+
def seed_demo_page(self, *, url: str = "demo://page", title: str = "Demo Page") -> None:
|
|
100
|
+
"""Plant the deterministic three-element demo page.
|
|
101
|
+
|
|
102
|
+
A bare fake adapter starts empty — exploration has nothing to
|
|
103
|
+
compile and execution fails its preconditions (the elements a
|
|
104
|
+
learned capability refers to don't exist). This page (a Docs link,
|
|
105
|
+
a Search box, a Submit button) is the canonical offline demo
|
|
106
|
+
environment: ``cc learn``/``cc execute`` and the MCP server's
|
|
107
|
+
default executor all seed it so the full
|
|
108
|
+
learn → compile → persist → execute loop works with zero setup.
|
|
109
|
+
"""
|
|
110
|
+
self.set_state(
|
|
111
|
+
url=url,
|
|
112
|
+
title=title,
|
|
113
|
+
elements=[
|
|
114
|
+
InteractiveElement(
|
|
115
|
+
element_id="nav_docs",
|
|
116
|
+
ref="nav-docs",
|
|
117
|
+
role="link",
|
|
118
|
+
name="Docs",
|
|
119
|
+
action_hints=["click"],
|
|
120
|
+
),
|
|
121
|
+
InteractiveElement(
|
|
122
|
+
element_id="search_box",
|
|
123
|
+
ref="search-box",
|
|
124
|
+
role="searchbox",
|
|
125
|
+
name="Search",
|
|
126
|
+
action_hints=["type", "click"],
|
|
127
|
+
),
|
|
128
|
+
InteractiveElement(
|
|
129
|
+
element_id="submit_btn",
|
|
130
|
+
ref="submit-btn",
|
|
131
|
+
role="button",
|
|
132
|
+
name="Submit",
|
|
133
|
+
action_hints=["click"],
|
|
134
|
+
),
|
|
135
|
+
],
|
|
136
|
+
text_digest="demo page with docs link, search box, and submit button",
|
|
137
|
+
)
|
|
138
|
+
|
|
99
139
|
def set_state(
|
|
100
140
|
self,
|
|
101
141
|
*,
|
|
@@ -227,6 +267,21 @@ class FakeAdapter:
|
|
|
227
267
|
# -- registration ---------------------------------------------------------------
|
|
228
268
|
|
|
229
269
|
|
|
270
|
+
def seed_demo_page(adapter: Any, url: str) -> bool:
|
|
271
|
+
"""Seed *adapter* with the demo page when (and only when) it is a FakeAdapter.
|
|
272
|
+
|
|
273
|
+
Real adapters (browser/desktop) are never touched — their state belongs
|
|
274
|
+
to the live environment. Returns ``True`` when the demo page was planted.
|
|
275
|
+
|
|
276
|
+
The query string is stripped so ``https://example.com/docs?q=x`` and
|
|
277
|
+
``https://example.com/docs`` land on the same deterministic page.
|
|
278
|
+
"""
|
|
279
|
+
if not isinstance(adapter, FakeAdapter):
|
|
280
|
+
return False
|
|
281
|
+
adapter.seed_demo_page(url=url.rsplit("?", 1)[0])
|
|
282
|
+
return True
|
|
283
|
+
|
|
284
|
+
|
|
230
285
|
def _factory(settings: Any | None = None) -> FakeAdapter:
|
|
231
286
|
return FakeAdapter(settings)
|
|
232
287
|
|
|
@@ -234,7 +289,7 @@ def _factory(settings: Any | None = None) -> FakeAdapter:
|
|
|
234
289
|
register_adapter("fake", _factory, description=FakeAdapter.description, replace=True)
|
|
235
290
|
|
|
236
291
|
|
|
237
|
-
__all__ = ["FakeAdapter"]
|
|
292
|
+
__all__ = ["FakeAdapter", "seed_demo_page"]
|
|
238
293
|
|
|
239
294
|
|
|
240
295
|
def id_for(prefix: str = "fake") -> str:
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/cli/_common.py
RENAMED
|
@@ -33,6 +33,7 @@ __all__ = [
|
|
|
33
33
|
"parse_key_path",
|
|
34
34
|
"parse_key_value",
|
|
35
35
|
"run_async",
|
|
36
|
+
"seed_fake_demo",
|
|
36
37
|
]
|
|
37
38
|
|
|
38
39
|
|
|
@@ -133,3 +134,26 @@ def parse_key_path(key_path: str) -> list[str]:
|
|
|
133
134
|
msg = f"key.path must be 'section.key' (min 2 segments), got {key_path!r}"
|
|
134
135
|
raise ValueError(msg)
|
|
135
136
|
return parts
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# -- fake-adapter demo seeding ----------------------------------------------------
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def seed_fake_demo(adapter_obj: Any, url: str) -> bool:
|
|
143
|
+
"""Seed a FakeAdapter with the small demo page so the pipeline has work.
|
|
144
|
+
|
|
145
|
+
The fake adapter starts empty — with no interactive elements exploration
|
|
146
|
+
runs dry (nothing to compile) and execution fails its preconditions (the
|
|
147
|
+
elements a learned capability refers to don't exist). When (and only
|
|
148
|
+
when) the attached adapter is the in-memory FakeAdapter, plant a
|
|
149
|
+
deterministic three-element demo page (Docs link, Search box, Submit
|
|
150
|
+
button) so the full learn → compile → persist → execute loop works
|
|
151
|
+
offline out of the box. Real adapters (browser/desktop) are never
|
|
152
|
+
touched.
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
``True`` when the demo page was planted, ``False`` otherwise.
|
|
156
|
+
"""
|
|
157
|
+
from capability_compiler.adapters.fake_adapter import seed_demo_page
|
|
158
|
+
|
|
159
|
+
return seed_demo_page(adapter_obj, url)
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/cli/execute_cmd.py
RENAMED
|
@@ -27,6 +27,7 @@ from capability_compiler.cli._common import (
|
|
|
27
27
|
load_registry,
|
|
28
28
|
load_settings_cached,
|
|
29
29
|
run_async,
|
|
30
|
+
seed_fake_demo,
|
|
30
31
|
)
|
|
31
32
|
from capability_compiler.errors import CapabilityCompilerError, PermissionDeniedError
|
|
32
33
|
|
|
@@ -117,6 +118,9 @@ def execute(
|
|
|
117
118
|
compiler = _build_compiler(settings, adapter)
|
|
118
119
|
try:
|
|
119
120
|
run_async(compiler.connect())
|
|
121
|
+
# Give the offline fake adapter the same demo page the capability was
|
|
122
|
+
# learned from, so its preconditions (element presence) can hold.
|
|
123
|
+
seed_fake_demo(getattr(compiler, "adapter", None), _start_url(capability))
|
|
120
124
|
result = run_async(compiler.execute(capability, inputs, confirmed=confirmed))
|
|
121
125
|
except CapabilityCompilerError as exc:
|
|
122
126
|
_fail(exc, json_mode=json_mode)
|
|
@@ -171,6 +175,17 @@ def _build_compiler(settings: Any, adapter: str) -> Any:
|
|
|
171
175
|
return Compiler(settings, adapter_kind=adapter)
|
|
172
176
|
|
|
173
177
|
|
|
178
|
+
def _start_url(capability: Any) -> str:
|
|
179
|
+
"""First navigation URL in the capability's procedure (fallback: app://x)."""
|
|
180
|
+
from capability_compiler.models.action import NavigateAction
|
|
181
|
+
|
|
182
|
+
for step in capability.procedure.steps:
|
|
183
|
+
action = getattr(step, "action", None)
|
|
184
|
+
if isinstance(action, NavigateAction):
|
|
185
|
+
return action.url
|
|
186
|
+
return "app://x"
|
|
187
|
+
|
|
188
|
+
|
|
174
189
|
def _render_execution(result: Any) -> None:
|
|
175
190
|
typer.echo(f"# {result.capability} @ {result.version} — {result.status.value}")
|
|
176
191
|
typer.echo(f" duration_ms: {result.duration_ms:.1f}")
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/cli/learn_cmd.py
RENAMED
|
@@ -22,6 +22,7 @@ from capability_compiler.cli._common import (
|
|
|
22
22
|
_wants_json,
|
|
23
23
|
load_settings_cached,
|
|
24
24
|
run_async,
|
|
25
|
+
seed_fake_demo,
|
|
25
26
|
)
|
|
26
27
|
from capability_compiler.errors import CapabilityCompilerError
|
|
27
28
|
from capability_compiler.models.action import NavigateAction
|
|
@@ -61,7 +62,11 @@ def learn(
|
|
|
61
62
|
run_async(compiler.connect())
|
|
62
63
|
try:
|
|
63
64
|
target_url = start_url or url
|
|
64
|
-
if
|
|
65
|
+
if seed_fake_demo(getattr(compiler, "adapter", None), target_url):
|
|
66
|
+
# The demo page already set the URL; navigating again would
|
|
67
|
+
# be a no-op on the fake adapter.
|
|
68
|
+
pass
|
|
69
|
+
elif _can_navigate(compiler):
|
|
65
70
|
run_async(
|
|
66
71
|
compiler.adapter.execute(NavigateAction(url=target_url))
|
|
67
72
|
if compiler.adapter
|
|
@@ -49,12 +49,16 @@ def build_default_factory() -> ExecutorFactory:
|
|
|
49
49
|
|
|
50
50
|
The default keeps the MCP server runnable end-to-end with zero setup so
|
|
51
51
|
`cc doctor`-style smoke tests succeed even before a real adapter is
|
|
52
|
-
registered.
|
|
53
|
-
|
|
52
|
+
registered. The adapter is seeded with the same demo page ``cc learn``
|
|
53
|
+
uses offline, so capabilities learned from that page hold their
|
|
54
|
+
preconditions when invoked over MCP. Production deployments should
|
|
55
|
+
override this with the real adapter (browser/desktop) at the CLI wiring
|
|
56
|
+
layer.
|
|
54
57
|
"""
|
|
55
58
|
|
|
56
59
|
def factory(settings: CompilerSettings) -> CapabilityExecutor:
|
|
57
60
|
adapter = FakeAdapter(settings)
|
|
61
|
+
adapter.seed_demo_page()
|
|
58
62
|
log.debug(
|
|
59
63
|
"executor_factory.default_built",
|
|
60
64
|
extra={"extra_fields": {"adapter": adapter.kind}},
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/synthesis/engine.py
RENAMED
|
@@ -31,6 +31,7 @@ from __future__ import annotations
|
|
|
31
31
|
import re
|
|
32
32
|
from typing import TYPE_CHECKING, Any
|
|
33
33
|
|
|
34
|
+
from capability_compiler.errors import CapabilityCompilerError
|
|
34
35
|
from capability_compiler.logging import StructuredLogAdapter, get_logger
|
|
35
36
|
from capability_compiler.models import (
|
|
36
37
|
AssertionKind,
|
|
@@ -145,6 +146,24 @@ class CapabilitySynthesizer:
|
|
|
145
146
|
|
|
146
147
|
effects = self._derive_effects(hypotheses)
|
|
147
148
|
|
|
149
|
+
if not procedure_steps:
|
|
150
|
+
# Nothing demonstrable happened: the trajectory had no successful
|
|
151
|
+
# actions to compile (empty environment, exploration cut short,
|
|
152
|
+
# or every step failed). A capability with an empty procedure is
|
|
153
|
+
# invalid (it could never execute), so fail loudly with guidance
|
|
154
|
+
# instead of surfacing a raw pydantic validation error.
|
|
155
|
+
raise CapabilityCompilerError(
|
|
156
|
+
"no successful actions in trajectory: cannot compile a capability "
|
|
157
|
+
"from an empty procedure — record at least one successful action "
|
|
158
|
+
"(check that the target environment exposes interactive elements)",
|
|
159
|
+
code="synthesis.empty_procedure",
|
|
160
|
+
context={
|
|
161
|
+
"trajectory_id": trajectory.trajectory_id,
|
|
162
|
+
"total_steps": len(trajectory.steps),
|
|
163
|
+
"skipped_steps": report.skipped_steps,
|
|
164
|
+
},
|
|
165
|
+
)
|
|
166
|
+
|
|
148
167
|
capability = Capability(
|
|
149
168
|
name=name,
|
|
150
169
|
description=description,
|
|
@@ -267,7 +286,13 @@ class CapabilitySynthesizer:
|
|
|
267
286
|
name=pname,
|
|
268
287
|
type="string",
|
|
269
288
|
description=f"Value for '{element_name}'",
|
|
270
|
-
|
|
289
|
+
# The recorded literal is the default ("literals become
|
|
290
|
+
# defaults, not guesses"): callers may omit the input and
|
|
291
|
+
# the executor/template binder falls back to it. Keeping
|
|
292
|
+
# required=True here would contradict the default and make
|
|
293
|
+
# MCP tool calls with omitted arguments fail SDK-side
|
|
294
|
+
# validation before the executor could apply the default.
|
|
295
|
+
required=False,
|
|
271
296
|
default=action.text,
|
|
272
297
|
example=action.text,
|
|
273
298
|
)
|
|
@@ -279,7 +304,7 @@ class CapabilitySynthesizer:
|
|
|
279
304
|
name=pname,
|
|
280
305
|
type="string",
|
|
281
306
|
description=f"Selected value for '{element_name}'",
|
|
282
|
-
required=
|
|
307
|
+
required=False, # recorded literal is the default (see above)
|
|
283
308
|
default=action.value,
|
|
284
309
|
example=action.value,
|
|
285
310
|
)
|
|
@@ -29,6 +29,7 @@ from capability_compiler.models import (
|
|
|
29
29
|
NavigateAction,
|
|
30
30
|
PermissionScope,
|
|
31
31
|
ProcedureStep,
|
|
32
|
+
TypeAction,
|
|
32
33
|
)
|
|
33
34
|
from capability_compiler.registry import CapabilityRegistry
|
|
34
35
|
from capability_compiler.server import (
|
|
@@ -233,6 +234,62 @@ class TestExecuteTool:
|
|
|
233
234
|
assert "navigate" in captured["adapter"].calls
|
|
234
235
|
assert "click" in captured["adapter"].calls
|
|
235
236
|
|
|
237
|
+
async def test_default_factory_runs_demo_capability_with_omitted_inputs(
|
|
238
|
+
self, tmp_path: Path
|
|
239
|
+
) -> None:
|
|
240
|
+
"""Regression: demo-learned capabilities run over MCP with no args.
|
|
241
|
+
|
|
242
|
+
Two bugs used to break this path: synthesis emitted
|
|
243
|
+
``required=True`` alongside the recorded default (empty ``arguments``
|
|
244
|
+
failed the SDK-side validation before the executor could apply the
|
|
245
|
+
default), and the default executor factory built a bare FakeAdapter
|
|
246
|
+
(preconditions like "'Search' is present" failed because the demo
|
|
247
|
+
page ``cc learn`` compiles from was never seeded server-side).
|
|
248
|
+
"""
|
|
249
|
+
registry = CapabilityRegistry.from_settings(_settings(tmp_path))
|
|
250
|
+
await registry.save(
|
|
251
|
+
_make_capability(
|
|
252
|
+
name="demo_search",
|
|
253
|
+
inputs=[
|
|
254
|
+
CapabilityParameter(
|
|
255
|
+
name="search",
|
|
256
|
+
type="string",
|
|
257
|
+
description="Value for 'Search'",
|
|
258
|
+
required=False,
|
|
259
|
+
default="hello",
|
|
260
|
+
)
|
|
261
|
+
],
|
|
262
|
+
procedure=CapabilityProcedure(
|
|
263
|
+
steps=[
|
|
264
|
+
ProcedureStep(
|
|
265
|
+
step_id="s1",
|
|
266
|
+
action=TypeAction(
|
|
267
|
+
target=ActionTarget(
|
|
268
|
+
ref="search-box", role="searchbox", name="Search"
|
|
269
|
+
),
|
|
270
|
+
text="{{search}}",
|
|
271
|
+
),
|
|
272
|
+
),
|
|
273
|
+
ProcedureStep(
|
|
274
|
+
step_id="s2",
|
|
275
|
+
action=ClickAction(
|
|
276
|
+
target=ActionTarget(
|
|
277
|
+
ref="submit-btn", role="button", name="Submit"
|
|
278
|
+
)
|
|
279
|
+
),
|
|
280
|
+
),
|
|
281
|
+
]
|
|
282
|
+
),
|
|
283
|
+
)
|
|
284
|
+
)
|
|
285
|
+
# Default factory: bare FakeAdapter + demo page, as `cc serve` uses it.
|
|
286
|
+
server = CapabilityMCPServer(registry, _settings(tmp_path))
|
|
287
|
+
result = await server.execute_tool("demo_search", {})
|
|
288
|
+
assert result["isError"] is False, result["content"][0]["text"]
|
|
289
|
+
body = json.loads(result["content"][0]["text"])
|
|
290
|
+
assert body["status"] == "success"
|
|
291
|
+
assert all(step["success"] for step in body["steps"])
|
|
292
|
+
|
|
236
293
|
async def test_ping_returns_health_payload(self, tmp_path: Path) -> None:
|
|
237
294
|
registry = CapabilityRegistry.from_settings(_settings(tmp_path))
|
|
238
295
|
await registry.save(_make_capability(name="alpha"))
|
|
@@ -146,6 +146,34 @@ class TestSynthesis:
|
|
|
146
146
|
assert params["format"].default == "png"
|
|
147
147
|
assert params["file_name"].default == "report"
|
|
148
148
|
|
|
149
|
+
async def test_recorded_parameters_are_optional(self):
|
|
150
|
+
"""Recorded literals become defaults, not required inputs.
|
|
151
|
+
|
|
152
|
+
Regression: synthesis used to emit ``required=True`` alongside the
|
|
153
|
+
recorded default. The executor applies defaults when a caller omits
|
|
154
|
+
the input, so ``required`` contradicted ``default`` — and the MCP
|
|
155
|
+
tool built from the capability rejected empty-args calls at the SDK
|
|
156
|
+
validation layer before the executor could fill the default in.
|
|
157
|
+
"""
|
|
158
|
+
app = ExportFakeApp()
|
|
159
|
+
trajectory, initial, final = await record_export_workflow(app)
|
|
160
|
+
capability = await CapabilitySynthesizer(use_model=False).synthesize(
|
|
161
|
+
trajectory, initial_observation=initial, final_observation=final
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
params = {p.name: p for p in capability.inputs}
|
|
165
|
+
assert params["format"].required is False
|
|
166
|
+
assert params["file_name"].required is False
|
|
167
|
+
|
|
168
|
+
# The MCP wire schema mirrors the contract: nothing required, the
|
|
169
|
+
# recorded literal surfaced as the JSON-Schema default.
|
|
170
|
+
from capability_compiler.server.tool_defs import build_input_schema
|
|
171
|
+
|
|
172
|
+
schema = build_input_schema(capability)
|
|
173
|
+
assert schema.get("required", []) == []
|
|
174
|
+
assert schema["properties"]["format"]["default"] == "png"
|
|
175
|
+
assert schema["properties"]["file_name"]["default"] == "report"
|
|
176
|
+
|
|
149
177
|
async def test_preconditions_derived(self):
|
|
150
178
|
app = ExportFakeApp()
|
|
151
179
|
trajectory, initial, final = await record_export_workflow(app)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/research/sources/desktop-automation.md
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/research/sources/gui-agents-vision.md
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/research/sources/mcp-ecosystem.md
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/docs/research/sources/packaging-security.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/adapters/__init__.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/adapters/base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/benchmark/report.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/benchmark/spec.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/benchmark/suite.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/cli/__init__.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/cli/_register.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/cli/benchmark_cmd.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/cli/config_cmds.py
RENAMED
|
File without changes
|
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/cli/registry_cmds.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/cli/serve_cmd.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/models/__init__.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/models/action.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/models/capability.py
RENAMED
|
File without changes
|
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/models/state.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/models/transition.py
RENAMED
|
File without changes
|
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/models/versioning.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/providers/base.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/providers/http.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/providers/mock.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/providers/ollama.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/recording/replay.py
RENAMED
|
File without changes
|
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/refinement/engine.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/refinement/repair.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/registry/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/registry/registry.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/runtime/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/runtime/executor.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/server/__init__.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/server/auth.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/server/server.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/server/tool_defs.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/storage/__init__.py
RENAMED
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/storage/base.py
RENAMED
|
File without changes
|
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/storage/sqlite.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/src/capability_compiler/verification/base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{capability_compiler-0.1.0 → capability_compiler-0.1.2}/tests/test_state_consistency_eval.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|