vis-agent 0.2.52.dev7755__tar.gz → 0.2.53__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.
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/PKG-INFO +1 -1
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/schema/agents.json +72 -12
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/schema/gateway.json +9 -1
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/pyproject.toml +1 -1
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/engine/_agents.py +1 -1
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/engine/_council.py +4 -1
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/engine/_extensions.py +1 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/extension.py +47 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_agents.py +5 -2
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_client.py +0 -1
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_declarations.py +27 -0
- vis_agent-0.2.52.dev7755/release-tag +0 -1
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/.gitignore +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/LICENSE +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/README.md +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/fixtures/activity-arguments.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/fixtures/activity-cases.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/fixtures/activity-copy.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/fixtures/activity-execution.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/fixtures/activity-groups.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/fixtures/activity-read-session.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/fixtures/activity-reads.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/fixtures/activity-results.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/fixtures/activity-tables.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/fixtures/activity.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/fixtures/diff.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/fixtures/live-primitives.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/fixtures/session-health.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/fixtures/view.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/schema/activity.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/schema/automations.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/schema/common.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/schema/config.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/schema/content.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/schema/council.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/schema/diff.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/schema/evals.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/schema/improve.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/schema/provider.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/schema/rooms.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/schema/symbol.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/schema/toggle.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/contracts/schema/view.json +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/examples/greeter/tests/test_greeter.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/hatch_build.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/__init__.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/_contracts.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/_outside.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/_wire.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/activity.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/engine/__init__.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/engine/_agent.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/engine/_client.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/engine/_install.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/engine/_local.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/evals/__init__.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/evals/_gateway.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/evals/agent.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/evals/bench.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/evals/check.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/evals/compare.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/evals/environment.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/evals/grade.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/evals/harbor.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/evals/judge-rubric.toml +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/evals/judge.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/evals/labels.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/evals/leaderboard.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/evals/repeats.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/evals/rounds.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/evals/stages.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/evals/stats.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/evals/trajectory.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/extension_package.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/py.typed +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/rooms.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/src/blockether/vis/views.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/conftest.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/evals_atif.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_activity.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_agent.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_agent_extension_lifecycle.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_agent_extensions.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_api_guides.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_attachments.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_authoring.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_catalog.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_catalog_recipe.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_ci_report_recipe.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_client_extensions_engine.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_code_quality_recipe.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_contracts.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_council.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_engine.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_engine_docstrings.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_evals_agent.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_evals_bench.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_evals_check.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_evals_compare.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_evals_environment.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_evals_gateway.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_evals_grade.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_evals_guards.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_evals_harbor.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_evals_judge.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_evals_labels.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_evals_repeats.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_evals_rounds.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_evals_stages.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_evals_stats.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_evals_tasks.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_evals_trajectory.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_extension_package.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_extension_reference.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_gateway_performance.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_goals.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_install.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_live_primitives.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_live_wait.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_local.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_method_typing.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_monitor_recipe.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_namespace.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_outside.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_providers.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_read_session.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_record_arguments.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_registration.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_repair_hooks.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_result_sequence.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_rooms.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_scoped_settings.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_sdk_bootstrap.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_sdk_guide.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_sdk_typing.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_structured_live.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_symbol_contract.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_testing.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_text_list_arguments.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/tests/test_tools.py +0 -0
- {vis_agent-0.2.52.dev7755 → vis_agent-0.2.53}/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.
|
|
3
|
+
Version: 0.2.53
|
|
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
|
|
@@ -38,16 +38,13 @@
|
|
|
38
38
|
"maxItems": 64,
|
|
39
39
|
"uniqueItems": true
|
|
40
40
|
},
|
|
41
|
+
"files": {
|
|
42
|
+
"$ref": "#/$defs/files"
|
|
43
|
+
},
|
|
41
44
|
"key": {
|
|
42
45
|
"type": "string",
|
|
43
46
|
"minLength": 1,
|
|
44
47
|
"maxLength": 256
|
|
45
|
-
},
|
|
46
|
-
"context": {
|
|
47
|
-
"enum": [
|
|
48
|
-
"full",
|
|
49
|
-
"task"
|
|
50
|
-
]
|
|
51
48
|
}
|
|
52
49
|
},
|
|
53
50
|
"required": [
|
|
@@ -119,6 +116,43 @@
|
|
|
119
116
|
],
|
|
120
117
|
"additionalProperties": false
|
|
121
118
|
},
|
|
119
|
+
"grant": {
|
|
120
|
+
"$comment": "Add file rules to the grant of a subagent. A child without write rules writes only the granted rules after a write grant.",
|
|
121
|
+
"type": "object",
|
|
122
|
+
"properties": {
|
|
123
|
+
"session_id": {
|
|
124
|
+
"type": "string",
|
|
125
|
+
"minLength": 1
|
|
126
|
+
},
|
|
127
|
+
"files": {
|
|
128
|
+
"$ref": "#/$defs/files"
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
"required": [
|
|
132
|
+
"session_id",
|
|
133
|
+
"files"
|
|
134
|
+
],
|
|
135
|
+
"additionalProperties": false
|
|
136
|
+
},
|
|
137
|
+
"ask_files": {
|
|
138
|
+
"type": "object",
|
|
139
|
+
"properties": {
|
|
140
|
+
"files": {
|
|
141
|
+
"$ref": "#/$defs/files"
|
|
142
|
+
},
|
|
143
|
+
"reason": {
|
|
144
|
+
"type": "string",
|
|
145
|
+
"minLength": 1,
|
|
146
|
+
"maxLength": 2000,
|
|
147
|
+
"pattern": "\\S"
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
"required": [
|
|
151
|
+
"files",
|
|
152
|
+
"reason"
|
|
153
|
+
],
|
|
154
|
+
"additionalProperties": false
|
|
155
|
+
},
|
|
122
156
|
"resume": {
|
|
123
157
|
"type": "object",
|
|
124
158
|
"properties": {
|
|
@@ -176,6 +210,35 @@
|
|
|
176
210
|
],
|
|
177
211
|
"additionalProperties": false
|
|
178
212
|
},
|
|
213
|
+
"files": {
|
|
214
|
+
"$comment": "A subagent file grant. Each rule is a path or a glob, absolute, ~ or relative to the parent's workspace root. Rules also cover files that do not exist yet.",
|
|
215
|
+
"type": "object",
|
|
216
|
+
"properties": {
|
|
217
|
+
"write": {
|
|
218
|
+
"$ref": "#/$defs/file_rules"
|
|
219
|
+
},
|
|
220
|
+
"read_only": {
|
|
221
|
+
"$ref": "#/$defs/file_rules"
|
|
222
|
+
},
|
|
223
|
+
"deny": {
|
|
224
|
+
"$ref": "#/$defs/file_rules"
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
"minProperties": 1,
|
|
228
|
+
"additionalProperties": false
|
|
229
|
+
},
|
|
230
|
+
"file_rules": {
|
|
231
|
+
"type": "array",
|
|
232
|
+
"items": {
|
|
233
|
+
"type": "string",
|
|
234
|
+
"minLength": 1,
|
|
235
|
+
"maxLength": 4096,
|
|
236
|
+
"pattern": "\\S"
|
|
237
|
+
},
|
|
238
|
+
"minItems": 1,
|
|
239
|
+
"maxItems": 64,
|
|
240
|
+
"uniqueItems": true
|
|
241
|
+
},
|
|
179
242
|
"agent": {
|
|
180
243
|
"type": "object",
|
|
181
244
|
"properties": {
|
|
@@ -209,11 +272,6 @@
|
|
|
209
272
|
"budget_limited"
|
|
210
273
|
]
|
|
211
274
|
},
|
|
212
|
-
"depth": {
|
|
213
|
-
"type": "integer",
|
|
214
|
-
"minimum": 1,
|
|
215
|
-
"maximum": 2
|
|
216
|
-
},
|
|
217
275
|
"iteration_budget": {
|
|
218
276
|
"$ref": "#/$defs/spawn/properties/iteration_budget"
|
|
219
277
|
},
|
|
@@ -248,6 +306,9 @@
|
|
|
248
306
|
"object",
|
|
249
307
|
"null"
|
|
250
308
|
]
|
|
309
|
+
},
|
|
310
|
+
"files": {
|
|
311
|
+
"$ref": "#/$defs/files"
|
|
251
312
|
}
|
|
252
313
|
},
|
|
253
314
|
"required": [
|
|
@@ -257,7 +318,6 @@
|
|
|
257
318
|
"team_id",
|
|
258
319
|
"task",
|
|
259
320
|
"status",
|
|
260
|
-
"depth",
|
|
261
321
|
"iteration_budget",
|
|
262
322
|
"iterations_used"
|
|
263
323
|
],
|
|
@@ -2370,6 +2370,9 @@
|
|
|
2370
2370
|
{
|
|
2371
2371
|
"const": "context.updated"
|
|
2372
2372
|
},
|
|
2373
|
+
{
|
|
2374
|
+
"const": "extensions.reloaded"
|
|
2375
|
+
},
|
|
2373
2376
|
{
|
|
2374
2377
|
"const": "iteration.completed",
|
|
2375
2378
|
"x-vis-turn-stream": true
|
|
@@ -2979,13 +2982,18 @@
|
|
|
2979
2982
|
"required": [
|
|
2980
2983
|
"loaded",
|
|
2981
2984
|
"failed",
|
|
2982
|
-
"scopes"
|
|
2985
|
+
"scopes",
|
|
2986
|
+
"reload_id"
|
|
2983
2987
|
],
|
|
2984
2988
|
"properties": {
|
|
2985
2989
|
"loaded": {
|
|
2986
2990
|
"type": "integer",
|
|
2987
2991
|
"minimum": 0
|
|
2988
2992
|
},
|
|
2993
|
+
"reload_id": {
|
|
2994
|
+
"type": "string",
|
|
2995
|
+
"minLength": 1
|
|
2996
|
+
},
|
|
2989
2997
|
"failed": {
|
|
2990
2998
|
"type": "integer",
|
|
2991
2999
|
"minimum": 0
|
|
@@ -8,7 +8,7 @@ build-backend = "hatchling.build"
|
|
|
8
8
|
|
|
9
9
|
[project]
|
|
10
10
|
name = "vis-agent"
|
|
11
|
-
version = "0.2.
|
|
11
|
+
version = "0.2.53"
|
|
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"
|
|
@@ -16,7 +16,6 @@ class Subagent:
|
|
|
16
16
|
team_id: str
|
|
17
17
|
task: str
|
|
18
18
|
status: str
|
|
19
|
-
depth: int
|
|
20
19
|
iteration_budget: int
|
|
21
20
|
iterations_used: int
|
|
22
21
|
provider: str | None = None
|
|
@@ -24,6 +23,7 @@ class Subagent:
|
|
|
24
23
|
routing_locked: bool = False
|
|
25
24
|
pending_input: bool = False
|
|
26
25
|
usage: dict[str, Any] | None = None
|
|
26
|
+
files: dict[str, list[str]] | None = None
|
|
27
27
|
|
|
28
28
|
@classmethod
|
|
29
29
|
def from_wire(cls, value: dict[str, Any]) -> Subagent:
|
|
@@ -235,6 +235,7 @@ class Council:
|
|
|
235
235
|
model: str | None = None,
|
|
236
236
|
iteration_budget: int | None = None,
|
|
237
237
|
allowed_models: list[dict[str, str]] | None = None,
|
|
238
|
+
files: dict[str, list[str]] | None = None,
|
|
238
239
|
key: str | None = None,
|
|
239
240
|
) -> Subagent:
|
|
240
241
|
"""Create a subagent and publish its delegated task through Council.
|
|
@@ -244,7 +245,8 @@ class Council:
|
|
|
244
245
|
share the checkout, inherit authorization and use their own bounded model
|
|
245
246
|
iterations. A key makes retries idempotent within the parent turn, and reusing
|
|
246
247
|
it with different input is rejected. This is not an ordinary independent fork,
|
|
247
|
-
and it does not grant broader permissions.
|
|
248
|
+
and it does not grant broader permissions. ``files`` narrows file access with
|
|
249
|
+
``write``, ``read_only`` and ``deny`` rules: paths or globs, also for future files.
|
|
248
250
|
"""
|
|
249
251
|
body = {"task": task}
|
|
250
252
|
body.update(
|
|
@@ -255,6 +257,7 @@ class Council:
|
|
|
255
257
|
"iteration_budget": iteration_budget,
|
|
256
258
|
"model": model,
|
|
257
259
|
"allowed_models": allowed_models,
|
|
260
|
+
"files": files,
|
|
258
261
|
"key": key,
|
|
259
262
|
}.items()
|
|
260
263
|
if value is not None
|
|
@@ -1127,6 +1127,8 @@ class Extension:
|
|
|
1127
1127
|
network_filters: `NetworkFilter` declarations.
|
|
1128
1128
|
settings: Host-owned `Setting` declarations with explicit allowed scopes.
|
|
1129
1129
|
env: Environment variable names resolved at host registration.
|
|
1130
|
+
grants: `Grant` declarations: toolchain paths for this extension's
|
|
1131
|
+
`jailed_shell` children.
|
|
1130
1132
|
|
|
1131
1133
|
Collection inputs are copied into tuples. Constructing an Extension is pure: it does
|
|
1132
1134
|
not run callbacks or register anything. In an application, pass it to
|
|
@@ -1155,6 +1157,7 @@ class Extension:
|
|
|
1155
1157
|
network_filters: Sequence[NetworkFilter] = ()
|
|
1156
1158
|
settings: Sequence[Setting] = ()
|
|
1157
1159
|
env: Sequence[str] = ()
|
|
1160
|
+
grants: Sequence[Grant] = ()
|
|
1158
1161
|
|
|
1159
1162
|
def __post_init__(self):
|
|
1160
1163
|
if not isinstance(self.name, str) or not self.name.strip():
|
|
@@ -1186,6 +1189,7 @@ class Extension:
|
|
|
1186
1189
|
("providers", Provider),
|
|
1187
1190
|
("network_filters", NetworkFilter),
|
|
1188
1191
|
("settings", Setting),
|
|
1192
|
+
("grants", Grant),
|
|
1189
1193
|
):
|
|
1190
1194
|
value = getattr(self, name)
|
|
1191
1195
|
if not isinstance(value, (tuple, list)) or not all(
|
|
@@ -1219,6 +1223,7 @@ class Extension:
|
|
|
1219
1223
|
"providers",
|
|
1220
1224
|
"network_filters",
|
|
1221
1225
|
"settings",
|
|
1226
|
+
"grants",
|
|
1222
1227
|
}
|
|
1223
1228
|
return {
|
|
1224
1229
|
field.name: (
|
|
@@ -2712,6 +2717,48 @@ class NetworkFilter:
|
|
|
2712
2717
|
return {"marker": "network_filter", "fn": self.fn}
|
|
2713
2718
|
|
|
2714
2719
|
|
|
2720
|
+
@dataclass(frozen=True, slots=True)
|
|
2721
|
+
class Grant:
|
|
2722
|
+
"""Filesystem access that this extension's own jailed child processes need.
|
|
2723
|
+
|
|
2724
|
+
A toolchain often lives outside the workspace: a JDK, a package cache or a
|
|
2725
|
+
launcher. Declare each path once. The host checks every grant at registration.
|
|
2726
|
+
It adds the grant only to the `jailed_shell` children of this extension. The
|
|
2727
|
+
model's shell never receives it, and the jail deny rules still win.
|
|
2728
|
+
|
|
2729
|
+
Args:
|
|
2730
|
+
path: Absolute path, or a path that starts with `~`.
|
|
2731
|
+
mode: `"read"` to read and run files, or `"read_write"` for a cache that
|
|
2732
|
+
the tool also writes.
|
|
2733
|
+
reason: Short text that tells people why the extension needs the path.
|
|
2734
|
+
|
|
2735
|
+
Raises:
|
|
2736
|
+
ValueError: The path or reason is blank, or the mode is unknown.
|
|
2737
|
+
"""
|
|
2738
|
+
|
|
2739
|
+
path: str | PathLike[str]
|
|
2740
|
+
mode: Literal["read", "read_write"] = "read"
|
|
2741
|
+
reason: str = field(kw_only=True)
|
|
2742
|
+
|
|
2743
|
+
def __post_init__(self):
|
|
2744
|
+
path = os.fspath(self.path) if isinstance(self.path, PathLike) else self.path
|
|
2745
|
+
if not isinstance(path, str) or not path.strip():
|
|
2746
|
+
raise ValueError("vis.Grant requires path=<non-empty string>")
|
|
2747
|
+
object.__setattr__(self, "path", path)
|
|
2748
|
+
if self.mode not in ("read", "read_write"):
|
|
2749
|
+
raise ValueError('vis.Grant mode must be "read" or "read_write"')
|
|
2750
|
+
if not isinstance(self.reason, str) or not self.reason.strip():
|
|
2751
|
+
raise ValueError("vis.Grant requires reason=<non-empty string>")
|
|
2752
|
+
|
|
2753
|
+
def _spec(self):
|
|
2754
|
+
return {
|
|
2755
|
+
"marker": "grant",
|
|
2756
|
+
"path": self.path,
|
|
2757
|
+
"mode": self.mode,
|
|
2758
|
+
"reason": self.reason,
|
|
2759
|
+
}
|
|
2760
|
+
|
|
2761
|
+
|
|
2715
2762
|
# Provider vocabularies are pinned to the canonical provider/config JSON in tests.
|
|
2716
2763
|
ProviderJSON: TypeAlias = (
|
|
2717
2764
|
str
|
|
@@ -13,7 +13,6 @@ CHILD = {
|
|
|
13
13
|
"team_id": "task",
|
|
14
14
|
"task": "Check the contract",
|
|
15
15
|
"status": "running",
|
|
16
|
-
"depth": 1,
|
|
17
16
|
"iteration_budget": 4,
|
|
18
17
|
"iterations_used": 1,
|
|
19
18
|
"provider": "p",
|
|
@@ -63,6 +62,7 @@ def test_managed_team_transport():
|
|
|
63
62
|
model="small",
|
|
64
63
|
iteration_budget=4,
|
|
65
64
|
allowed_models=[{"provider": "p", "model": "small"}],
|
|
65
|
+
files={"write": ["src/owner/**"]},
|
|
66
66
|
key="contract",
|
|
67
67
|
)
|
|
68
68
|
assert isinstance(child, Subagent)
|
|
@@ -86,6 +86,7 @@ def test_managed_team_transport():
|
|
|
86
86
|
"provider": "p",
|
|
87
87
|
"model": "small",
|
|
88
88
|
"allowed_models": [{"provider": "p", "model": "small"}],
|
|
89
|
+
"files": {"write": ["src/owner/**"]},
|
|
89
90
|
"key": "contract",
|
|
90
91
|
},
|
|
91
92
|
),
|
|
@@ -167,6 +168,9 @@ def test_group_members_are_not_the_managed_team():
|
|
|
167
168
|
{"task": "x", "iteration_budget": 601},
|
|
168
169
|
{"task": "x", "model": "small"},
|
|
169
170
|
{"task": "x", "allowed_models": []},
|
|
171
|
+
{"task": "x", "files": {}},
|
|
172
|
+
{"task": "x", "files": {"exec": ["a"]}},
|
|
173
|
+
{"task": "x", "files": {"write": []}},
|
|
170
174
|
],
|
|
171
175
|
)
|
|
172
176
|
def test_spawn_rejects_invalid_input_before_http(opts):
|
|
@@ -293,7 +297,6 @@ def test_all_lifecycle_states_and_optional_response_defaults(status):
|
|
|
293
297
|
"leader_id",
|
|
294
298
|
"team_id",
|
|
295
299
|
"task",
|
|
296
|
-
"depth",
|
|
297
300
|
"iteration_budget",
|
|
298
301
|
"iterations_used",
|
|
299
302
|
)
|
|
@@ -87,6 +87,7 @@ def test_dictionary_builders_are_retired(name):
|
|
|
87
87
|
"slash_commands",
|
|
88
88
|
"op_hooks",
|
|
89
89
|
"network_filters",
|
|
90
|
+
"grants",
|
|
90
91
|
],
|
|
91
92
|
)
|
|
92
93
|
def test_declarations_refuse_untyped_children(field, monkeypatch):
|
|
@@ -324,3 +325,29 @@ def test_registration_snapshots_collections_and_provider_config(monkeypatch):
|
|
|
324
325
|
}
|
|
325
326
|
wire["providers"][0]["preset"]["extra_body"]["models"].clear()
|
|
326
327
|
assert provider.preset.extra_body["models"][0]["name"] == "example"
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
# Regression for #394: an extension declares its toolchain paths as typed grants.
|
|
331
|
+
def test_grant_declarations_reach_the_wire(tmp_path):
|
|
332
|
+
grant = vis.Grant(tmp_path, "read_write", reason="Cache")
|
|
333
|
+
assert grant.path == str(tmp_path)
|
|
334
|
+
extension = vis.Extension(
|
|
335
|
+
name="tools",
|
|
336
|
+
description="Tools",
|
|
337
|
+
grants=[grant, vis.Grant("/opt/jdk", reason="JDK")],
|
|
338
|
+
)
|
|
339
|
+
assert extension._spec()["grants"] == [
|
|
340
|
+
{
|
|
341
|
+
"marker": "grant",
|
|
342
|
+
"path": str(tmp_path),
|
|
343
|
+
"mode": "read_write",
|
|
344
|
+
"reason": "Cache",
|
|
345
|
+
},
|
|
346
|
+
{"marker": "grant", "path": "/opt/jdk", "mode": "read", "reason": "JDK"},
|
|
347
|
+
]
|
|
348
|
+
with pytest.raises(ValueError, match="mode"):
|
|
349
|
+
vis.Grant("/opt/jdk", "write", reason="JDK")
|
|
350
|
+
with pytest.raises(ValueError, match="reason"):
|
|
351
|
+
vis.Grant("/opt/jdk", reason=" ")
|
|
352
|
+
with pytest.raises(TypeError):
|
|
353
|
+
vis.Grant("/opt/jdk")
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
beta-030ba6505ce00caad546fbff1bfdfe01b71c641d
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|