vis-agent 0.2.53.dev7787__tar.gz → 0.2.54.dev7809__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/PKG-INFO +1 -1
  2. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/schema/config.json +1 -1
  3. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/schema/gateway.json +78 -0
  4. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/pyproject.toml +1 -1
  5. vis_agent-0.2.54.dev7809/release-tag +1 -0
  6. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/_outside.py +1 -0
  7. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/extension.py +18 -4
  8. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_contracts.py +4 -4
  9. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_outside.py +7 -0
  10. vis_agent-0.2.53.dev7787/release-tag +0 -1
  11. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/.gitignore +0 -0
  12. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/LICENSE +0 -0
  13. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/README.md +0 -0
  14. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/fixtures/activity-arguments.json +0 -0
  15. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/fixtures/activity-cases.json +0 -0
  16. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/fixtures/activity-copy.json +0 -0
  17. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/fixtures/activity-execution.json +0 -0
  18. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/fixtures/activity-groups.json +0 -0
  19. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/fixtures/activity-read-session.json +0 -0
  20. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/fixtures/activity-reads.json +0 -0
  21. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/fixtures/activity-results.json +0 -0
  22. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/fixtures/activity-tables.json +0 -0
  23. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/fixtures/activity.json +0 -0
  24. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/fixtures/diff.json +0 -0
  25. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/fixtures/live-primitives.json +0 -0
  26. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/fixtures/session-health.json +0 -0
  27. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/fixtures/view.json +0 -0
  28. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/schema/activity.json +0 -0
  29. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/schema/agents.json +0 -0
  30. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/schema/automations.json +0 -0
  31. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/schema/common.json +0 -0
  32. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/schema/content.json +0 -0
  33. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/schema/council.json +0 -0
  34. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/schema/diff.json +0 -0
  35. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/schema/evals.json +0 -0
  36. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/schema/improve.json +0 -0
  37. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/schema/provider.json +0 -0
  38. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/schema/rooms.json +0 -0
  39. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/schema/symbol.json +0 -0
  40. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/schema/toggle.json +0 -0
  41. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/contracts/schema/view.json +0 -0
  42. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/examples/greeter/tests/test_greeter.py +0 -0
  43. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/hatch_build.py +0 -0
  44. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/__init__.py +0 -0
  45. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/_contracts.py +0 -0
  46. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/_wire.py +0 -0
  47. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/activity.py +0 -0
  48. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/engine/__init__.py +0 -0
  49. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/engine/_agent.py +0 -0
  50. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/engine/_agents.py +0 -0
  51. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/engine/_client.py +0 -0
  52. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/engine/_council.py +0 -0
  53. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/engine/_extensions.py +0 -0
  54. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/engine/_install.py +0 -0
  55. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/engine/_local.py +0 -0
  56. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/evals/__init__.py +0 -0
  57. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/evals/_gateway.py +0 -0
  58. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/evals/agent.py +0 -0
  59. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/evals/bench.py +0 -0
  60. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/evals/check.py +0 -0
  61. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/evals/compare.py +0 -0
  62. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/evals/environment.py +0 -0
  63. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/evals/grade.py +0 -0
  64. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/evals/harbor.py +0 -0
  65. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/evals/judge-rubric.toml +0 -0
  66. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/evals/judge.py +0 -0
  67. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/evals/labels.py +0 -0
  68. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/evals/leaderboard.py +0 -0
  69. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/evals/repeats.py +0 -0
  70. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/evals/rounds.py +0 -0
  71. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/evals/stages.py +0 -0
  72. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/evals/stats.py +0 -0
  73. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/evals/trajectory.py +0 -0
  74. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/extension_package.py +0 -0
  75. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/py.typed +0 -0
  76. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/rooms.py +0 -0
  77. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/src/blockether/vis/views.py +0 -0
  78. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/conftest.py +0 -0
  79. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/evals_atif.py +0 -0
  80. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_activity.py +0 -0
  81. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_agent.py +0 -0
  82. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_agent_extension_lifecycle.py +0 -0
  83. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_agent_extensions.py +0 -0
  84. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_agents.py +0 -0
  85. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_api_guides.py +0 -0
  86. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_attachments.py +0 -0
  87. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_authoring.py +0 -0
  88. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_catalog.py +0 -0
  89. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_catalog_recipe.py +0 -0
  90. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_ci_report_recipe.py +0 -0
  91. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_client.py +0 -0
  92. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_client_extensions_engine.py +0 -0
  93. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_code_quality_recipe.py +0 -0
  94. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_council.py +0 -0
  95. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_declarations.py +0 -0
  96. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_engine.py +0 -0
  97. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_engine_docstrings.py +0 -0
  98. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_evals_agent.py +0 -0
  99. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_evals_bench.py +0 -0
  100. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_evals_check.py +0 -0
  101. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_evals_compare.py +0 -0
  102. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_evals_environment.py +0 -0
  103. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_evals_gateway.py +0 -0
  104. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_evals_grade.py +0 -0
  105. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_evals_guards.py +0 -0
  106. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_evals_harbor.py +0 -0
  107. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_evals_judge.py +0 -0
  108. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_evals_labels.py +0 -0
  109. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_evals_repeats.py +0 -0
  110. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_evals_rounds.py +0 -0
  111. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_evals_stages.py +0 -0
  112. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_evals_stats.py +0 -0
  113. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_evals_tasks.py +0 -0
  114. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_evals_trajectory.py +0 -0
  115. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_extension_package.py +0 -0
  116. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_extension_reference.py +0 -0
  117. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_gateway_performance.py +0 -0
  118. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_goals.py +0 -0
  119. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_install.py +0 -0
  120. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_live_primitives.py +0 -0
  121. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_live_wait.py +0 -0
  122. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_local.py +0 -0
  123. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_method_typing.py +0 -0
  124. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_monitor_recipe.py +0 -0
  125. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_namespace.py +0 -0
  126. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_providers.py +0 -0
  127. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_read_session.py +0 -0
  128. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_record_arguments.py +0 -0
  129. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_registration.py +0 -0
  130. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_repair_hooks.py +0 -0
  131. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_result_sequence.py +0 -0
  132. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_rooms.py +0 -0
  133. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_scoped_settings.py +0 -0
  134. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_sdk_bootstrap.py +0 -0
  135. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_sdk_guide.py +0 -0
  136. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_sdk_typing.py +0 -0
  137. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_structured_live.py +0 -0
  138. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_symbol_contract.py +0 -0
  139. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_testing.py +0 -0
  140. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_text_list_arguments.py +0 -0
  141. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_tools.py +0 -0
  142. {vis_agent-0.2.53.dev7787 → vis_agent-0.2.54.dev7809}/tests/test_views.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: vis-agent
3
- Version: 0.2.53.dev7787
3
+ Version: 0.2.54.dev7809
4
4
  Summary: The Vis Python SDK — author extensions and control local or remote engines.
5
5
  Project-URL: Homepage, https://vis.blockether.com
6
6
  Project-URL: Documentation, https://vis.blockether.com
@@ -1276,7 +1276,7 @@
1276
1276
  ]
1277
1277
  },
1278
1278
  "additionalProperties": false,
1279
- "description": "Explicit extension sync declaration. Review source and run extension sync --trust; config loading never installs code. Omitted selector chooses the latest approved stable release once, retained until --refresh; version: latest rechecks it on every sync."
1279
+ "description": "Explicit extension sync declaration. Review source and run extension sync --trust; config loading never installs code. Omitted selector chooses the latest approved stable release once, retained until --refresh; version: latest rechecks it on every sync. A local source with *, ? or [ is a glob of extension entries: it takes no other keys, loads in place at each load and /reload, and sync ignores it."
1280
1280
  },
1281
1281
  "extensions": {
1282
1282
  "type": "object",
@@ -1555,6 +1555,29 @@
1555
1555
  },
1556
1556
  "path": "/v1/voice/model"
1557
1557
  },
1558
+ {
1559
+ "audience": "administration",
1560
+ "operations": {
1561
+ "post": {
1562
+ "request": "none",
1563
+ "response": "json",
1564
+ "response_schema": "web_launch"
1565
+ }
1566
+ },
1567
+ "path": "/v1/web/launches"
1568
+ },
1569
+ {
1570
+ "audience": "public",
1571
+ "operations": {
1572
+ "post": {
1573
+ "request": "json",
1574
+ "response": "json",
1575
+ "request_schema": "web_launch_redeem",
1576
+ "response_schema": "web_launch_grant"
1577
+ }
1578
+ },
1579
+ "path": "/v1/web/launches/redeem"
1580
+ },
1558
1581
  {
1559
1582
  "audience": "sdk",
1560
1583
  "path": "/v1/council/rooms",
@@ -1840,6 +1863,61 @@
1840
1863
  "keepalive_route": "/v1/capabilities"
1841
1864
  },
1842
1865
  "$defs": {
1866
+ "web_launch": {
1867
+ "description": "A one-time code that connects a browser to this gateway. `vis-agent web` puts it in the URL fragment.",
1868
+ "type": "object",
1869
+ "required": [
1870
+ "code",
1871
+ "expires_at_ms",
1872
+ "gateway_id"
1873
+ ],
1874
+ "properties": {
1875
+ "code": {
1876
+ "type": "string",
1877
+ "minLength": 1
1878
+ },
1879
+ "expires_at_ms": {
1880
+ "type": "integer"
1881
+ },
1882
+ "gateway_id": {
1883
+ "type": "string",
1884
+ "minLength": 1
1885
+ }
1886
+ }
1887
+ },
1888
+ "web_launch_redeem": {
1889
+ "type": "object",
1890
+ "required": [
1891
+ "code"
1892
+ ],
1893
+ "properties": {
1894
+ "code": {
1895
+ "type": "string",
1896
+ "minLength": 1
1897
+ }
1898
+ }
1899
+ },
1900
+ "web_launch_grant": {
1901
+ "description": "What a redeemed launch code gives the browser: the gateway it reached and the token for its API.",
1902
+ "type": "object",
1903
+ "required": [
1904
+ "gateway_id",
1905
+ "token",
1906
+ "require_token"
1907
+ ],
1908
+ "properties": {
1909
+ "gateway_id": {
1910
+ "type": "string",
1911
+ "minLength": 1
1912
+ },
1913
+ "token": {
1914
+ "type": "string"
1915
+ },
1916
+ "require_token": {
1917
+ "type": "boolean"
1918
+ }
1919
+ }
1920
+ },
1843
1921
  "decision_archive_bytes": {
1844
1922
  "type": "integer",
1845
1923
  "minimum": 1,
@@ -8,7 +8,7 @@ build-backend = "hatchling.build"
8
8
 
9
9
  [project]
10
10
  name = "vis-agent"
11
- version = "0.2.53.dev7787"
11
+ version = "0.2.54.dev7809"
12
12
  description = "The Vis Python SDK — author extensions and control local or remote engines."
13
13
  readme = "README.md"
14
14
  requires-python = ">=3.12"
@@ -0,0 +1 @@
1
+ beta-a0640b0341d2d74fd4b7a411ee7c82ad4f048528
@@ -1436,6 +1436,7 @@ def _live_handle(held, envelope, op, view_id):
1436
1436
 
1437
1437
  _IMPLEMENTATIONS = {
1438
1438
  "workspace_root": workspace_root,
1439
+ "project_root": workspace_root,
1439
1440
  "python_environment": python_environment,
1440
1441
  "setting_declaration": setting_declaration,
1441
1442
  "setting": setting,
@@ -57,6 +57,10 @@ class Host(Protocol):
57
57
  """Read the active session working copy, or the outside process directory."""
58
58
  ...
59
59
 
60
+ def project_root(self) -> str:
61
+ """Read this extension's project in the session working copy, or the outside process directory."""
62
+ ...
63
+
60
64
  def python_environment(self) -> str:
61
65
  """Read the project's `python.environment`: `project` or `shared`."""
62
66
  ...
@@ -3392,6 +3396,18 @@ def workspace_root() -> Path:
3392
3396
  return Path(_host.workspace_root())
3393
3397
 
3394
3398
 
3399
+ def project_root() -> Path:
3400
+ """Return this extension's project root in the active session workspace.
3401
+
3402
+ The project root is the nearest directory above the extension entry that
3403
+ holds a `.vis` directory, mapped into the session working copy. For an
3404
+ extension in the workspace's own `.vis/extensions`, it is `workspace_root()`.
3405
+ Outside Vis, it is the process directory. A hosted call without a bound
3406
+ session fails, like `workspace_root()`.
3407
+ """
3408
+ return Path(_host.project_root())
3409
+
3410
+
3395
3411
  def python_environment() -> Literal["project", "shared"]:
3396
3412
  """Return the Python environment that the session's project selects.
3397
3413
 
@@ -3758,8 +3774,7 @@ def ask(title, fields, **options):
3758
3774
 
3759
3775
 
3760
3776
  # -- Form builders ------------------------------------------------------------
3761
- # One helper per node type, named exactly like Clojure's
3762
- # `com.blockether.vis.view`: the type IS the function and the name is
3777
+ # One helper per node type: the type IS the function and the name is
3763
3778
  # POSITIONAL, so a misspelled type is a NameError on the spot instead of a
3764
3779
  # refused request, and every other key stays the snake_case spelling `ask`
3765
3780
  # documents.
@@ -5257,8 +5272,7 @@ testing = _Testing()
5257
5272
 
5258
5273
 
5259
5274
  # -- Live view builders -------------------------------------------------------
5260
- # One helper per node type, named exactly like Clojure's
5261
- # `com.blockether.vis.view`, and the ID IS POSITIONAL because every op an
5275
+ # One helper per node type, and the ID IS POSITIONAL because every op an
5262
5276
  # extension writes later addresses that id. A builder is a plain dict: nothing
5263
5277
  # here talks to the host, and `vis.live` is what carries it to the engine that
5264
5278
  # judges it.
@@ -55,11 +55,11 @@ def test_gateway_routes_and_lease_policy_are_shared():
55
55
  lease = gateway["x-vis-client-lease"]
56
56
  assert 0 < lease["touch_ms"] < lease["keepalive_ms"] < lease["ttl_ms"]
57
57
  assert 0 < lease["keepalive_timeout_ms"] < lease["keepalive_ms"]
58
- assert len(routes) == 162
59
- assert len(operations) == 201
58
+ assert len(routes) == 164
59
+ assert len(operations) == 203
60
60
  assert Counter(operation["request"] for operation in operations) == {
61
- "none": 125,
62
- "json": 71,
61
+ "none": 126,
62
+ "json": 72,
63
63
  "binary": 5,
64
64
  }
65
65
  assert by_path["/v1/decisions/models"]["operations"]["get"] == {
@@ -105,6 +105,13 @@ def test_workspace_root_tracks_outside_process_directory(tmp_path, monkeypatch):
105
105
  assert isinstance(vis.workspace_root(), Path)
106
106
 
107
107
 
108
+ def test_project_root_tracks_outside_process_directory(tmp_path, monkeypatch):
109
+ # Regression, #399: an extension reads its project root the same way inside and outside Vis.
110
+ monkeypatch.chdir(tmp_path)
111
+ assert vis.project_root() == tmp_path
112
+ assert isinstance(vis.project_root(), Path)
113
+
114
+
108
115
  def test_python_environment_defaults_to_project_outside_vis():
109
116
  # Regression, #379: py tools read this value to choose the shared interpreter.
110
117
  assert vis.python_environment() == "project"
@@ -1 +0,0 @@
1
- beta-b92ec5c56e34a4d03055d8d6342055f4878eb4ed