eyvan 0.0.1__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 (389) hide show
  1. eyvan-0.0.1/PKG-INFO +305 -0
  2. eyvan-0.0.1/README.md +261 -0
  3. eyvan-0.0.1/eyvan/__init__.py +156 -0
  4. eyvan-0.0.1/eyvan/_dashboard/assets/LineChart-CcILbKnD.js +3 -0
  5. eyvan-0.0.1/eyvan/_dashboard/assets/LineChart-D1GxaB_c.css +1 -0
  6. eyvan-0.0.1/eyvan/_dashboard/assets/index-CUw1Ss_o.css +1 -0
  7. eyvan-0.0.1/eyvan/_dashboard/assets/index-aNA_h2N4.js +438 -0
  8. eyvan-0.0.1/eyvan/_dashboard/index.html +21 -0
  9. eyvan-0.0.1/eyvan/_internal/__init__.py +6 -0
  10. eyvan-0.0.1/eyvan/_internal/access_logging.py +308 -0
  11. eyvan-0.0.1/eyvan/_internal/build_identity.py +256 -0
  12. eyvan-0.0.1/eyvan/_internal/client_version.py +118 -0
  13. eyvan-0.0.1/eyvan/_internal/compat.py +11 -0
  14. eyvan-0.0.1/eyvan/_internal/correlation.py +68 -0
  15. eyvan-0.0.1/eyvan/_internal/correlation_ids.py +25 -0
  16. eyvan-0.0.1/eyvan/_internal/fleet_init_script.py +113 -0
  17. eyvan-0.0.1/eyvan/_internal/identifiers.py +17 -0
  18. eyvan-0.0.1/eyvan/_internal/json_types.py +55 -0
  19. eyvan-0.0.1/eyvan/_internal/network.py +34 -0
  20. eyvan-0.0.1/eyvan/_internal/observability.py +130 -0
  21. eyvan-0.0.1/eyvan/_internal/plane_tls.py +165 -0
  22. eyvan-0.0.1/eyvan/_internal/platform.py +79 -0
  23. eyvan-0.0.1/eyvan/_internal/ssh.py +491 -0
  24. eyvan-0.0.1/eyvan/_internal/subprocess_env.py +58 -0
  25. eyvan-0.0.1/eyvan/_internal/trace_context.py +55 -0
  26. eyvan-0.0.1/eyvan/_internal/training_metrics.py +111 -0
  27. eyvan-0.0.1/eyvan/_internal/workspace.py +613 -0
  28. eyvan-0.0.1/eyvan/_version.py +12 -0
  29. eyvan-0.0.1/eyvan/artifacts/__init__.py +388 -0
  30. eyvan-0.0.1/eyvan/artifacts/_capability_tokens.py +122 -0
  31. eyvan-0.0.1/eyvan/artifacts/managed.py +4145 -0
  32. eyvan-0.0.1/eyvan/artifacts/secret_capability.py +240 -0
  33. eyvan-0.0.1/eyvan/artifacts/transfers.py +172 -0
  34. eyvan-0.0.1/eyvan/artifacts/workload_capability.py +180 -0
  35. eyvan-0.0.1/eyvan/assistant_knowledge/__init__.py +923 -0
  36. eyvan-0.0.1/eyvan/assistant_knowledge/easydel_essentials.json +176 -0
  37. eyvan-0.0.1/eyvan/assistant_knowledge/easydel_trainers.json +12180 -0
  38. eyvan-0.0.1/eyvan/capacity/__init__.py +70 -0
  39. eyvan-0.0.1/eyvan/capacity/acquisition_backoff.py +265 -0
  40. eyvan-0.0.1/eyvan/capacity/audit.py +212 -0
  41. eyvan-0.0.1/eyvan/capacity/autoscale/__init__.py +120 -0
  42. eyvan-0.0.1/eyvan/capacity/autoscale/cache.py +957 -0
  43. eyvan-0.0.1/eyvan/capacity/autoscale/cluster_capacity.py +230 -0
  44. eyvan-0.0.1/eyvan/capacity/autoscale/compiler.py +324 -0
  45. eyvan-0.0.1/eyvan/capacity/autoscale/models.py +828 -0
  46. eyvan-0.0.1/eyvan/capacity/autoscale/pool_capacity.py +502 -0
  47. eyvan-0.0.1/eyvan/capacity/autoscale/profiles.py +179 -0
  48. eyvan-0.0.1/eyvan/capacity/autoscale/queue_admission.py +79 -0
  49. eyvan-0.0.1/eyvan/capacity/autoscale/service.py +336 -0
  50. eyvan-0.0.1/eyvan/capacity/conformance.py +706 -0
  51. eyvan-0.0.1/eyvan/capacity/data/accelerator_shapes.yaml +393 -0
  52. eyvan-0.0.1/eyvan/capacity/drivers/__init__.py +109 -0
  53. eyvan-0.0.1/eyvan/capacity/drivers/aws.py +513 -0
  54. eyvan-0.0.1/eyvan/capacity/drivers/azure.py +453 -0
  55. eyvan-0.0.1/eyvan/capacity/drivers/base.py +781 -0
  56. eyvan-0.0.1/eyvan/capacity/drivers/gcp.py +2237 -0
  57. eyvan-0.0.1/eyvan/capacity/drivers/gcp_attach.py +621 -0
  58. eyvan-0.0.1/eyvan/capacity/drivers/kubernetes.py +1918 -0
  59. eyvan-0.0.1/eyvan/capacity/drivers/local.py +260 -0
  60. eyvan-0.0.1/eyvan/capacity/drivers/manual.py +362 -0
  61. eyvan-0.0.1/eyvan/capacity/drivers/onprem_ssh.py +1396 -0
  62. eyvan-0.0.1/eyvan/capacity/drivers/registry.py +748 -0
  63. eyvan-0.0.1/eyvan/capacity/fleet_config.py +1026 -0
  64. eyvan-0.0.1/eyvan/capacity/fleet_state.py +1171 -0
  65. eyvan-0.0.1/eyvan/capacity/gcs_rest.py +200 -0
  66. eyvan-0.0.1/eyvan/capacity/hardware_catalog.py +648 -0
  67. eyvan-0.0.1/eyvan/capacity/planning.py +1653 -0
  68. eyvan-0.0.1/eyvan/capacity/providers/__init__.py +6 -0
  69. eyvan-0.0.1/eyvan/capacity/providers/aws/__init__.py +6 -0
  70. eyvan-0.0.1/eyvan/capacity/providers/aws/api.py +401 -0
  71. eyvan-0.0.1/eyvan/capacity/providers/aws/instances.py +199 -0
  72. eyvan-0.0.1/eyvan/capacity/providers/aws/signing.py +192 -0
  73. eyvan-0.0.1/eyvan/capacity/providers/azure/__init__.py +6 -0
  74. eyvan-0.0.1/eyvan/capacity/providers/azure/api.py +366 -0
  75. eyvan-0.0.1/eyvan/capacity/providers/azure/machines.py +206 -0
  76. eyvan-0.0.1/eyvan/capacity/providers/gcp/__init__.py +82 -0
  77. eyvan-0.0.1/eyvan/capacity/providers/gcp/accelerator_catalog.py +186 -0
  78. eyvan-0.0.1/eyvan/capacity/providers/gcp/compute_instances.py +1257 -0
  79. eyvan-0.0.1/eyvan/capacity/providers/gcp/native_worker_ingress.py +773 -0
  80. eyvan-0.0.1/eyvan/capacity/providers/gcp/queued_resources.py +1151 -0
  81. eyvan-0.0.1/eyvan/capacity/providers/gcp/quota_catalog.py +139 -0
  82. eyvan-0.0.1/eyvan/capacity/providers/gcp/quota_discovery.py +589 -0
  83. eyvan-0.0.1/eyvan/capacity/providers/gcp/quota_usage.py +355 -0
  84. eyvan-0.0.1/eyvan/capacity/providers/gcp/runtime/__init__.py +6 -0
  85. eyvan-0.0.1/eyvan/capacity/providers/gcp/runtime/bootstrap.py +527 -0
  86. eyvan-0.0.1/eyvan/capacity/providers/gcp/runtime/profile.py +637 -0
  87. eyvan-0.0.1/eyvan/capacity/providers/gcp/runtime/supervisor.py +1059 -0
  88. eyvan-0.0.1/eyvan/capacity/providers/gcp/tpu_discovery.py +362 -0
  89. eyvan-0.0.1/eyvan/capacity/providers/gcp/tpu_nodes.py +485 -0
  90. eyvan-0.0.1/eyvan/capacity/providers/gcp/tpu_ssh.py +231 -0
  91. eyvan-0.0.1/eyvan/capacity/providers/gcp/tpu_types.py +54 -0
  92. eyvan-0.0.1/eyvan/capacity/providers/gcp/tpu_zone_policy.py +54 -0
  93. eyvan-0.0.1/eyvan/capacity/providers/kubernetes/__init__.py +5 -0
  94. eyvan-0.0.1/eyvan/capacity/providers/kubernetes/api.py +578 -0
  95. eyvan-0.0.1/eyvan/capacity/providers/kubernetes/kueue.py +1123 -0
  96. eyvan-0.0.1/eyvan/capacity/providers/kubernetes/workers.py +392 -0
  97. eyvan-0.0.1/eyvan/capacity/stage_policy.py +90 -0
  98. eyvan-0.0.1/eyvan/config.py +909 -0
  99. eyvan-0.0.1/eyvan/domain/__init__.py +66 -0
  100. eyvan-0.0.1/eyvan/domain/accelerators.py +32 -0
  101. eyvan-0.0.1/eyvan/domain/availability.py +200 -0
  102. eyvan-0.0.1/eyvan/domain/carbon.py +202 -0
  103. eyvan-0.0.1/eyvan/domain/costing.py +114 -0
  104. eyvan-0.0.1/eyvan/domain/governance.py +279 -0
  105. eyvan-0.0.1/eyvan/domain/models.py +820 -0
  106. eyvan-0.0.1/eyvan/domain/prediction.py +177 -0
  107. eyvan-0.0.1/eyvan/domain/pricing.py +158 -0
  108. eyvan-0.0.1/eyvan/domain/scheduler.py +1358 -0
  109. eyvan-0.0.1/eyvan/domain/sizing.py +472 -0
  110. eyvan-0.0.1/eyvan/domain/spend.py +123 -0
  111. eyvan-0.0.1/eyvan/domain/tpu_chips.py +124 -0
  112. eyvan-0.0.1/eyvan/identity/__init__.py +90 -0
  113. eyvan-0.0.1/eyvan/identity/assistant_keys.py +81 -0
  114. eyvan-0.0.1/eyvan/identity/metadata.py +238 -0
  115. eyvan-0.0.1/eyvan/identity/mtls.py +412 -0
  116. eyvan-0.0.1/eyvan/identity/rotation.py +421 -0
  117. eyvan-0.0.1/eyvan/identity/team_secrets.py +158 -0
  118. eyvan-0.0.1/eyvan/py.typed +0 -0
  119. eyvan-0.0.1/eyvan/records.py +4528 -0
  120. eyvan-0.0.1/eyvan/sdk/__init__.py +15 -0
  121. eyvan-0.0.1/eyvan/sdk/cli.py +188 -0
  122. eyvan-0.0.1/eyvan/sdk/client/__init__.py +27 -0
  123. eyvan-0.0.1/eyvan/sdk/client/async_client.py +513 -0
  124. eyvan-0.0.1/eyvan/sdk/client/callables.py +816 -0
  125. eyvan-0.0.1/eyvan/sdk/client/endpoint.py +62 -0
  126. eyvan-0.0.1/eyvan/sdk/client/idempotency.py +28 -0
  127. eyvan-0.0.1/eyvan/sdk/client/identity.py +133 -0
  128. eyvan-0.0.1/eyvan/sdk/client/jobs.py +518 -0
  129. eyvan-0.0.1/eyvan/sdk/client/requests.py +165 -0
  130. eyvan-0.0.1/eyvan/sdk/client/retry.py +62 -0
  131. eyvan-0.0.1/eyvan/sdk/client/sync.py +538 -0
  132. eyvan-0.0.1/eyvan/sdk/client/transport.py +550 -0
  133. eyvan-0.0.1/eyvan/sdk/client/types.py +14 -0
  134. eyvan-0.0.1/eyvan/sdk/commands/__init__.py +6 -0
  135. eyvan-0.0.1/eyvan/sdk/commands/artifacts.py +267 -0
  136. eyvan-0.0.1/eyvan/sdk/commands/assistant.py +597 -0
  137. eyvan-0.0.1/eyvan/sdk/commands/assistant_claude_code.py +84 -0
  138. eyvan-0.0.1/eyvan/sdk/commands/autoscale.py +663 -0
  139. eyvan-0.0.1/eyvan/sdk/commands/capacity.py +901 -0
  140. eyvan-0.0.1/eyvan/sdk/commands/common.py +103 -0
  141. eyvan-0.0.1/eyvan/sdk/commands/connect.py +385 -0
  142. eyvan-0.0.1/eyvan/sdk/commands/contexts.py +94 -0
  143. eyvan-0.0.1/eyvan/sdk/commands/dashboard.py +199 -0
  144. eyvan-0.0.1/eyvan/sdk/commands/demo.py +208 -0
  145. eyvan-0.0.1/eyvan/sdk/commands/deployment.py +124 -0
  146. eyvan-0.0.1/eyvan/sdk/commands/doctor.py +982 -0
  147. eyvan-0.0.1/eyvan/sdk/commands/doctor_preflights.py +340 -0
  148. eyvan-0.0.1/eyvan/sdk/commands/federation.py +317 -0
  149. eyvan-0.0.1/eyvan/sdk/commands/fleet_status.py +387 -0
  150. eyvan-0.0.1/eyvan/sdk/commands/fleets.py +755 -0
  151. eyvan-0.0.1/eyvan/sdk/commands/gcp.py +473 -0
  152. eyvan-0.0.1/eyvan/sdk/commands/gcp_connect.py +1339 -0
  153. eyvan-0.0.1/eyvan/sdk/commands/gcp_host_access.py +301 -0
  154. eyvan-0.0.1/eyvan/sdk/commands/governance.py +561 -0
  155. eyvan-0.0.1/eyvan/sdk/commands/head.py +3088 -0
  156. eyvan-0.0.1/eyvan/sdk/commands/head_discovery.py +232 -0
  157. eyvan-0.0.1/eyvan/sdk/commands/http.py +262 -0
  158. eyvan-0.0.1/eyvan/sdk/commands/mcp.py +326 -0
  159. eyvan-0.0.1/eyvan/sdk/commands/operations.py +227 -0
  160. eyvan-0.0.1/eyvan/sdk/commands/proof.py +1587 -0
  161. eyvan-0.0.1/eyvan/sdk/commands/query.py +123 -0
  162. eyvan-0.0.1/eyvan/sdk/commands/receipts.py +433 -0
  163. eyvan-0.0.1/eyvan/sdk/commands/research.py +238 -0
  164. eyvan-0.0.1/eyvan/sdk/commands/resources.py +338 -0
  165. eyvan-0.0.1/eyvan/sdk/commands/runtime.py +1149 -0
  166. eyvan-0.0.1/eyvan/sdk/commands/services.py +111 -0
  167. eyvan-0.0.1/eyvan/sdk/commands/soak.py +2157 -0
  168. eyvan-0.0.1/eyvan/sdk/commands/soak_monitor.py +594 -0
  169. eyvan-0.0.1/eyvan/sdk/commands/start.py +427 -0
  170. eyvan-0.0.1/eyvan/sdk/commands/state.py +363 -0
  171. eyvan-0.0.1/eyvan/sdk/commands/team.py +626 -0
  172. eyvan-0.0.1/eyvan/sdk/commands/tenancy.py +281 -0
  173. eyvan-0.0.1/eyvan/sdk/commands/track.py +565 -0
  174. eyvan-0.0.1/eyvan/sdk/commands/workloads.py +1914 -0
  175. eyvan-0.0.1/eyvan/sdk/contexts.py +261 -0
  176. eyvan-0.0.1/eyvan/sdk/execution.py +834 -0
  177. eyvan-0.0.1/eyvan/sdk/follow.py +415 -0
  178. eyvan-0.0.1/eyvan/sdk/job_receipt.py +414 -0
  179. eyvan-0.0.1/eyvan/sdk/lifecycle.py +113 -0
  180. eyvan-0.0.1/eyvan/sdk/node.py +279 -0
  181. eyvan-0.0.1/eyvan/sdk/shapes.py +60 -0
  182. eyvan-0.0.1/eyvan/sdk/spend.py +75 -0
  183. eyvan-0.0.1/eyvan/sdk/tables.py +161 -0
  184. eyvan-0.0.1/eyvan/sdk/team_credentials.py +289 -0
  185. eyvan-0.0.1/eyvan/sdk/terminal.py +133 -0
  186. eyvan-0.0.1/eyvan/sdk/timeline.py +184 -0
  187. eyvan-0.0.1/eyvan/sdk/workload_summary.py +204 -0
  188. eyvan-0.0.1/eyvan/secrets.py +370 -0
  189. eyvan-0.0.1/eyvan/server/__init__.py +6 -0
  190. eyvan-0.0.1/eyvan/server/api/__init__.py +67 -0
  191. eyvan-0.0.1/eyvan/server/api/app.py +4394 -0
  192. eyvan-0.0.1/eyvan/server/api/assistant.py +1208 -0
  193. eyvan-0.0.1/eyvan/server/api/assistant_claude_code.py +1082 -0
  194. eyvan-0.0.1/eyvan/server/api/assistant_presets.py +595 -0
  195. eyvan-0.0.1/eyvan/server/api/assistant_stream.py +291 -0
  196. eyvan-0.0.1/eyvan/server/api/attachments.py +190 -0
  197. eyvan-0.0.1/eyvan/server/api/auth.py +428 -0
  198. eyvan-0.0.1/eyvan/server/api/bootstrap_admin.py +136 -0
  199. eyvan-0.0.1/eyvan/server/api/dashboard_sessions.py +575 -0
  200. eyvan-0.0.1/eyvan/server/api/mcp_routes.py +985 -0
  201. eyvan-0.0.1/eyvan/server/api/research_routes.py +191 -0
  202. eyvan-0.0.1/eyvan/server/api/research_runner.py +253 -0
  203. eyvan-0.0.1/eyvan/server/api/schemas.py +1156 -0
  204. eyvan-0.0.1/eyvan/server/api/server_bind.py +87 -0
  205. eyvan-0.0.1/eyvan/server/api/server_logging.py +140 -0
  206. eyvan-0.0.1/eyvan/server/api/server_startup.py +303 -0
  207. eyvan-0.0.1/eyvan/server/api/sse.py +72 -0
  208. eyvan-0.0.1/eyvan/server/api/team_routes.py +374 -0
  209. eyvan-0.0.1/eyvan/server/api/tracking_proxy.py +285 -0
  210. eyvan-0.0.1/eyvan/server/controller/__init__.py +71 -0
  211. eyvan-0.0.1/eyvan/server/controller/_support.py +418 -0
  212. eyvan-0.0.1/eyvan/server/controller/capacity_commands.py +380 -0
  213. eyvan-0.0.1/eyvan/server/controller/expansion.py +208 -0
  214. eyvan-0.0.1/eyvan/server/controller/fleets.py +1233 -0
  215. eyvan-0.0.1/eyvan/server/controller/lifecycle.py +327 -0
  216. eyvan-0.0.1/eyvan/server/controller/log_archival.py +343 -0
  217. eyvan-0.0.1/eyvan/server/controller/loops.py +448 -0
  218. eyvan-0.0.1/eyvan/server/controller/observation.py +3247 -0
  219. eyvan-0.0.1/eyvan/server/controller/outbox.py +720 -0
  220. eyvan-0.0.1/eyvan/server/controller/preemption.py +837 -0
  221. eyvan-0.0.1/eyvan/server/controller/reclaim.py +462 -0
  222. eyvan-0.0.1/eyvan/server/controller/scheduling.py +478 -0
  223. eyvan-0.0.1/eyvan/server/controller/services.py +661 -0
  224. eyvan-0.0.1/eyvan/server/controller/settlement.py +1519 -0
  225. eyvan-0.0.1/eyvan/server/controller/staging.py +935 -0
  226. eyvan-0.0.1/eyvan/server/controller/webhook_delivery.py +264 -0
  227. eyvan-0.0.1/eyvan/server/controller/workload_commands.py +1936 -0
  228. eyvan-0.0.1/eyvan/server/introspection.py +139 -0
  229. eyvan-0.0.1/eyvan/server/invariants.py +612 -0
  230. eyvan-0.0.1/eyvan/server/local/__init__.py +6 -0
  231. eyvan-0.0.1/eyvan/server/local/attach_job.py +309 -0
  232. eyvan-0.0.1/eyvan/server/local/auth.py +286 -0
  233. eyvan-0.0.1/eyvan/server/local/daemon.py +1385 -0
  234. eyvan-0.0.1/eyvan/server/local/profile.py +132 -0
  235. eyvan-0.0.1/eyvan/server/local/tracker.py +345 -0
  236. eyvan-0.0.1/eyvan/server/persistence/__init__.py +47 -0
  237. eyvan-0.0.1/eyvan/server/persistence/base.py +635 -0
  238. eyvan-0.0.1/eyvan/server/persistence/leader.py +125 -0
  239. eyvan-0.0.1/eyvan/server/persistence/local.py +1587 -0
  240. eyvan-0.0.1/eyvan/server/persistence/memory.py +23 -0
  241. eyvan-0.0.1/eyvan/server/persistence/migrate.py +398 -0
  242. eyvan-0.0.1/eyvan/server/persistence/migrations/__init__.py +6 -0
  243. eyvan-0.0.1/eyvan/server/persistence/migrations/env.py +65 -0
  244. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0002_transactional_outbox.py +84 -0
  245. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0003_capacity_pools.py +32 -0
  246. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0004_query_indexes.py +52 -0
  247. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0005_retention_columns.py +53 -0
  248. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0006_artifact_index.py +96 -0
  249. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0007_federation_identity.py +81 -0
  250. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0008_progress_reports.py +47 -0
  251. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0009_tenant_registry.py +64 -0
  252. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0010_role_grants.py +58 -0
  253. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0011_quota_grants.py +69 -0
  254. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0012_audit_event_time.py +49 -0
  255. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0012_scoped_artifact_identity.py +290 -0
  256. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0013_merge_artifact_audit.py +25 -0
  257. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0014_artifact_lifecycle.py +151 -0
  258. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0015_attempt_topology.py +66 -0
  259. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0016_cell_stages.py +73 -0
  260. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0016_credential_rotation.py +70 -0
  261. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0016_expansion_admissions.py +74 -0
  262. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0017_merge_stage_rot.py +32 -0
  263. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0018_service_operations.py +69 -0
  264. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0019_webhooks.py +54 -0
  265. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0020_team_accounts.py +64 -0
  266. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0021_team_requests.py +41 -0
  267. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0022_assistant_providers.py +36 -0
  268. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0023_assistant_conversations.py +38 -0
  269. eyvan-0.0.1/eyvan/server/persistence/migrations/versions/0024_research_plans.py +41 -0
  270. eyvan-0.0.1/eyvan/server/persistence/sqlalchemy.py +2427 -0
  271. eyvan-0.0.1/eyvan/server/persistence/state.py +1217 -0
  272. eyvan-0.0.1/eyvan/server/service/__init__.py +101 -0
  273. eyvan-0.0.1/eyvan/server/service/_control_plane/__init__.py +6 -0
  274. eyvan-0.0.1/eyvan/server/service/_control_plane/accounts.py +419 -0
  275. eyvan-0.0.1/eyvan/server/service/_control_plane/artifact_admission.py +263 -0
  276. eyvan-0.0.1/eyvan/server/service/_control_plane/artifact_collection.py +438 -0
  277. eyvan-0.0.1/eyvan/server/service/_control_plane/artifact_inventory.py +418 -0
  278. eyvan-0.0.1/eyvan/server/service/_control_plane/artifact_io.py +257 -0
  279. eyvan-0.0.1/eyvan/server/service/_control_plane/artifact_recovery.py +300 -0
  280. eyvan-0.0.1/eyvan/server/service/_control_plane/assistant_conversations.py +185 -0
  281. eyvan-0.0.1/eyvan/server/service/_control_plane/assistant_providers.py +259 -0
  282. eyvan-0.0.1/eyvan/server/service/_control_plane/audit.py +487 -0
  283. eyvan-0.0.1/eyvan/server/service/_control_plane/callable_submission.py +648 -0
  284. eyvan-0.0.1/eyvan/server/service/_control_plane/cells.py +455 -0
  285. eyvan-0.0.1/eyvan/server/service/_control_plane/child_submission.py +216 -0
  286. eyvan-0.0.1/eyvan/server/service/_control_plane/estimates.py +291 -0
  287. eyvan-0.0.1/eyvan/server/service/_control_plane/events.py +86 -0
  288. eyvan-0.0.1/eyvan/server/service/_control_plane/expansion.py +796 -0
  289. eyvan-0.0.1/eyvan/server/service/_control_plane/federation.py +597 -0
  290. eyvan-0.0.1/eyvan/server/service/_control_plane/fleets.py +795 -0
  291. eyvan-0.0.1/eyvan/server/service/_control_plane/governance.py +333 -0
  292. eyvan-0.0.1/eyvan/server/service/_control_plane/lease_settlement.py +510 -0
  293. eyvan-0.0.1/eyvan/server/service/_control_plane/leases.py +510 -0
  294. eyvan-0.0.1/eyvan/server/service/_control_plane/policies.py +358 -0
  295. eyvan-0.0.1/eyvan/server/service/_control_plane/reporting.py +389 -0
  296. eyvan-0.0.1/eyvan/server/service/_control_plane/research.py +1004 -0
  297. eyvan-0.0.1/eyvan/server/service/_control_plane/scheduling.py +287 -0
  298. eyvan-0.0.1/eyvan/server/service/_control_plane/services.py +430 -0
  299. eyvan-0.0.1/eyvan/server/service/_control_plane/shared.py +879 -0
  300. eyvan-0.0.1/eyvan/server/service/_control_plane/submission.py +300 -0
  301. eyvan-0.0.1/eyvan/server/service/_control_plane/team_requests.py +142 -0
  302. eyvan-0.0.1/eyvan/server/service/_control_plane/tenancy.py +394 -0
  303. eyvan-0.0.1/eyvan/server/service/_control_plane/transactions.py +154 -0
  304. eyvan-0.0.1/eyvan/server/service/_control_plane/webhooks.py +202 -0
  305. eyvan-0.0.1/eyvan/server/service/_control_plane/workload_lifecycle.py +626 -0
  306. eyvan-0.0.1/eyvan/server/service/_control_plane/workload_settlement.py +492 -0
  307. eyvan-0.0.1/eyvan/server/service/_control_plane/workload_storage.py +263 -0
  308. eyvan-0.0.1/eyvan/server/service/authz.py +101 -0
  309. eyvan-0.0.1/eyvan/server/service/batch.py +136 -0
  310. eyvan-0.0.1/eyvan/server/service/callable_trust.py +70 -0
  311. eyvan-0.0.1/eyvan/server/service/control_plane.py +840 -0
  312. eyvan-0.0.1/eyvan/server/service/credential_rotation.py +302 -0
  313. eyvan-0.0.1/eyvan/server/service/dag.py +143 -0
  314. eyvan-0.0.1/eyvan/server/service/errors.py +181 -0
  315. eyvan-0.0.1/eyvan/server/service/expansion.py +312 -0
  316. eyvan-0.0.1/eyvan/server/service/federation.py +381 -0
  317. eyvan-0.0.1/eyvan/server/service/groups.py +116 -0
  318. eyvan-0.0.1/eyvan/server/service/locality.py +162 -0
  319. eyvan-0.0.1/eyvan/server/service/pricing_resolver.py +194 -0
  320. eyvan-0.0.1/eyvan/server/service/provider_diagnostics.py +87 -0
  321. eyvan-0.0.1/eyvan/server/service/research_losses.py +105 -0
  322. eyvan-0.0.1/eyvan/server/service/scheduling.py +749 -0
  323. eyvan-0.0.1/eyvan/server/service/services.py +911 -0
  324. eyvan-0.0.1/eyvan/server/service/stage.py +505 -0
  325. eyvan-0.0.1/eyvan/server/service/state.py +68 -0
  326. eyvan-0.0.1/eyvan/server/service/subjobs.py +175 -0
  327. eyvan-0.0.1/eyvan/server/service/webhooks.py +176 -0
  328. eyvan-0.0.1/eyvan/server/service/workload_progress.py +489 -0
  329. eyvan-0.0.1/eyvan/soak_contract.py +410 -0
  330. eyvan-0.0.1/eyvan/soak_evidence.py +386 -0
  331. eyvan-0.0.1/eyvan/track/__init__.py +41 -0
  332. eyvan-0.0.1/eyvan/track/_format.py +328 -0
  333. eyvan-0.0.1/eyvan/track/_gcs.py +212 -0
  334. eyvan-0.0.1/eyvan/track/_rich.py +435 -0
  335. eyvan-0.0.1/eyvan/track/_run.py +1625 -0
  336. eyvan-0.0.1/eyvan/track/_store.py +274 -0
  337. eyvan-0.0.1/eyvan/track/tracker/__init__.py +11 -0
  338. eyvan-0.0.1/eyvan/track/tracker/__main__.py +11 -0
  339. eyvan-0.0.1/eyvan/track/tracker/aggregates.py +297 -0
  340. eyvan-0.0.1/eyvan/track/tracker/app.py +244 -0
  341. eyvan-0.0.1/eyvan/track/tracker/cli.py +51 -0
  342. eyvan-0.0.1/eyvan/track/tracker/index.py +682 -0
  343. eyvan-0.0.1/eyvan/track/tracker/phase2.py +210 -0
  344. eyvan-0.0.1/eyvan/track/tracker/phase3.py +538 -0
  345. eyvan-0.0.1/eyvan/track/tracker/phase3_api.py +155 -0
  346. eyvan-0.0.1/eyvan/track/tracker/phase3_index.py +200 -0
  347. eyvan-0.0.1/eyvan/track/tracker/phase3_records.py +194 -0
  348. eyvan-0.0.1/eyvan/track/tracker/records.py +171 -0
  349. eyvan-0.0.1/eyvan/track/tracker/replay.py +38 -0
  350. eyvan-0.0.1/eyvan/track/tracker/rich_sql.py +165 -0
  351. eyvan-0.0.1/eyvan/worker/__init__.py +6 -0
  352. eyvan-0.0.1/eyvan/worker/agent/__init__.py +30 -0
  353. eyvan-0.0.1/eyvan/worker/agent/app.py +379 -0
  354. eyvan-0.0.1/eyvan/worker/agent/cli.py +100 -0
  355. eyvan-0.0.1/eyvan/worker/agent/client.py +549 -0
  356. eyvan-0.0.1/eyvan/worker/agent/models.py +378 -0
  357. eyvan-0.0.1/eyvan/worker/agent/service.py +1215 -0
  358. eyvan-0.0.1/eyvan/worker/distributed_environment.py +651 -0
  359. eyvan-0.0.1/eyvan/worker/identity.py +100 -0
  360. eyvan-0.0.1/eyvan/worker/runtime/__init__.py +123 -0
  361. eyvan-0.0.1/eyvan/worker/runtime/_multihost_site.py +531 -0
  362. eyvan-0.0.1/eyvan/worker/runtime/callable_protocol.py +659 -0
  363. eyvan-0.0.1/eyvan/worker/runtime/callable_worker.py +129 -0
  364. eyvan-0.0.1/eyvan/worker/runtime/callables.py +12 -0
  365. eyvan-0.0.1/eyvan/worker/runtime/container.py +781 -0
  366. eyvan-0.0.1/eyvan/worker/runtime/dependency_entry.py +294 -0
  367. eyvan-0.0.1/eyvan/worker/runtime/host_accelerators.py +83 -0
  368. eyvan-0.0.1/eyvan/worker/runtime/http_retry.py +48 -0
  369. eyvan-0.0.1/eyvan/worker/runtime/in_job.py +206 -0
  370. eyvan-0.0.1/eyvan/worker/runtime/local_process.py +1044 -0
  371. eyvan-0.0.1/eyvan/worker/runtime/local_worker.py +243 -0
  372. eyvan-0.0.1/eyvan/worker/runtime/log_records.py +1472 -0
  373. eyvan-0.0.1/eyvan/worker/runtime/native_bootstrap.py +749 -0
  374. eyvan-0.0.1/eyvan/worker/runtime/native_gang.py +983 -0
  375. eyvan-0.0.1/eyvan/worker/runtime/native_remote.py +479 -0
  376. eyvan-0.0.1/eyvan/worker/runtime/native_slice.py +1484 -0
  377. eyvan-0.0.1/eyvan/worker/runtime/native_tls_bootstrap.py +119 -0
  378. eyvan-0.0.1/eyvan/worker/runtime/native_worker.py +689 -0
  379. eyvan-0.0.1/eyvan/worker/runtime/node_health.py +491 -0
  380. eyvan-0.0.1/eyvan/worker/runtime/oci_callable_runner.py +103 -0
  381. eyvan-0.0.1/eyvan/worker/runtime/oci_callable_stager.py +127 -0
  382. eyvan-0.0.1/eyvan/worker/runtime/progress.py +190 -0
  383. eyvan-0.0.1/eyvan/worker/runtime/registry.py +729 -0
  384. eyvan-0.0.1/eyvan/worker/runtime/results.py +12 -0
  385. eyvan-0.0.1/eyvan/worker/runtime/secret_materialization.py +219 -0
  386. eyvan-0.0.1/eyvan/worker/runtime/stage_executor.py +790 -0
  387. eyvan-0.0.1/eyvan/worker/runtime/systemd_transient.py +2482 -0
  388. eyvan-0.0.1/eyvan/worker/runtime/workspace_entry.py +166 -0
  389. eyvan-0.0.1/pyproject.toml +177 -0
eyvan-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,305 @@
1
+ Metadata-Version: 2.3
2
+ Name: eyvan
3
+ Version: 0.0.1
4
+ Summary: A policy-aware global fleet control plane with native GCP CPU, GPU, and TPU capacity
5
+ Author: Erfan Zare Chavoshi
6
+ Author-email: Erfan Zare Chavoshi <Erfanzare810@gmail.com>
7
+ License: AGPL-3.0-or-later
8
+ Requires-Dist: alembic>=1.14.0
9
+ Requires-Dist: asyncpg>=0.30.0
10
+ Requires-Dist: click>=8.4.2
11
+ Requires-Dist: cloudpickle>=3.1.0
12
+ Requires-Dist: cryptography>=50.0.0
13
+ Requires-Dist: fastapi>=0.141.1
14
+ Requires-Dist: httpx>=0.27.0
15
+ Requires-Dist: idna>=3.18
16
+ Requires-Dist: opentelemetry-api>=1.28.0
17
+ Requires-Dist: prometheus-client>=0.21.0
18
+ Requires-Dist: pydantic>=2.11.0
19
+ Requires-Dist: pygments>=2.20.0
20
+ Requires-Dist: pyjwt[crypto]>=2.9.0
21
+ Requires-Dist: pyyaml>=6.0
22
+ Requires-Dist: rich>=13.9
23
+ Requires-Dist: sqlalchemy[asyncio]>=2.0.36
24
+ Requires-Dist: starlette>=1.5.0
25
+ Requires-Dist: typing-extensions>=4.12.0
26
+ Requires-Dist: uvicorn[standard]>=0.48.0
27
+ Requires-Dist: pytest>=8.3.0 ; extra == 'dev'
28
+ Requires-Dist: pytest-asyncio>=0.24.0 ; extra == 'dev'
29
+ Requires-Dist: aiosqlite>=0.20.0 ; extra == 'dev'
30
+ Requires-Dist: hypothesis>=6.100.0 ; extra == 'dev'
31
+ Requires-Dist: pytest-cov>=6.0.0 ; extra == 'dev'
32
+ Requires-Dist: detect-secrets>=1.5.0 ; extra == 'dev'
33
+ Requires-Dist: mypy>=1.15 ; extra == 'dev'
34
+ Requires-Dist: pytest-xdist>=3.6 ; extra == 'dev'
35
+ Requires-Dist: ruff==0.15.16 ; extra == 'dev'
36
+ Requires-Dist: import-linter>=2.1 ; extra == 'dev'
37
+ Requires-Dist: pip-audit==2.10.1 ; extra == 'dev'
38
+ Requires-Dist: opentelemetry-sdk==1.45.1 ; extra == 'dev'
39
+ Requires-Dist: google-cloud-storage>=2.18.0 ; extra == 'oci'
40
+ Requires-Python: >=3.11, <3.14
41
+ Provides-Extra: dev
42
+ Provides-Extra: oci
43
+ Description-Content-Type: text/markdown
44
+
45
+ # Eyvan (ایوان)
46
+
47
+ Eyvan is a capacity plane for research compute. You state the shape of work you
48
+ need — `2 × v5p-16, spot, this fleet` — as a digest-verified unsigned Python
49
+ callable submitted to an explicitly trusted project. The plane acquires the
50
+ machines, boots them, dispatches your callable, and returns its result.
51
+ Capacity records show what was requested, what a provider accepted or refused,
52
+ and how long the handover took.
53
+
54
+ ## The sixty-second version
55
+
56
+ ```bash
57
+ uv sync --extra dev # workspace install + development dependencies
58
+ uv run eyvan up examples/laptop.yaml # start the local loopback CPU fleet before SDK init
59
+ uv run eyvan start # find or point at a control plane
60
+ uv run eyvan doctor # what is missing, named together
61
+ ```
62
+
63
+ Eyvan supports Python `>=3.11,<3.14` (the range declared in `pyproject.toml`).
64
+
65
+ ```python
66
+ from eyvan import CpuConfig, execute, init
67
+
68
+ init(fleet="laptop")
69
+
70
+
71
+ @execute(CpuConfig())
72
+ def train():
73
+ return sum(range(10))
74
+ ```
75
+
76
+ Calling `train()` submits the callable and waits, narrating progress:
77
+ `queued`, `provisioning`, `blocked … the plane is retrying (attempt N)`,
78
+ `dispatching`, then your result. The job is durable — it keeps running if your
79
+ client exits (`eyvan workload status <id>` to follow).
80
+
81
+ ### With a TPU fleet
82
+
83
+ First configure a fleet with matching TPU pools and a runtime that provides
84
+ JAX. The laptop fleet above has only CPU capacity.
85
+
86
+ ```python
87
+ from eyvan import TpuConfig, execute, init
88
+ from eyvan.records import CapacityClass
89
+
90
+ init(fleet="research-us-central1-a")
91
+
92
+
93
+ @execute(TpuConfig(type="v5p-16", pods=2, capacity_class=CapacityClass.SPOT))
94
+ def device_count():
95
+ import jax
96
+
97
+ return jax.device_count()
98
+ ```
99
+
100
+ ## The SDK in one page
101
+
102
+ ### Connecting: `init`
103
+
104
+ ```python
105
+ init(address=None, /, *, fleet=None, org_id=None, project_id=None,
106
+ artifact_uri=None, artifact_store=None, ...)
107
+ ```
108
+
109
+ With no arguments the SDK discovers the plane the CLI uses (`eyvan start`
110
+ shows you what exists: a local plane, or heads in your project). Point it at
111
+ an explicit plane by address — `eyvan.init("http://10.0.0.5:8080")` — or
112
+ bind a default fleet with `eyvan.init(fleet="research-us-central1-a")`.
113
+ Everything else is scope (`org_id`, `project_id`), where artifacts go (a
114
+ `gs://` root or your own `ArtifactStore` implementation), and fleet-state
115
+ location (`EYVAN_FLEET_STATE_URI`) when agents own distinct capacity
116
+ boundaries.
117
+
118
+ ### The shape: `TpuConfig`, `GpuConfig`, `CpuConfig`
119
+
120
+ One decorator takes all three; everything under it is shape-agnostic. The
121
+ TPU config's full surface (`eyvan/sdk/client/jobs.py`):
122
+
123
+ | field | default | meaning |
124
+ |---|---|---|
125
+ | `type` | — | accelerator type, e.g. `"v5p-16"`, `"v6e-8"` |
126
+ | `pods` | `1` | workers — how many slices of `type` the job asks for |
127
+ | `atomic` | `False` | `False` (**elastic**, node-pool style): pack warm cells of the same type and provision only the deficit — going `pods` 2→4 keeps the two warm slices and asks for two more, one lease group, one hardware world per cell. `True`: one exact-shape provider resource, one hardware world spanning every pod — what single-mesh training needs |
128
+ | `capacity_class` | Spot preference | `SPOT`, `ON_DEMAND`, `RESERVED`, or `FLEX_START`; an explicit value is exact. If omitted, a reserved-only fleet may substitute `RESERVED` |
129
+ | `max_retries` | `DEFAULT` | retries for **lost capacity** attempts |
130
+ | `max_preemption_retries` | `10` | restarts after the provider reclaims spot — deliberately generous; reclamation is the cheap failure |
131
+ | `max_failure_retries` | `0` | retries of the job's *own* failure — deliberately stingy; a non-zero exit usually repeats, and re-running it costs an accelerator |
132
+ | `secret_mounts` | `{}` | secret **references** resolved at dispatch into env vars on the cell — a reference is what gets persisted, never the value |
133
+ | `checkpointable` / `checkpoint_hook` / `checkpoint_output_uri` | `False`/— | the scheduler grants preemption-checkpoint time only when a real hook is named; otherwise a reclaimed job restarts from zero |
134
+ | `can_submit_children` | `False` | lets the job submit children under your identity — off by default; a credential nobody asked for is one nobody is watching |
135
+ | `dependencies` | `()` | packages installed on the cell before your callable loads — adding a library should not mean rebuilding an image |
136
+
137
+ ### The decorator: `execute`
138
+
139
+ ```python
140
+ @execute(TpuConfig(type="v6e-8", pods=4), workspace="src/")
141
+ def run(epochs: int):
142
+ ...
143
+ ```
144
+
145
+ `workspace=` accepts a directory path and ships that tree to the worker's
146
+ working directory before the callable imports. Omit it to derive the workspace
147
+ from the decorated function's source-file directory; interactive callables
148
+ without a source file need an explicit path. Set `workspace=False` to disable
149
+ workspace shipping.
150
+
151
+ ### Calling: blocking wait, or detached handle
152
+
153
+ ```python
154
+ result = run(epochs=3) # blocks; live progress lines; returns your value
155
+ ```
156
+
157
+ ```python
158
+ job = run.submit(epochs=3) # EyvanJob — detach, follow, intervene
159
+ job.status() # WorkloadState
160
+ job.logs() # the flattened, globally-ranked log stream
161
+ job.wait(timeout=600, progress=True) # blocking wait, same narration
162
+ job.result(timeout=3600) # your value, or EyvanJobError with the reason
163
+ job.cancel() # durable cancel
164
+ ```
165
+
166
+ Your callable's *return value* comes back through the artifact store; its
167
+ imports resolve on the cell (image packages + `dependencies` + whatever
168
+ `workspace` shipped). Identical callables deduplicate by content digest;
169
+ a concurrent upload verifies the existing object's digest before using it.
170
+ See [artifact-safety](docs/artifact-safety.md).
171
+
172
+ One more client-side knob worth knowing: the returned job exposes its
173
+ transport (`.base_url`) so tooling built on the SDK can follow the same
174
+ plane the SDK followed, without re-deriving discovery.
175
+
176
+ Failure narration is part of the API contract: a refused capacity attempt
177
+ renders as `blocked | … | the plane is retrying (attempt N)` with the
178
+ provider's diagnostic, and a terminal failure arrives as an exception whose
179
+ message contains the provider's own sentence — not a bare exit code.
180
+
181
+ ## Developing on top of Eyvan
182
+
183
+ Four seams, in order of how often you need them:
184
+
185
+ 1. **A different shape** — no code: a `TpuConfig`/`GpuConfig`/`CpuConfig`
186
+ value. Check the shape is real for you first:
187
+ `eyvan capacity quota --fits v5p-16:2` (quota **and** admission
188
+ permission **and** supply are three different gates).
189
+ 2. **A different fleet** — a YAML config: `eyvan up <config>` from a
190
+ hand-written file (see `examples/fleet.yaml`, `examples/laptop.yaml`) or
191
+ a generated fleet (`eyvan up --region <region> --preemptible`, or
192
+ `eyvan up --quota-based --zone <zone> --preemptible`). Node types, runtime
193
+ env, and autoscaling knobs live in the config, not in your callable.
194
+ 3. **A different cloud** — a provider package with a driver and transport.
195
+ External plugins default to single-machine cells; multi-worker planning
196
+ also needs an in-tree capability entry and a supporting pool factory.
197
+ See [providers](docs/providers.md) for the ABI and conformance contract.
198
+ 4. **A different workflow** — composition: `can_submit_children=True` grants
199
+ your job a submission capability under your identity (fan-out workers,
200
+ coordinator patterns), and checkpointing hooks let long spot jobs survive
201
+ reclamation by design rather than by luck.
202
+
203
+ ### Developing Eyvan itself
204
+
205
+ ```bash
206
+ git clone <this repo> && cd eyvan
207
+ uv sync --extra dev # editable install + dev deps (pytest, pytest-asyncio)
208
+ npm --prefix dashboard ci
209
+ npm --prefix dashboard run build # build the SPA before Python tests
210
+ uv run pytest tests -m fast -q # smoke subset for iteration, not a release gate
211
+ uv run pytest tests -q -rs # full suite; real PostgreSQL requires the test fixture setup
212
+ uv run ruff check eyvan tests # lint (line 121, py3.11)
213
+ uv run eyvan-server --log-level info # run the plane from source
214
+ uv run eyvan-agent --host 127.0.0.1 --port 8090 --allow-unauthenticated # local dev only
215
+ ```
216
+
217
+ Verify the dashboard from a fresh checkout with the commands in
218
+ [Contributing — Dashboard](CONTRIBUTING.md#running-the-tests):
219
+
220
+ ```bash
221
+ npm --prefix dashboard ci
222
+ npm --prefix dashboard test
223
+ npm --prefix dashboard run build
224
+ ```
225
+
226
+ The rules that keep the package honest — enforce them in review, not in
227
+ memory:
228
+
229
+ - **Provider boundary:** nothing that decides (scheduler, planner, durable
230
+ model) may name a provider; `tests/test_provider_boundary.py` enforces it.
231
+ - **Claims need receipts:** a behavior claim cites a recorded run; hardware
232
+ claims go through `eyvan proof` (exit 0 pass, 1 fail, 2 *did not exercise
233
+ the behaviour*, 3 refusal) — see [proofs](docs/proofs.md).
234
+ - **Tests assert public behavior:** state transitions, API outputs, parity —
235
+ not private helper calls or log strings.
236
+ - **Diagnostics travel with failures:** a CLI or provider failure raises with
237
+ its own words attached (`GcsCommandError` carries command + stderr).
238
+ - Architecture decisions are design records under
239
+ [docs/design/](docs/design/0001-scoped-artifact-lifecycle.md), each stating
240
+ its real implementation status.
241
+
242
+ ## The ideas everything else follows from
243
+
244
+ 1. **You state the shape, not the pool.** The scheduler and capacity planner
245
+ decide where that shape can exist.
246
+ 2. **Receipts or it did not happen.** Capacity claims cite recorded runs.
247
+ 3. **Failure narrates itself.** Diagnostics render, never `FAILED`.
248
+ 4. **Nothing that decides names a provider.** Clouds plug in; the core stays
249
+ agnostic.
250
+ 5. **Durable state survives the plane.** A restarted `eyvan-server`
251
+ reconciles the whole world from its durable store.
252
+
253
+ ## Concepts
254
+
255
+ | term | meaning |
256
+ |---------|--------------------------------------------------------------------|
257
+ | plane | the control plane (`eyvan-server`) — scheduler, planner, state |
258
+ | agent | a cell agent (`eyvan-agent`) owning machines on one backend |
259
+ | fleet | a named set of capacity pools you can submit into |
260
+ | pool | one (backend, accelerator, capacity class, zone) combination |
261
+ | cell | one acquired allocation (e.g. one spot queued resource) |
262
+ | workload| your callable + its requested shape, moving through durable states |
263
+
264
+ ## Where it runs
265
+
266
+ Registered capacity backends: `local` (loopback laptop fleets), `gcp-tpu`
267
+ (generated zone fleets driving TPU queued resources, spot or on-demand),
268
+ `gcp-compute`, the `gcp` umbrella, `aws-ec2` (the worked provider example)
269
+ and the `aws` umbrella, `azure-vm` and the `azure` umbrella, `kubernetes`
270
+ (`k8s`) against a real API server, `manual`, `onprem-ssh`, and `gcp-attach`
271
+ (an existing Cloud TPU VM attached with `eyvan gcp connect`; observed, never
272
+ created or deleted).
273
+
274
+ Backend availability is not proof of qualification on your infrastructure.
275
+ GCP TPU is the backend with live hardware runs; the on-premises SSH driver is
276
+ code with no run against a real SSH host yet. See [proofs](docs/proofs.md) for
277
+ evidence requirements and backend-specific limits.
278
+
279
+ ## The docs map
280
+
281
+ New to the project? Start with the [tutorial](docs/tutorial/README.md) —
282
+ seventeen source-grounded parts that walk from "what is Eyvan" through the SDK,
283
+ the control plane, providers, operations, deployment, and an explicit Spot TPU example.
284
+
285
+ | page | what it answers |
286
+ |---|---|
287
+ | [tutorial](docs/tutorial/README.md) | a part-per-subsystem tutorial, grounded in the source |
288
+ | [eyvan-explained](docs/eyvan-explained.md) | the mental model, one workload's full journey |
289
+ | [install](docs/install.md) | laptop path, the fifteen, GCP head, secrets |
290
+ | [operate](docs/operate.md) | the runbook: fleets, workloads, capacity, zone racing |
291
+ | [runtimes](docs/runtimes.md) | the two provisioning models, the defaults profile, custom images |
292
+ | [proofs](docs/proofs.md) | what is proven, with receipts; known rough edges |
293
+ | [providers](docs/providers.md) | writing a capacity provider; the conformance contract |
294
+ | [security](docs/security.md) | trust boundaries, tokens, what jobs can do |
295
+ | [env-surface](docs/env-surface.md) | every `EYVAN_*` variable |
296
+ | [artifact-safety](docs/artifact-safety.md) | tenancy, lifecycle, the digest-addressed store |
297
+ | [troubleshoot](docs/troubleshoot.md) | symptom → cause → action tables |
298
+ | [design records](docs/design/0001-scoped-artifact-lifecycle.md) | the ADRs and their real status |
299
+
300
+ ## What is proven
301
+
302
+ See [proofs](docs/proofs.md) for proof criteria and evidence limits. After a
303
+ restart, use the intended durable state and matching credentials; inspect
304
+ quarantined leases before intervening. See [operate](docs/operate.md) and
305
+ [troubleshoot](docs/troubleshoot.md) for recovery procedures.
eyvan-0.0.1/README.md ADDED
@@ -0,0 +1,261 @@
1
+ # Eyvan (ایوان)
2
+
3
+ Eyvan is a capacity plane for research compute. You state the shape of work you
4
+ need — `2 × v5p-16, spot, this fleet` — as a digest-verified unsigned Python
5
+ callable submitted to an explicitly trusted project. The plane acquires the
6
+ machines, boots them, dispatches your callable, and returns its result.
7
+ Capacity records show what was requested, what a provider accepted or refused,
8
+ and how long the handover took.
9
+
10
+ ## The sixty-second version
11
+
12
+ ```bash
13
+ uv sync --extra dev # workspace install + development dependencies
14
+ uv run eyvan up examples/laptop.yaml # start the local loopback CPU fleet before SDK init
15
+ uv run eyvan start # find or point at a control plane
16
+ uv run eyvan doctor # what is missing, named together
17
+ ```
18
+
19
+ Eyvan supports Python `>=3.11,<3.14` (the range declared in `pyproject.toml`).
20
+
21
+ ```python
22
+ from eyvan import CpuConfig, execute, init
23
+
24
+ init(fleet="laptop")
25
+
26
+
27
+ @execute(CpuConfig())
28
+ def train():
29
+ return sum(range(10))
30
+ ```
31
+
32
+ Calling `train()` submits the callable and waits, narrating progress:
33
+ `queued`, `provisioning`, `blocked … the plane is retrying (attempt N)`,
34
+ `dispatching`, then your result. The job is durable — it keeps running if your
35
+ client exits (`eyvan workload status <id>` to follow).
36
+
37
+ ### With a TPU fleet
38
+
39
+ First configure a fleet with matching TPU pools and a runtime that provides
40
+ JAX. The laptop fleet above has only CPU capacity.
41
+
42
+ ```python
43
+ from eyvan import TpuConfig, execute, init
44
+ from eyvan.records import CapacityClass
45
+
46
+ init(fleet="research-us-central1-a")
47
+
48
+
49
+ @execute(TpuConfig(type="v5p-16", pods=2, capacity_class=CapacityClass.SPOT))
50
+ def device_count():
51
+ import jax
52
+
53
+ return jax.device_count()
54
+ ```
55
+
56
+ ## The SDK in one page
57
+
58
+ ### Connecting: `init`
59
+
60
+ ```python
61
+ init(address=None, /, *, fleet=None, org_id=None, project_id=None,
62
+ artifact_uri=None, artifact_store=None, ...)
63
+ ```
64
+
65
+ With no arguments the SDK discovers the plane the CLI uses (`eyvan start`
66
+ shows you what exists: a local plane, or heads in your project). Point it at
67
+ an explicit plane by address — `eyvan.init("http://10.0.0.5:8080")` — or
68
+ bind a default fleet with `eyvan.init(fleet="research-us-central1-a")`.
69
+ Everything else is scope (`org_id`, `project_id`), where artifacts go (a
70
+ `gs://` root or your own `ArtifactStore` implementation), and fleet-state
71
+ location (`EYVAN_FLEET_STATE_URI`) when agents own distinct capacity
72
+ boundaries.
73
+
74
+ ### The shape: `TpuConfig`, `GpuConfig`, `CpuConfig`
75
+
76
+ One decorator takes all three; everything under it is shape-agnostic. The
77
+ TPU config's full surface (`eyvan/sdk/client/jobs.py`):
78
+
79
+ | field | default | meaning |
80
+ |---|---|---|
81
+ | `type` | — | accelerator type, e.g. `"v5p-16"`, `"v6e-8"` |
82
+ | `pods` | `1` | workers — how many slices of `type` the job asks for |
83
+ | `atomic` | `False` | `False` (**elastic**, node-pool style): pack warm cells of the same type and provision only the deficit — going `pods` 2→4 keeps the two warm slices and asks for two more, one lease group, one hardware world per cell. `True`: one exact-shape provider resource, one hardware world spanning every pod — what single-mesh training needs |
84
+ | `capacity_class` | Spot preference | `SPOT`, `ON_DEMAND`, `RESERVED`, or `FLEX_START`; an explicit value is exact. If omitted, a reserved-only fleet may substitute `RESERVED` |
85
+ | `max_retries` | `DEFAULT` | retries for **lost capacity** attempts |
86
+ | `max_preemption_retries` | `10` | restarts after the provider reclaims spot — deliberately generous; reclamation is the cheap failure |
87
+ | `max_failure_retries` | `0` | retries of the job's *own* failure — deliberately stingy; a non-zero exit usually repeats, and re-running it costs an accelerator |
88
+ | `secret_mounts` | `{}` | secret **references** resolved at dispatch into env vars on the cell — a reference is what gets persisted, never the value |
89
+ | `checkpointable` / `checkpoint_hook` / `checkpoint_output_uri` | `False`/— | the scheduler grants preemption-checkpoint time only when a real hook is named; otherwise a reclaimed job restarts from zero |
90
+ | `can_submit_children` | `False` | lets the job submit children under your identity — off by default; a credential nobody asked for is one nobody is watching |
91
+ | `dependencies` | `()` | packages installed on the cell before your callable loads — adding a library should not mean rebuilding an image |
92
+
93
+ ### The decorator: `execute`
94
+
95
+ ```python
96
+ @execute(TpuConfig(type="v6e-8", pods=4), workspace="src/")
97
+ def run(epochs: int):
98
+ ...
99
+ ```
100
+
101
+ `workspace=` accepts a directory path and ships that tree to the worker's
102
+ working directory before the callable imports. Omit it to derive the workspace
103
+ from the decorated function's source-file directory; interactive callables
104
+ without a source file need an explicit path. Set `workspace=False` to disable
105
+ workspace shipping.
106
+
107
+ ### Calling: blocking wait, or detached handle
108
+
109
+ ```python
110
+ result = run(epochs=3) # blocks; live progress lines; returns your value
111
+ ```
112
+
113
+ ```python
114
+ job = run.submit(epochs=3) # EyvanJob — detach, follow, intervene
115
+ job.status() # WorkloadState
116
+ job.logs() # the flattened, globally-ranked log stream
117
+ job.wait(timeout=600, progress=True) # blocking wait, same narration
118
+ job.result(timeout=3600) # your value, or EyvanJobError with the reason
119
+ job.cancel() # durable cancel
120
+ ```
121
+
122
+ Your callable's *return value* comes back through the artifact store; its
123
+ imports resolve on the cell (image packages + `dependencies` + whatever
124
+ `workspace` shipped). Identical callables deduplicate by content digest;
125
+ a concurrent upload verifies the existing object's digest before using it.
126
+ See [artifact-safety](docs/artifact-safety.md).
127
+
128
+ One more client-side knob worth knowing: the returned job exposes its
129
+ transport (`.base_url`) so tooling built on the SDK can follow the same
130
+ plane the SDK followed, without re-deriving discovery.
131
+
132
+ Failure narration is part of the API contract: a refused capacity attempt
133
+ renders as `blocked | … | the plane is retrying (attempt N)` with the
134
+ provider's diagnostic, and a terminal failure arrives as an exception whose
135
+ message contains the provider's own sentence — not a bare exit code.
136
+
137
+ ## Developing on top of Eyvan
138
+
139
+ Four seams, in order of how often you need them:
140
+
141
+ 1. **A different shape** — no code: a `TpuConfig`/`GpuConfig`/`CpuConfig`
142
+ value. Check the shape is real for you first:
143
+ `eyvan capacity quota --fits v5p-16:2` (quota **and** admission
144
+ permission **and** supply are three different gates).
145
+ 2. **A different fleet** — a YAML config: `eyvan up <config>` from a
146
+ hand-written file (see `examples/fleet.yaml`, `examples/laptop.yaml`) or
147
+ a generated fleet (`eyvan up --region <region> --preemptible`, or
148
+ `eyvan up --quota-based --zone <zone> --preemptible`). Node types, runtime
149
+ env, and autoscaling knobs live in the config, not in your callable.
150
+ 3. **A different cloud** — a provider package with a driver and transport.
151
+ External plugins default to single-machine cells; multi-worker planning
152
+ also needs an in-tree capability entry and a supporting pool factory.
153
+ See [providers](docs/providers.md) for the ABI and conformance contract.
154
+ 4. **A different workflow** — composition: `can_submit_children=True` grants
155
+ your job a submission capability under your identity (fan-out workers,
156
+ coordinator patterns), and checkpointing hooks let long spot jobs survive
157
+ reclamation by design rather than by luck.
158
+
159
+ ### Developing Eyvan itself
160
+
161
+ ```bash
162
+ git clone <this repo> && cd eyvan
163
+ uv sync --extra dev # editable install + dev deps (pytest, pytest-asyncio)
164
+ npm --prefix dashboard ci
165
+ npm --prefix dashboard run build # build the SPA before Python tests
166
+ uv run pytest tests -m fast -q # smoke subset for iteration, not a release gate
167
+ uv run pytest tests -q -rs # full suite; real PostgreSQL requires the test fixture setup
168
+ uv run ruff check eyvan tests # lint (line 121, py3.11)
169
+ uv run eyvan-server --log-level info # run the plane from source
170
+ uv run eyvan-agent --host 127.0.0.1 --port 8090 --allow-unauthenticated # local dev only
171
+ ```
172
+
173
+ Verify the dashboard from a fresh checkout with the commands in
174
+ [Contributing — Dashboard](CONTRIBUTING.md#running-the-tests):
175
+
176
+ ```bash
177
+ npm --prefix dashboard ci
178
+ npm --prefix dashboard test
179
+ npm --prefix dashboard run build
180
+ ```
181
+
182
+ The rules that keep the package honest — enforce them in review, not in
183
+ memory:
184
+
185
+ - **Provider boundary:** nothing that decides (scheduler, planner, durable
186
+ model) may name a provider; `tests/test_provider_boundary.py` enforces it.
187
+ - **Claims need receipts:** a behavior claim cites a recorded run; hardware
188
+ claims go through `eyvan proof` (exit 0 pass, 1 fail, 2 *did not exercise
189
+ the behaviour*, 3 refusal) — see [proofs](docs/proofs.md).
190
+ - **Tests assert public behavior:** state transitions, API outputs, parity —
191
+ not private helper calls or log strings.
192
+ - **Diagnostics travel with failures:** a CLI or provider failure raises with
193
+ its own words attached (`GcsCommandError` carries command + stderr).
194
+ - Architecture decisions are design records under
195
+ [docs/design/](docs/design/0001-scoped-artifact-lifecycle.md), each stating
196
+ its real implementation status.
197
+
198
+ ## The ideas everything else follows from
199
+
200
+ 1. **You state the shape, not the pool.** The scheduler and capacity planner
201
+ decide where that shape can exist.
202
+ 2. **Receipts or it did not happen.** Capacity claims cite recorded runs.
203
+ 3. **Failure narrates itself.** Diagnostics render, never `FAILED`.
204
+ 4. **Nothing that decides names a provider.** Clouds plug in; the core stays
205
+ agnostic.
206
+ 5. **Durable state survives the plane.** A restarted `eyvan-server`
207
+ reconciles the whole world from its durable store.
208
+
209
+ ## Concepts
210
+
211
+ | term | meaning |
212
+ |---------|--------------------------------------------------------------------|
213
+ | plane | the control plane (`eyvan-server`) — scheduler, planner, state |
214
+ | agent | a cell agent (`eyvan-agent`) owning machines on one backend |
215
+ | fleet | a named set of capacity pools you can submit into |
216
+ | pool | one (backend, accelerator, capacity class, zone) combination |
217
+ | cell | one acquired allocation (e.g. one spot queued resource) |
218
+ | workload| your callable + its requested shape, moving through durable states |
219
+
220
+ ## Where it runs
221
+
222
+ Registered capacity backends: `local` (loopback laptop fleets), `gcp-tpu`
223
+ (generated zone fleets driving TPU queued resources, spot or on-demand),
224
+ `gcp-compute`, the `gcp` umbrella, `aws-ec2` (the worked provider example)
225
+ and the `aws` umbrella, `azure-vm` and the `azure` umbrella, `kubernetes`
226
+ (`k8s`) against a real API server, `manual`, `onprem-ssh`, and `gcp-attach`
227
+ (an existing Cloud TPU VM attached with `eyvan gcp connect`; observed, never
228
+ created or deleted).
229
+
230
+ Backend availability is not proof of qualification on your infrastructure.
231
+ GCP TPU is the backend with live hardware runs; the on-premises SSH driver is
232
+ code with no run against a real SSH host yet. See [proofs](docs/proofs.md) for
233
+ evidence requirements and backend-specific limits.
234
+
235
+ ## The docs map
236
+
237
+ New to the project? Start with the [tutorial](docs/tutorial/README.md) —
238
+ seventeen source-grounded parts that walk from "what is Eyvan" through the SDK,
239
+ the control plane, providers, operations, deployment, and an explicit Spot TPU example.
240
+
241
+ | page | what it answers |
242
+ |---|---|
243
+ | [tutorial](docs/tutorial/README.md) | a part-per-subsystem tutorial, grounded in the source |
244
+ | [eyvan-explained](docs/eyvan-explained.md) | the mental model, one workload's full journey |
245
+ | [install](docs/install.md) | laptop path, the fifteen, GCP head, secrets |
246
+ | [operate](docs/operate.md) | the runbook: fleets, workloads, capacity, zone racing |
247
+ | [runtimes](docs/runtimes.md) | the two provisioning models, the defaults profile, custom images |
248
+ | [proofs](docs/proofs.md) | what is proven, with receipts; known rough edges |
249
+ | [providers](docs/providers.md) | writing a capacity provider; the conformance contract |
250
+ | [security](docs/security.md) | trust boundaries, tokens, what jobs can do |
251
+ | [env-surface](docs/env-surface.md) | every `EYVAN_*` variable |
252
+ | [artifact-safety](docs/artifact-safety.md) | tenancy, lifecycle, the digest-addressed store |
253
+ | [troubleshoot](docs/troubleshoot.md) | symptom → cause → action tables |
254
+ | [design records](docs/design/0001-scoped-artifact-lifecycle.md) | the ADRs and their real status |
255
+
256
+ ## What is proven
257
+
258
+ See [proofs](docs/proofs.md) for proof criteria and evidence limits. After a
259
+ restart, use the intended durable state and matching credentials; inspect
260
+ quarantined leases before intervening. See [operate](docs/operate.md) and
261
+ [troubleshoot](docs/troubleshoot.md) for recovery procedures.