vis-agent 0.2.47.dev7709__tar.gz → 0.2.48.dev7727__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.47.dev7709 → vis_agent-0.2.48.dev7727}/PKG-INFO +1 -1
  2. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/schema/agents.json +57 -1
  3. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/pyproject.toml +1 -1
  4. vis_agent-0.2.48.dev7727/release-tag +1 -0
  5. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_gateway_performance.py +74 -6
  6. vis_agent-0.2.47.dev7709/release-tag +0 -1
  7. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/.gitignore +0 -0
  8. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/LICENSE +0 -0
  9. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/README.md +0 -0
  10. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/fixtures/activity-arguments.json +0 -0
  11. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/fixtures/activity-cases.json +0 -0
  12. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/fixtures/activity-copy.json +0 -0
  13. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/fixtures/activity-execution.json +0 -0
  14. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/fixtures/activity-groups.json +0 -0
  15. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/fixtures/activity-read-session.json +0 -0
  16. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/fixtures/activity-reads.json +0 -0
  17. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/fixtures/activity-results.json +0 -0
  18. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/fixtures/activity-tables.json +0 -0
  19. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/fixtures/activity.json +0 -0
  20. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/fixtures/diff.json +0 -0
  21. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/fixtures/live-primitives.json +0 -0
  22. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/fixtures/session-health.json +0 -0
  23. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/fixtures/view.json +0 -0
  24. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/schema/activity.json +0 -0
  25. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/schema/automations.json +0 -0
  26. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/schema/common.json +0 -0
  27. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/schema/config.json +0 -0
  28. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/schema/content.json +0 -0
  29. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/schema/council.json +0 -0
  30. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/schema/diff.json +0 -0
  31. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/schema/evals.json +0 -0
  32. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/schema/gateway.json +0 -0
  33. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/schema/improve.json +0 -0
  34. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/schema/provider.json +0 -0
  35. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/schema/rooms.json +0 -0
  36. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/schema/symbol.json +0 -0
  37. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/schema/toggle.json +0 -0
  38. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/contracts/schema/view.json +0 -0
  39. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/examples/greeter/tests/test_greeter.py +0 -0
  40. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/hatch_build.py +0 -0
  41. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/__init__.py +0 -0
  42. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/_contracts.py +0 -0
  43. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/_outside.py +0 -0
  44. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/_wire.py +0 -0
  45. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/activity.py +0 -0
  46. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/engine/__init__.py +0 -0
  47. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/engine/_agent.py +0 -0
  48. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/engine/_agents.py +0 -0
  49. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/engine/_client.py +0 -0
  50. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/engine/_council.py +0 -0
  51. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/engine/_extensions.py +0 -0
  52. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/engine/_install.py +0 -0
  53. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/engine/_local.py +0 -0
  54. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/evals/__init__.py +0 -0
  55. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/evals/_gateway.py +0 -0
  56. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/evals/agent.py +0 -0
  57. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/evals/bench.py +0 -0
  58. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/evals/check.py +0 -0
  59. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/evals/compare.py +0 -0
  60. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/evals/environment.py +0 -0
  61. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/evals/grade.py +0 -0
  62. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/evals/harbor.py +0 -0
  63. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/evals/judge-rubric.toml +0 -0
  64. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/evals/judge.py +0 -0
  65. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/evals/labels.py +0 -0
  66. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/evals/leaderboard.py +0 -0
  67. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/evals/repeats.py +0 -0
  68. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/evals/rounds.py +0 -0
  69. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/evals/stages.py +0 -0
  70. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/evals/stats.py +0 -0
  71. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/evals/trajectory.py +0 -0
  72. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/extension.py +0 -0
  73. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/extension_package.py +0 -0
  74. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/py.typed +0 -0
  75. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/rooms.py +0 -0
  76. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/src/blockether/vis/views.py +0 -0
  77. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/conftest.py +0 -0
  78. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/evals_atif.py +0 -0
  79. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_activity.py +0 -0
  80. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_agent.py +0 -0
  81. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_agent_extension_lifecycle.py +0 -0
  82. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_agent_extensions.py +0 -0
  83. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_agents.py +0 -0
  84. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_api_guides.py +0 -0
  85. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_attachments.py +0 -0
  86. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_authoring.py +0 -0
  87. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_catalog.py +0 -0
  88. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_catalog_recipe.py +0 -0
  89. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_ci_report_recipe.py +0 -0
  90. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_client.py +0 -0
  91. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_client_extensions_engine.py +0 -0
  92. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_code_quality_recipe.py +0 -0
  93. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_contracts.py +0 -0
  94. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_council.py +0 -0
  95. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_declarations.py +0 -0
  96. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_engine.py +0 -0
  97. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_engine_docstrings.py +0 -0
  98. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_evals_agent.py +0 -0
  99. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_evals_bench.py +0 -0
  100. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_evals_check.py +0 -0
  101. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_evals_compare.py +0 -0
  102. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_evals_environment.py +0 -0
  103. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_evals_gateway.py +0 -0
  104. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_evals_grade.py +0 -0
  105. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_evals_guards.py +0 -0
  106. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_evals_harbor.py +0 -0
  107. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_evals_judge.py +0 -0
  108. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_evals_labels.py +0 -0
  109. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_evals_repeats.py +0 -0
  110. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_evals_rounds.py +0 -0
  111. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_evals_stages.py +0 -0
  112. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_evals_stats.py +0 -0
  113. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_evals_tasks.py +0 -0
  114. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_evals_trajectory.py +0 -0
  115. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_extension_package.py +0 -0
  116. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_extension_reference.py +0 -0
  117. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_goals.py +0 -0
  118. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_install.py +0 -0
  119. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_live_primitives.py +0 -0
  120. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_live_wait.py +0 -0
  121. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_local.py +0 -0
  122. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_method_typing.py +0 -0
  123. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_monitor_recipe.py +0 -0
  124. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_namespace.py +0 -0
  125. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_outside.py +0 -0
  126. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_providers.py +0 -0
  127. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_read_session.py +0 -0
  128. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_record_arguments.py +0 -0
  129. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_registration.py +0 -0
  130. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_repair_hooks.py +0 -0
  131. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_result_sequence.py +0 -0
  132. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_rooms.py +0 -0
  133. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_scoped_settings.py +0 -0
  134. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_sdk_bootstrap.py +0 -0
  135. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_sdk_guide.py +0 -0
  136. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_sdk_typing.py +0 -0
  137. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_structured_live.py +0 -0
  138. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_symbol_contract.py +0 -0
  139. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_testing.py +0 -0
  140. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_text_list_arguments.py +0 -0
  141. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/tests/test_tools.py +0 -0
  142. {vis_agent-0.2.47.dev7709 → vis_agent-0.2.48.dev7727}/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.47.dev7709
3
+ Version: 0.2.48.dev7727
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
@@ -27,7 +27,7 @@
27
27
  "type": "integer",
28
28
  "minimum": 1,
29
29
  "maximum": 600,
30
- "default": 64
30
+ "default": 120
31
31
  },
32
32
  "allowed_models": {
33
33
  "type": "array",
@@ -80,6 +80,62 @@
80
80
  ],
81
81
  "additionalProperties": false
82
82
  },
83
+ "extend": {
84
+ "type": "object",
85
+ "properties": {
86
+ "session_id": {
87
+ "type": "string",
88
+ "minLength": 1
89
+ },
90
+ "iterations": {
91
+ "type": "integer",
92
+ "minimum": 1,
93
+ "maximum": 600
94
+ }
95
+ },
96
+ "required": [
97
+ "session_id",
98
+ "iterations"
99
+ ],
100
+ "additionalProperties": false
101
+ },
102
+ "deny": {
103
+ "type": "object",
104
+ "properties": {
105
+ "session_id": {
106
+ "type": "string",
107
+ "minLength": 1
108
+ },
109
+ "reason": {
110
+ "type": "string",
111
+ "minLength": 1,
112
+ "maxLength": 2000,
113
+ "pattern": "\\S"
114
+ }
115
+ },
116
+ "required": [
117
+ "session_id",
118
+ "reason"
119
+ ],
120
+ "additionalProperties": false
121
+ },
122
+ "resume": {
123
+ "type": "object",
124
+ "properties": {
125
+ "session_id": {
126
+ "type": "string",
127
+ "minLength": 1
128
+ },
129
+ "task": {
130
+ "$ref": "#/$defs/spawn/properties/task"
131
+ }
132
+ },
133
+ "required": [
134
+ "session_id",
135
+ "task"
136
+ ],
137
+ "additionalProperties": false
138
+ },
83
139
  "route": {
84
140
  "type": "object",
85
141
  "properties": {
@@ -8,7 +8,7 @@ build-backend = "hatchling.build"
8
8
 
9
9
  [project]
10
10
  name = "vis-agent"
11
- version = "0.2.47.dev7709"
11
+ version = "0.2.48.dev7727"
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-42b3774c2ba242ef912478ea699d58019849f55f
@@ -7,6 +7,8 @@ measure volume; JFR weights are sampling estimates, not exact per-site totals.
7
7
  VIS_TEST_GATEWAY_PROFILE_TASKS and VIS_TEST_GATEWAY_PROFILE_WARMUP control the
8
8
  measured and warmup session counts (defaults: 20 and 5). Set
9
9
  VIS_TEST_GATEWAY_PROFILE_TURNS_PER_SESSION (default: 1) to exercise growing history.
10
+ VIS_TEST_GATEWAY_PROFILE_STDOUT_REPEATS (default: 0) adds source-like stdout lines
11
+ to each tool result. Use 6000 to measure clipped replay and preserve raw output.
10
12
  VIS_TEST_GATEWAY_PROFILE_IDLE_SECONDS (default: 5) controls the final idle sample;
11
13
  use 65 or more to include the default 60-second periodic GC interval.
12
14
  VIS_TEST_GATEWAY_PROFILE_COLLECT_BEFORE=0 omits the pre-measurement full GC
@@ -103,6 +105,14 @@ def test_profile_rejects_invalid_mode(tmp_path, monkeypatch, setting):
103
105
  test_jvm_gateway_repeated_sessions(tmp_path, monkeypatch)
104
106
 
105
107
 
108
+ @pytest.mark.parametrize("repeats", [-1, 1, 12001])
109
+ def test_profile_rejects_invalid_stdout_size(tmp_path, monkeypatch, repeats):
110
+ monkeypatch.setattr(shutil, "which", lambda name: name)
111
+ monkeypatch.setenv("VIS_TEST_GATEWAY_PROFILE_STDOUT_REPEATS", str(repeats))
112
+ with pytest.raises(AssertionError, match="STDOUT_REPEATS must be"):
113
+ test_jvm_gateway_repeated_sessions(tmp_path, monkeypatch)
114
+
115
+
106
116
  @pytest.mark.skipif(
107
117
  os.environ.get("VIS_TEST_GATEWAY_PROFILE") != "1",
108
118
  reason="set VIS_TEST_GATEWAY_PROFILE=1 for JVM resource measurements",
@@ -131,18 +141,52 @@ def test_jvm_gateway_repeated_sessions(tmp_path, monkeypatch):
131
141
  "TRANSCRIPT_EVERY_TURN must be 0 or 1"
132
142
  )
133
143
  transcript_every_turn = transcript_every_turn_value == "1"
144
+ stdout_repeats = int(os.environ.get("VIS_TEST_GATEWAY_PROFILE_STDOUT_REPEATS", "0"))
145
+ assert stdout_repeats == 0 or 6000 <= stdout_repeats <= 12000, (
146
+ "STDOUT_REPEATS must be 0 or between 6000 and 12000"
147
+ )
134
148
  assert tasks > 0 and warmup_tasks >= 0 and turns_per_session > 0
135
149
  assert idle_seconds > 0
136
150
  processes = []
137
151
  worker_samples = []
138
152
  tool_call_ids = set()
153
+ turn_wall_seconds = []
154
+ stdout_line = 'source path: "quoted"\n'
155
+
156
+ def tool_code(position):
157
+ code = f"print(sum(range(1000))); print('execution-{position}')"
158
+ if stdout_repeats:
159
+ code += (
160
+ f"; print({stdout_line!r} * {stdout_repeats}, end='')"
161
+ f"; print('tail-{position}')"
162
+ )
163
+ return code
164
+
165
+ def check_transcript(session, positions):
166
+ content = session.transcript().content
167
+ assert "499500" in str(content)
168
+ if stdout_repeats:
169
+ transcript = json.loads(content)
170
+ forms = [
171
+ form
172
+ for turn in transcript["turns"]
173
+ for iteration in turn["iterations"]
174
+ for form in iteration.get("forms", ())
175
+ if form.get("stdout")
176
+ ]
177
+ assert [form["stdout"] for form in forms] == [
178
+ f"499500\nexecution-{position}\n"
179
+ + stdout_line * stdout_repeats
180
+ + f"tail-{position}\n"
181
+ for position in positions
182
+ ]
183
+ assert "SDK flow completed" in str(content)
184
+
139
185
  with sdk_fixture(
140
186
  tmp_path,
141
187
  monkeypatch,
142
188
  "http",
143
- tool_code=lambda position: (
144
- f"print(sum(range(1000))); print('execution-{position}')"
145
- ),
189
+ tool_code=tool_code,
146
190
  on_process=processes.append,
147
191
  ) as (client, work, requests):
148
192
  process = processes[0]
@@ -209,8 +253,10 @@ def test_jvm_gateway_repeated_sessions(tmp_path, monkeypatch):
209
253
 
210
254
  def task(streamed, *, measure_worker=False):
211
255
  session = client.create_session(root=str(work), channel="app")
256
+ positions = []
212
257
  try:
213
258
  for turn_index in range(turns_per_session):
259
+ turn_started = time.monotonic()
214
260
  turn = session.send(
215
261
  f"Turn {turn_index}: compute the sum of integers from zero through 999"
216
262
  )
@@ -226,8 +272,8 @@ def test_jvm_gateway_repeated_sessions(tmp_path, monkeypatch):
226
272
  assert event.type == "turn.completed", event.data
227
273
  break
228
274
  assert turn.wait(timeout=60)["status"] == "completed"
229
- if transcript_every_turn:
230
- assert "499500" in str(session.transcript().content)
275
+ if measure_worker:
276
+ turn_wall_seconds.append(time.monotonic() - turn_started)
231
277
  assert len(requests) == 2
232
278
  tool_result = requests[-1]["messages"][-1]
233
279
  assert tool_result["role"] == "tool"
@@ -239,10 +285,27 @@ def test_jvm_gateway_repeated_sessions(tmp_path, monkeypatch):
239
285
  assert f"execution-{call_id.removeprefix('call_')}" in str(
240
286
  tool_result["content"]
241
287
  )
288
+ position = int(call_id.removeprefix("call_"))
289
+ positions.append(position)
290
+ if stdout_repeats:
291
+ replay = str(tool_result["content"])
292
+ assert f"tail-{position}" in replay
293
+ assert "stdout clipped: kept " in replay
294
+ assert "4096 estimated-token ceiling" in replay
295
+ assert "Recover exact stdout" in replay
296
+ assert call_id in replay
297
+ replay_ids = [
298
+ message["tool_call_id"]
299
+ for message in requests[-1]["messages"]
300
+ if message["role"] == "tool"
301
+ ]
302
+ assert replay_ids == [f"call_{item}" for item in positions]
242
303
  tool_call_ids.add(call_id)
304
+ if transcript_every_turn:
305
+ check_transcript(session, positions)
243
306
  requests.clear() # Do not retain earlier prompts in the provider.
244
307
  if not transcript_every_turn:
245
- assert "499500" in str(session.transcript().content)
308
+ check_transcript(session, positions)
246
309
  assert len(session.turns()) == turns_per_session
247
310
  if measure_worker:
248
311
  worker_samples.append(
@@ -259,6 +322,9 @@ def test_jvm_gateway_repeated_sessions(tmp_path, monkeypatch):
259
322
  "JFR.start",
260
323
  "name=sdk-dogfood",
261
324
  "settings=profile",
325
+ "jdk.InitialEnvironmentVariable#enabled=false",
326
+ "jdk.InitialSystemProperty#enabled=false",
327
+ "jdk.SystemProcess#enabled=false",
262
328
  f"filename={recording}",
263
329
  "dumponexit=true",
264
330
  )
@@ -315,6 +381,8 @@ def test_jvm_gateway_repeated_sessions(tmp_path, monkeypatch):
315
381
  "warmup_tasks": warmup_tasks,
316
382
  "turns_per_session": turns_per_session,
317
383
  "measured_turns": tasks * turns_per_session,
384
+ "stdout_repeats": stdout_repeats,
385
+ "turn_wall_seconds": turn_wall_seconds,
318
386
  "wall_seconds": elapsed,
319
387
  "jvm_allocated_bytes": (
320
388
  after["total_allocated_bytes"] - before["total_allocated_bytes"]
@@ -1 +0,0 @@
1
- beta-c3f961bff6c51d6d19fdc376437e897d2139bc8b