gini-toolkit 6.0.1.dev0__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 (488) hide show
  1. gini_toolkit-6.0.1.dev0/PKG-INFO +77 -0
  2. gini_toolkit-6.0.1.dev0/README.md +56 -0
  3. gini_toolkit-6.0.1.dev0/pyproject.toml +60 -0
  4. gini_toolkit-6.0.1.dev0/scripts/build_kb_index.py +61 -0
  5. gini_toolkit-6.0.1.dev0/scripts/gen_cue_shots.py +193 -0
  6. gini_toolkit-6.0.1.dev0/scripts/image_report.py +123 -0
  7. gini_toolkit-6.0.1.dev0/scripts/probe_doctor.py +178 -0
  8. gini_toolkit-6.0.1.dev0/scripts/server_smoke.py +61 -0
  9. gini_toolkit-6.0.1.dev0/scripts/validate_lesson.py +55 -0
  10. gini_toolkit-6.0.1.dev0/setup.cfg +4 -0
  11. gini_toolkit-6.0.1.dev0/src/gini/__init__.py +12 -0
  12. gini_toolkit-6.0.1.dev0/src/gini/__main__.py +107 -0
  13. gini_toolkit-6.0.1.dev0/src/gini/_version.py +24 -0
  14. gini_toolkit-6.0.1.dev0/src/gini/agent/__init__.py +17 -0
  15. gini_toolkit-6.0.1.dev0/src/gini/agent/agent_gamemaster.py +140 -0
  16. gini_toolkit-6.0.1.dev0/src/gini/agent/api.py +291 -0
  17. gini_toolkit-6.0.1.dev0/src/gini/agent/ask.py +123 -0
  18. gini_toolkit-6.0.1.dev0/src/gini/agent/authoring.py +72 -0
  19. gini_toolkit-6.0.1.dev0/src/gini/agent/blackboard.py +114 -0
  20. gini_toolkit-6.0.1.dev0/src/gini/agent/contracts.py +142 -0
  21. gini_toolkit-6.0.1.dev0/src/gini/agent/domains.py +91 -0
  22. gini_toolkit-6.0.1.dev0/src/gini/agent/embed.py +123 -0
  23. gini_toolkit-6.0.1.dev0/src/gini/agent/gamemaster.py +256 -0
  24. gini_toolkit-6.0.1.dev0/src/gini/agent/kb.py +148 -0
  25. gini_toolkit-6.0.1.dev0/src/gini/agent/lesson_resolver.py +261 -0
  26. gini_toolkit-6.0.1.dev0/src/gini/agent/llm/__init__.py +5 -0
  27. gini_toolkit-6.0.1.dev0/src/gini/agent/llm/backend.py +43 -0
  28. gini_toolkit-6.0.1.dev0/src/gini/agent/llm/fake.py +25 -0
  29. gini_toolkit-6.0.1.dev0/src/gini/agent/llm/ollama.py +206 -0
  30. gini_toolkit-6.0.1.dev0/src/gini/agent/loop.py +258 -0
  31. gini_toolkit-6.0.1.dev0/src/gini/agent/mcp_server.py +86 -0
  32. gini_toolkit-6.0.1.dev0/src/gini/agent/meaning.py +225 -0
  33. gini_toolkit-6.0.1.dev0/src/gini/agent/mission.py +210 -0
  34. gini_toolkit-6.0.1.dev0/src/gini/agent/mission_controller.py +208 -0
  35. gini_toolkit-6.0.1.dev0/src/gini/agent/narration.py +116 -0
  36. gini_toolkit-6.0.1.dev0/src/gini/agent/notifier.py +86 -0
  37. gini_toolkit-6.0.1.dev0/src/gini/agent/personas.py +79 -0
  38. gini_toolkit-6.0.1.dev0/src/gini/agent/reasoning.py +172 -0
  39. gini_toolkit-6.0.1.dev0/src/gini/agent/recall.py +248 -0
  40. gini_toolkit-6.0.1.dev0/src/gini/agent/session.py +79 -0
  41. gini_toolkit-6.0.1.dev0/src/gini/agent/teaching_center.py +482 -0
  42. gini_toolkit-6.0.1.dev0/src/gini/agent/tools/__init__.py +3 -0
  43. gini_toolkit-6.0.1.dev0/src/gini/agent/tools/registry.py +193 -0
  44. gini_toolkit-6.0.1.dev0/src/gini/agent/twin/__init__.py +28 -0
  45. gini_toolkit-6.0.1.dev0/src/gini/agent/twin/authoring.py +71 -0
  46. gini_toolkit-6.0.1.dev0/src/gini/agent/twin/contracts.py +54 -0
  47. gini_toolkit-6.0.1.dev0/src/gini/agent/twin/dialectic.py +189 -0
  48. gini_toolkit-6.0.1.dev0/src/gini/agent/twin/harness.py +93 -0
  49. gini_toolkit-6.0.1.dev0/src/gini/agent/twin/justify.py +156 -0
  50. gini_toolkit-6.0.1.dev0/src/gini/agent/twin/learner.py +64 -0
  51. gini_toolkit-6.0.1.dev0/src/gini/agent/twin/mission.py +60 -0
  52. gini_toolkit-6.0.1.dev0/src/gini/agent/twin/os_coach.py +79 -0
  53. gini_toolkit-6.0.1.dev0/src/gini/agent/twin/salience.py +30 -0
  54. gini_toolkit-6.0.1.dev0/src/gini/agent/understand.py +250 -0
  55. gini_toolkit-6.0.1.dev0/src/gini/agent/verifiers.py +106 -0
  56. gini_toolkit-6.0.1.dev0/src/gini/agent/wizard.py +178 -0
  57. gini_toolkit-6.0.1.dev0/src/gini/agent/xv6_pack.py +74 -0
  58. gini_toolkit-6.0.1.dev0/src/gini/app/__init__.py +3 -0
  59. gini_toolkit-6.0.1.dev0/src/gini/app/context.py +368 -0
  60. gini_toolkit-6.0.1.dev0/src/gini/app/paths.py +121 -0
  61. gini_toolkit-6.0.1.dev0/src/gini/data/README.md +21 -0
  62. gini_toolkit-6.0.1.dev0/src/gini/domain/__init__.py +9 -0
  63. gini_toolkit-6.0.1.dev0/src/gini/domain/assembly.py +209 -0
  64. gini_toolkit-6.0.1.dev0/src/gini/domain/authoring.py +353 -0
  65. gini_toolkit-6.0.1.dev0/src/gini/domain/blueprints.py +5 -0
  66. gini_toolkit-6.0.1.dev0/src/gini/domain/capabilities.py +177 -0
  67. gini_toolkit-6.0.1.dev0/src/gini/domain/catalog.py +85 -0
  68. gini_toolkit-6.0.1.dev0/src/gini/domain/certify.py +201 -0
  69. gini_toolkit-6.0.1.dev0/src/gini/domain/compose.py +413 -0
  70. gini_toolkit-6.0.1.dev0/src/gini/domain/composition.py +88 -0
  71. gini_toolkit-6.0.1.dev0/src/gini/domain/concepts.py +383 -0
  72. gini_toolkit-6.0.1.dev0/src/gini/domain/connection_rules.py +269 -0
  73. gini_toolkit-6.0.1.dev0/src/gini/domain/constraints.py +153 -0
  74. gini_toolkit-6.0.1.dev0/src/gini/domain/content.py +59 -0
  75. gini_toolkit-6.0.1.dev0/src/gini/domain/cpu_journey.py +89 -0
  76. gini_toolkit-6.0.1.dev0/src/gini/domain/devices.py +747 -0
  77. gini_toolkit-6.0.1.dev0/src/gini/domain/diagnose.py +201 -0
  78. gini_toolkit-6.0.1.dev0/src/gini/domain/element_guide.py +327 -0
  79. gini_toolkit-6.0.1.dev0/src/gini/domain/explain.py +90 -0
  80. gini_toolkit-6.0.1.dev0/src/gini/domain/fingerprint.py +201 -0
  81. gini_toolkit-6.0.1.dev0/src/gini/domain/firewall.py +34 -0
  82. gini_toolkit-6.0.1.dev0/src/gini/domain/flowlog.py +61 -0
  83. gini_toolkit-6.0.1.dev0/src/gini/domain/flowtable.py +179 -0
  84. gini_toolkit-6.0.1.dev0/src/gini/domain/fragment_yaml.py +230 -0
  85. gini_toolkit-6.0.1.dev0/src/gini/domain/fragments.py +169 -0
  86. gini_toolkit-6.0.1.dev0/src/gini/domain/games/__init__.py +2 -0
  87. gini_toolkit-6.0.1.dev0/src/gini/domain/games/paging_games.py +119 -0
  88. gini_toolkit-6.0.1.dev0/src/gini/domain/games/policy_game.py +86 -0
  89. gini_toolkit-6.0.1.dev0/src/gini/domain/games/process_game.py +48 -0
  90. gini_toolkit-6.0.1.dev0/src/gini/domain/games/thrash_game.py +75 -0
  91. gini_toolkit-6.0.1.dev0/src/gini/domain/games/translate_game.py +60 -0
  92. gini_toolkit-6.0.1.dev0/src/gini/domain/games/trap_game.py +86 -0
  93. gini_toolkit-6.0.1.dev0/src/gini/domain/grader.py +155 -0
  94. gini_toolkit-6.0.1.dev0/src/gini/domain/grouping.py +67 -0
  95. gini_toolkit-6.0.1.dev0/src/gini/domain/legality.py +103 -0
  96. gini_toolkit-6.0.1.dev0/src/gini/domain/lesson.py +241 -0
  97. gini_toolkit-6.0.1.dev0/src/gini/domain/lexicon.py +150 -0
  98. gini_toolkit-6.0.1.dev0/src/gini/domain/machine_state.py +410 -0
  99. gini_toolkit-6.0.1.dev0/src/gini/domain/missions/networking/basic-lan.yaml +32 -0
  100. gini_toolkit-6.0.1.dev0/src/gini/domain/missions/networking/cache-in-front.yaml +23 -0
  101. gini_toolkit-6.0.1.dev0/src/gini/domain/missions/networking/decouple-with-queue.yaml +31 -0
  102. gini_toolkit-6.0.1.dev0/src/gini/domain/missions/networking/drive-load.yaml +20 -0
  103. gini_toolkit-6.0.1.dev0/src/gini/domain/missions/networking/fix-the-address.yaml +75 -0
  104. gini_toolkit-6.0.1.dev0/src/gini/domain/missions/networking/fix-the-lan.yaml +43 -0
  105. gini_toolkit-6.0.1.dev0/src/gini/domain/missions/networking/inspect-flows.yaml +16 -0
  106. gini_toolkit-6.0.1.dev0/src/gini/domain/missions/networking/k8s-autoscale.yaml +27 -0
  107. gini_toolkit-6.0.1.dev0/src/gini/domain/missions/networking/least-privilege.yaml +21 -0
  108. gini_toolkit-6.0.1.dev0/src/gini/domain/missions/networking/load-balanced-web.yaml +29 -0
  109. gini_toolkit-6.0.1.dev0/src/gini/domain/missions/networking/observe-it.yaml +24 -0
  110. gini_toolkit-6.0.1.dev0/src/gini/domain/missions/networking/put-in-vpc.yaml +30 -0
  111. gini_toolkit-6.0.1.dev0/src/gini/domain/missions/networking/reachability-boundary.yaml +56 -0
  112. gini_toolkit-6.0.1.dev0/src/gini/domain/missions/networking/sdn-reactive.yaml +35 -0
  113. gini_toolkit-6.0.1.dev0/src/gini/domain/missions/networking/send-request.yaml +19 -0
  114. gini_toolkit-6.0.1.dev0/src/gini/domain/missions/networking/serverless-api.yaml +25 -0
  115. gini_toolkit-6.0.1.dev0/src/gini/domain/missions/networking/service-chain.yaml +33 -0
  116. gini_toolkit-6.0.1.dev0/src/gini/domain/missions/os/lottery-fix.yaml +19 -0
  117. gini_toolkit-6.0.1.dev0/src/gini/domain/missions/os/priority-fix.yaml +24 -0
  118. gini_toolkit-6.0.1.dev0/src/gini/domain/missions.py +111 -0
  119. gini_toolkit-6.0.1.dev0/src/gini/domain/modulechain.py +36 -0
  120. gini_toolkit-6.0.1.dev0/src/gini/domain/objectives.py +488 -0
  121. gini_toolkit-6.0.1.dev0/src/gini/domain/os_zoo.py +79 -0
  122. gini_toolkit-6.0.1.dev0/src/gini/domain/paging_sim.py +141 -0
  123. gini_toolkit-6.0.1.dev0/src/gini/domain/pricing.py +199 -0
  124. gini_toolkit-6.0.1.dev0/src/gini/domain/probes.py +226 -0
  125. gini_toolkit-6.0.1.dev0/src/gini/domain/profile.py +142 -0
  126. gini_toolkit-6.0.1.dev0/src/gini/domain/recipes.py +738 -0
  127. gini_toolkit-6.0.1.dev0/src/gini/domain/riders.py +309 -0
  128. gini_toolkit-6.0.1.dev0/src/gini/domain/router_modules.py +224 -0
  129. gini_toolkit-6.0.1.dev0/src/gini/domain/routetable.py +67 -0
  130. gini_toolkit-6.0.1.dev0/src/gini/domain/scoring.py +76 -0
  131. gini_toolkit-6.0.1.dev0/src/gini/domain/staging.py +122 -0
  132. gini_toolkit-6.0.1.dev0/src/gini/domain/syscall_builder.py +144 -0
  133. gini_toolkit-6.0.1.dev0/src/gini/domain/topic_cloud.py +62 -0
  134. gini_toolkit-6.0.1.dev0/src/gini/domain/topology.py +213 -0
  135. gini_toolkit-6.0.1.dev0/src/gini/domain/vocabulary.py +51 -0
  136. gini_toolkit-6.0.1.dev0/src/gini/domain/xv6.py +808 -0
  137. gini_toolkit-6.0.1.dev0/src/gini/domain/xv6_fs.py +250 -0
  138. gini_toolkit-6.0.1.dev0/src/gini/domain/xv6_runner.py +113 -0
  139. gini_toolkit-6.0.1.dev0/src/gini/domain/xv6_vm.py +385 -0
  140. gini_toolkit-6.0.1.dev0/src/gini/gloader.py +17 -0
  141. gini_toolkit-6.0.1.dev0/src/gini/runtime/__init__.py +18 -0
  142. gini_toolkit-6.0.1.dev0/src/gini/runtime/cloudfabric_agent.py +370 -0
  143. gini_toolkit-6.0.1.dev0/src/gini/runtime/console.py +68 -0
  144. gini_toolkit-6.0.1.dev0/src/gini/runtime/control.py +70 -0
  145. gini_toolkit-6.0.1.dev0/src/gini/runtime/frame.py +138 -0
  146. gini_toolkit-6.0.1.dev0/src/gini/runtime/gbridge.py +638 -0
  147. gini_toolkit-6.0.1.dev0/src/gini/runtime/grouter.py +223 -0
  148. gini_toolkit-6.0.1.dev0/src/gini/runtime/hostsim.py +90 -0
  149. gini_toolkit-6.0.1.dev0/src/gini/runtime/shuttle.py +348 -0
  150. gini_toolkit-6.0.1.dev0/src/gini/runtime/switch.py +109 -0
  151. gini_toolkit-6.0.1.dev0/src/gini/runtime/transport.py +77 -0
  152. gini_toolkit-6.0.1.dev0/src/gini/runtime/xv6_bridge.py +312 -0
  153. gini_toolkit-6.0.1.dev0/src/gini/server/__init__.py +22 -0
  154. gini_toolkit-6.0.1.dev0/src/gini/server/__main__.py +74 -0
  155. gini_toolkit-6.0.1.dev0/src/gini/server/app.py +140 -0
  156. gini_toolkit-6.0.1.dev0/src/gini/server/auth.py +82 -0
  157. gini_toolkit-6.0.1.dev0/src/gini/server/policy.py +57 -0
  158. gini_toolkit-6.0.1.dev0/src/gini/server/session.py +23 -0
  159. gini_toolkit-6.0.1.dev0/src/gini/services/__init__.py +15 -0
  160. gini_toolkit-6.0.1.dev0/src/gini/services/boardflash.py +248 -0
  161. gini_toolkit-6.0.1.dev0/src/gini/services/boardsetup.py +374 -0
  162. gini_toolkit-6.0.1.dev0/src/gini/services/cloud_catalog.py +143 -0
  163. gini_toolkit-6.0.1.dev0/src/gini/services/compiler.py +1858 -0
  164. gini_toolkit-6.0.1.dev0/src/gini/services/discovery.py +324 -0
  165. gini_toolkit-6.0.1.dev0/src/gini/services/gloader.py +183 -0
  166. gini_toolkit-6.0.1.dev0/src/gini/services/orchestrator.py +1460 -0
  167. gini_toolkit-6.0.1.dev0/src/gini/services/persistence.py +28 -0
  168. gini_toolkit-6.0.1.dev0/src/gini/services/probe_runner.py +149 -0
  169. gini_toolkit-6.0.1.dev0/src/gini/services/project.py +217 -0
  170. gini_toolkit-6.0.1.dev0/src/gini/services/remote.py +93 -0
  171. gini_toolkit-6.0.1.dev0/src/gini/services/rider_runner.py +96 -0
  172. gini_toolkit-6.0.1.dev0/src/gini/services/rider_session.py +171 -0
  173. gini_toolkit-6.0.1.dev0/src/gini/services/shadow_store.py +52 -0
  174. gini_toolkit-6.0.1.dev0/src/gini/services/terminal.py +45 -0
  175. gini_toolkit-6.0.1.dev0/src/gini/setup/__init__.py +17 -0
  176. gini_toolkit-6.0.1.dev0/src/gini/setup/cli.py +109 -0
  177. gini_toolkit-6.0.1.dev0/src/gini/setup/images.py +33 -0
  178. gini_toolkit-6.0.1.dev0/src/gini/setup/marker.py +43 -0
  179. gini_toolkit-6.0.1.dev0/src/gini/setup/runtime.py +69 -0
  180. gini_toolkit-6.0.1.dev0/src/gini/ui/__init__.py +3 -0
  181. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/app_icon.icns +0 -0
  182. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/app_icon.ico +0 -0
  183. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/app_icon.png +0 -0
  184. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/app_icon_1024.png +0 -0
  185. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/_w.txt +1 -0
  186. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/ai.png +0 -0
  187. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/canvas.png +0 -0
  188. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/cloud.png +0 -0
  189. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/cost.png +0 -0
  190. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/dark/ai.png +0 -0
  191. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/dark/canvas.png +0 -0
  192. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/dark/cloud.png +0 -0
  193. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/dark/cost.png +0 -0
  194. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/dark/metrics.png +0 -0
  195. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/dark/router.png +0 -0
  196. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/dark/run.png +0 -0
  197. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/dark/serverless.png +0 -0
  198. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/dark/settings.png +0 -0
  199. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/dark/welcome.png +0 -0
  200. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/dark/wizard.png +0 -0
  201. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/ginibrand/ai.png +0 -0
  202. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/ginibrand/canvas.png +0 -0
  203. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/ginibrand/cloud.png +0 -0
  204. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/ginibrand/cost.png +0 -0
  205. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/ginibrand/metrics.png +0 -0
  206. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/ginibrand/router.png +0 -0
  207. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/ginibrand/run.png +0 -0
  208. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/ginibrand/serverless.png +0 -0
  209. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/ginibrand/settings.png +0 -0
  210. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/ginibrand/welcome.png +0 -0
  211. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/ginibrand/wizard.png +0 -0
  212. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/highcontrast/ai.png +0 -0
  213. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/highcontrast/canvas.png +0 -0
  214. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/highcontrast/cloud.png +0 -0
  215. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/highcontrast/cost.png +0 -0
  216. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/highcontrast/metrics.png +0 -0
  217. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/highcontrast/router.png +0 -0
  218. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/highcontrast/run.png +0 -0
  219. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/highcontrast/serverless.png +0 -0
  220. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/highcontrast/settings.png +0 -0
  221. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/highcontrast/welcome.png +0 -0
  222. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/highcontrast/wizard.png +0 -0
  223. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/light/ai.png +0 -0
  224. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/light/canvas.png +0 -0
  225. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/light/cloud.png +0 -0
  226. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/light/cost.png +0 -0
  227. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/light/metrics.png +0 -0
  228. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/light/router.png +0 -0
  229. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/light/run.png +0 -0
  230. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/light/serverless.png +0 -0
  231. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/light/settings.png +0 -0
  232. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/light/welcome.png +0 -0
  233. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/light/wizard.png +0 -0
  234. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/metrics.png +0 -0
  235. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/router.png +0 -0
  236. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/run.png +0 -0
  237. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/serverless.png +0 -0
  238. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/settings.png +0 -0
  239. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/welcome.png +0 -0
  240. gini_toolkit-6.0.1.dev0/src/gini/ui/assets/cue/wizard.png +0 -0
  241. gini_toolkit-6.0.1.dev0/src/gini/ui/assistant.py +2111 -0
  242. gini_toolkit-6.0.1.dev0/src/gini/ui/author_dialog.py +184 -0
  243. gini_toolkit-6.0.1.dev0/src/gini/ui/board_dialog.py +247 -0
  244. gini_toolkit-6.0.1.dev0/src/gini/ui/branding.py +21 -0
  245. gini_toolkit-6.0.1.dev0/src/gini/ui/canvas.py +2007 -0
  246. gini_toolkit-6.0.1.dev0/src/gini/ui/chat_panel.py +7 -0
  247. gini_toolkit-6.0.1.dev0/src/gini/ui/cpu_journey.py +212 -0
  248. gini_toolkit-6.0.1.dev0/src/gini/ui/cpu_lab.py +306 -0
  249. gini_toolkit-6.0.1.dev0/src/gini/ui/cue_cards.py +214 -0
  250. gini_toolkit-6.0.1.dev0/src/gini/ui/dashboard.py +222 -0
  251. gini_toolkit-6.0.1.dev0/src/gini/ui/diagnose_game.py +336 -0
  252. gini_toolkit-6.0.1.dev0/src/gini/ui/fingerprint_lab.py +219 -0
  253. gini_toolkit-6.0.1.dev0/src/gini/ui/flash_dialog.py +244 -0
  254. gini_toolkit-6.0.1.dev0/src/gini/ui/flow_layout.py +63 -0
  255. gini_toolkit-6.0.1.dev0/src/gini/ui/fragment_manager.py +1415 -0
  256. gini_toolkit-6.0.1.dev0/src/gini/ui/game_catalog.py +184 -0
  257. gini_toolkit-6.0.1.dev0/src/gini/ui/game_renderers.py +340 -0
  258. gini_toolkit-6.0.1.dev0/src/gini/ui/games_lab.py +90 -0
  259. gini_toolkit-6.0.1.dev0/src/gini/ui/inspector.py +1055 -0
  260. gini_toolkit-6.0.1.dev0/src/gini/ui/live_metrics.py +130 -0
  261. gini_toolkit-6.0.1.dev0/src/gini/ui/machine_lab.py +1412 -0
  262. gini_toolkit-6.0.1.dev0/src/gini/ui/main_window.py +3153 -0
  263. gini_toolkit-6.0.1.dev0/src/gini/ui/memory_lab.py +371 -0
  264. gini_toolkit-6.0.1.dev0/src/gini/ui/mission_panel.py +302 -0
  265. gini_toolkit-6.0.1.dev0/src/gini/ui/mode_indicator.py +227 -0
  266. gini_toolkit-6.0.1.dev0/src/gini/ui/palette.py +112 -0
  267. gini_toolkit-6.0.1.dev0/src/gini/ui/peripherals.py +218 -0
  268. gini_toolkit-6.0.1.dev0/src/gini/ui/process_tree.py +130 -0
  269. gini_toolkit-6.0.1.dev0/src/gini/ui/reset_dialog.py +179 -0
  270. gini_toolkit-6.0.1.dev0/src/gini/ui/router_lab.py +776 -0
  271. gini_toolkit-6.0.1.dev0/src/gini/ui/run_button.py +183 -0
  272. gini_toolkit-6.0.1.dev0/src/gini/ui/settings_dialog.py +234 -0
  273. gini_toolkit-6.0.1.dev0/src/gini/ui/signin_dialog.py +111 -0
  274. gini_toolkit-6.0.1.dev0/src/gini/ui/storage_lab.py +219 -0
  275. gini_toolkit-6.0.1.dev0/src/gini/ui/syscall_builder.py +235 -0
  276. gini_toolkit-6.0.1.dev0/src/gini/ui/syscall_lab.py +152 -0
  277. gini_toolkit-6.0.1.dev0/src/gini/ui/theme/__init__.py +5 -0
  278. gini_toolkit-6.0.1.dev0/src/gini/ui/theme/icons.py +145 -0
  279. gini_toolkit-6.0.1.dev0/src/gini/ui/theme/manager.py +291 -0
  280. gini_toolkit-6.0.1.dev0/src/gini/ui/theme/tokens.py +194 -0
  281. gini_toolkit-6.0.1.dev0/src/gini/ui/trap_lab.py +270 -0
  282. gini_toolkit-6.0.1.dev0/src/gini/ui/worker_host.py +102 -0
  283. gini_toolkit-6.0.1.dev0/src/gini/ui/zoo_lab.py +112 -0
  284. gini_toolkit-6.0.1.dev0/src/gini_toolkit.egg-info/PKG-INFO +77 -0
  285. gini_toolkit-6.0.1.dev0/src/gini_toolkit.egg-info/SOURCES.txt +486 -0
  286. gini_toolkit-6.0.1.dev0/src/gini_toolkit.egg-info/dependency_links.txt +1 -0
  287. gini_toolkit-6.0.1.dev0/src/gini_toolkit.egg-info/entry_points.txt +3 -0
  288. gini_toolkit-6.0.1.dev0/src/gini_toolkit.egg-info/requires.txt +15 -0
  289. gini_toolkit-6.0.1.dev0/src/gini_toolkit.egg-info/scm_file_list.json +481 -0
  290. gini_toolkit-6.0.1.dev0/src/gini_toolkit.egg-info/scm_version.json +8 -0
  291. gini_toolkit-6.0.1.dev0/src/gini_toolkit.egg-info/top_level.txt +1 -0
  292. gini_toolkit-6.0.1.dev0/tests/conftest.py +39 -0
  293. gini_toolkit-6.0.1.dev0/tests/test_addressing.py +42 -0
  294. gini_toolkit-6.0.1.dev0/tests/test_agent.py +46 -0
  295. gini_toolkit-6.0.1.dev0/tests/test_agent_integration.py +58 -0
  296. gini_toolkit-6.0.1.dev0/tests/test_agent_loop.py +87 -0
  297. gini_toolkit-6.0.1.dev0/tests/test_ai_context.py +61 -0
  298. gini_toolkit-6.0.1.dev0/tests/test_approval_build5.py +145 -0
  299. gini_toolkit-6.0.1.dev0/tests/test_ask.py +70 -0
  300. gini_toolkit-6.0.1.dev0/tests/test_ask_gini.py +88 -0
  301. gini_toolkit-6.0.1.dev0/tests/test_ask_pipeline.py +47 -0
  302. gini_toolkit-6.0.1.dev0/tests/test_assembly.py +61 -0
  303. gini_toolkit-6.0.1.dev0/tests/test_assistant_explain_routing.py +55 -0
  304. gini_toolkit-6.0.1.dev0/tests/test_assistant_menu.py +112 -0
  305. gini_toolkit-6.0.1.dev0/tests/test_auth.py +233 -0
  306. gini_toolkit-6.0.1.dev0/tests/test_auth_server.py +129 -0
  307. gini_toolkit-6.0.1.dev0/tests/test_authoring.py +53 -0
  308. gini_toolkit-6.0.1.dev0/tests/test_authoring_build2.py +122 -0
  309. gini_toolkit-6.0.1.dev0/tests/test_autobuild_setting.py +113 -0
  310. gini_toolkit-6.0.1.dev0/tests/test_blackboard.py +83 -0
  311. gini_toolkit-6.0.1.dev0/tests/test_blueprints.py +2 -0
  312. gini_toolkit-6.0.1.dev0/tests/test_board_carry.py +46 -0
  313. gini_toolkit-6.0.1.dev0/tests/test_board_dialog.py +109 -0
  314. gini_toolkit-6.0.1.dev0/tests/test_board_liveness.py +124 -0
  315. gini_toolkit-6.0.1.dev0/tests/test_boardflash.py +170 -0
  316. gini_toolkit-6.0.1.dev0/tests/test_boardsetup.py +309 -0
  317. gini_toolkit-6.0.1.dev0/tests/test_canvas_connect.py +98 -0
  318. gini_toolkit-6.0.1.dev0/tests/test_catalog.py +43 -0
  319. gini_toolkit-6.0.1.dev0/tests/test_certify.py +149 -0
  320. gini_toolkit-6.0.1.dev0/tests/test_chat_panel.py +3 -0
  321. gini_toolkit-6.0.1.dev0/tests/test_cloud.py +250 -0
  322. gini_toolkit-6.0.1.dev0/tests/test_cloud_fabric.py +110 -0
  323. gini_toolkit-6.0.1.dev0/tests/test_compose.py +269 -0
  324. gini_toolkit-6.0.1.dev0/tests/test_composer.py +104 -0
  325. gini_toolkit-6.0.1.dev0/tests/test_composition.py +61 -0
  326. gini_toolkit-6.0.1.dev0/tests/test_connect_gesture.py +320 -0
  327. gini_toolkit-6.0.1.dev0/tests/test_connection_rules.py +85 -0
  328. gini_toolkit-6.0.1.dev0/tests/test_console_routing.py +97 -0
  329. gini_toolkit-6.0.1.dev0/tests/test_constraints.py +39 -0
  330. gini_toolkit-6.0.1.dev0/tests/test_content_and_forks.py +127 -0
  331. gini_toolkit-6.0.1.dev0/tests/test_contract.py +55 -0
  332. gini_toolkit-6.0.1.dev0/tests/test_control.py +60 -0
  333. gini_toolkit-6.0.1.dev0/tests/test_cpu_journey.py +29 -0
  334. gini_toolkit-6.0.1.dev0/tests/test_cpu_lab.py +147 -0
  335. gini_toolkit-6.0.1.dev0/tests/test_cue_cards.py +92 -0
  336. gini_toolkit-6.0.1.dev0/tests/test_delete.py +58 -0
  337. gini_toolkit-6.0.1.dev0/tests/test_desktop.py +24 -0
  338. gini_toolkit-6.0.1.dev0/tests/test_diagnose.py +104 -0
  339. gini_toolkit-6.0.1.dev0/tests/test_diagnose_game.py +83 -0
  340. gini_toolkit-6.0.1.dev0/tests/test_discovery.py +185 -0
  341. gini_toolkit-6.0.1.dev0/tests/test_domain.py +48 -0
  342. gini_toolkit-6.0.1.dev0/tests/test_domains.py +45 -0
  343. gini_toolkit-6.0.1.dev0/tests/test_embed.py +76 -0
  344. gini_toolkit-6.0.1.dev0/tests/test_experiments.py +182 -0
  345. gini_toolkit-6.0.1.dev0/tests/test_explain.py +38 -0
  346. gini_toolkit-6.0.1.dev0/tests/test_faas_authoring.py +128 -0
  347. gini_toolkit-6.0.1.dev0/tests/test_faces.py +79 -0
  348. gini_toolkit-6.0.1.dev0/tests/test_fingerprint.py +67 -0
  349. gini_toolkit-6.0.1.dev0/tests/test_fingerprint_lab.py +84 -0
  350. gini_toolkit-6.0.1.dev0/tests/test_flash_dialog.py +163 -0
  351. gini_toolkit-6.0.1.dev0/tests/test_flowlog.py +46 -0
  352. gini_toolkit-6.0.1.dev0/tests/test_flowtable.py +92 -0
  353. gini_toolkit-6.0.1.dev0/tests/test_fragment_ports.py +151 -0
  354. gini_toolkit-6.0.1.dev0/tests/test_fragment_terminals.py +339 -0
  355. gini_toolkit-6.0.1.dev0/tests/test_fragment_yaml.py +45 -0
  356. gini_toolkit-6.0.1.dev0/tests/test_gamemaster.py +104 -0
  357. gini_toolkit-6.0.1.dev0/tests/test_gini32.py +686 -0
  358. gini_toolkit-6.0.1.dev0/tests/test_gloader.py +63 -0
  359. gini_toolkit-6.0.1.dev0/tests/test_gradebook_official.py +49 -0
  360. gini_toolkit-6.0.1.dev0/tests/test_grader.py +80 -0
  361. gini_toolkit-6.0.1.dev0/tests/test_grounding_stance.py +37 -0
  362. gini_toolkit-6.0.1.dev0/tests/test_grouping.py +42 -0
  363. gini_toolkit-6.0.1.dev0/tests/test_guided_missions.py +127 -0
  364. gini_toolkit-6.0.1.dev0/tests/test_hub.py +89 -0
  365. gini_toolkit-6.0.1.dev0/tests/test_integration.py +73 -0
  366. gini_toolkit-6.0.1.dev0/tests/test_k8s.py +270 -0
  367. gini_toolkit-6.0.1.dev0/tests/test_kata.py +59 -0
  368. gini_toolkit-6.0.1.dev0/tests/test_kb.py +54 -0
  369. gini_toolkit-6.0.1.dev0/tests/test_kb_index_sync.py +18 -0
  370. gini_toolkit-6.0.1.dev0/tests/test_knowledge.py +104 -0
  371. gini_toolkit-6.0.1.dev0/tests/test_legality.py +59 -0
  372. gini_toolkit-6.0.1.dev0/tests/test_lesson.py +64 -0
  373. gini_toolkit-6.0.1.dev0/tests/test_lesson_resolver.py +44 -0
  374. gini_toolkit-6.0.1.dev0/tests/test_lexicon.py +41 -0
  375. gini_toolkit-6.0.1.dev0/tests/test_live_metrics.py +131 -0
  376. gini_toolkit-6.0.1.dev0/tests/test_loadgen_proxy.py +114 -0
  377. gini_toolkit-6.0.1.dev0/tests/test_loop_visible.py +56 -0
  378. gini_toolkit-6.0.1.dev0/tests/test_m2_behavioral.py +64 -0
  379. gini_toolkit-6.0.1.dev0/tests/test_m7_polish.py +46 -0
  380. gini_toolkit-6.0.1.dev0/tests/test_machine_lab.py +479 -0
  381. gini_toolkit-6.0.1.dev0/tests/test_machine_state.py +242 -0
  382. gini_toolkit-6.0.1.dev0/tests/test_machine_toolkit.py +120 -0
  383. gini_toolkit-6.0.1.dev0/tests/test_meaning.py +87 -0
  384. gini_toolkit-6.0.1.dev0/tests/test_memory_lab.py +79 -0
  385. gini_toolkit-6.0.1.dev0/tests/test_mission.py +82 -0
  386. gini_toolkit-6.0.1.dev0/tests/test_mission_controller.py +93 -0
  387. gini_toolkit-6.0.1.dev0/tests/test_mission_panel.py +125 -0
  388. gini_toolkit-6.0.1.dev0/tests/test_missions.py +32 -0
  389. gini_toolkit-6.0.1.dev0/tests/test_missions_entry.py +117 -0
  390. gini_toolkit-6.0.1.dev0/tests/test_missions_mode.py +73 -0
  391. gini_toolkit-6.0.1.dev0/tests/test_name_independence.py +92 -0
  392. gini_toolkit-6.0.1.dev0/tests/test_naming.py +37 -0
  393. gini_toolkit-6.0.1.dev0/tests/test_narration.py +80 -0
  394. gini_toolkit-6.0.1.dev0/tests/test_nfv.py +30 -0
  395. gini_toolkit-6.0.1.dev0/tests/test_no_vacuous_objectives.py +42 -0
  396. gini_toolkit-6.0.1.dev0/tests/test_notifier.py +69 -0
  397. gini_toolkit-6.0.1.dev0/tests/test_objectives.py +113 -0
  398. gini_toolkit-6.0.1.dev0/tests/test_ollama_thinking.py +83 -0
  399. gini_toolkit-6.0.1.dev0/tests/test_orchestrator_switch.py +82 -0
  400. gini_toolkit-6.0.1.dev0/tests/test_os_zoo.py +33 -0
  401. gini_toolkit-6.0.1.dev0/tests/test_oszoo_compile.py +95 -0
  402. gini_toolkit-6.0.1.dev0/tests/test_ota_build4.py +132 -0
  403. gini_toolkit-6.0.1.dev0/tests/test_paging.py +57 -0
  404. gini_toolkit-6.0.1.dev0/tests/test_paging_games.py +74 -0
  405. gini_toolkit-6.0.1.dev0/tests/test_palette_taxonomy.py +61 -0
  406. gini_toolkit-6.0.1.dev0/tests/test_peripherals_wiring.py +35 -0
  407. gini_toolkit-6.0.1.dev0/tests/test_persistence.py +45 -0
  408. gini_toolkit-6.0.1.dev0/tests/test_photo.py +68 -0
  409. gini_toolkit-6.0.1.dev0/tests/test_policy_game.py +33 -0
  410. gini_toolkit-6.0.1.dev0/tests/test_present.py +48 -0
  411. gini_toolkit-6.0.1.dev0/tests/test_pricing.py +112 -0
  412. gini_toolkit-6.0.1.dev0/tests/test_probes.py +121 -0
  413. gini_toolkit-6.0.1.dev0/tests/test_process_tree.py +76 -0
  414. gini_toolkit-6.0.1.dev0/tests/test_profai.py +212 -0
  415. gini_toolkit-6.0.1.dev0/tests/test_profile.py +81 -0
  416. gini_toolkit-6.0.1.dev0/tests/test_projects.py +241 -0
  417. gini_toolkit-6.0.1.dev0/tests/test_rank_spot.py +56 -0
  418. gini_toolkit-6.0.1.dev0/tests/test_reasoning.py +73 -0
  419. gini_toolkit-6.0.1.dev0/tests/test_recall.py +81 -0
  420. gini_toolkit-6.0.1.dev0/tests/test_recipes.py +102 -0
  421. gini_toolkit-6.0.1.dev0/tests/test_recorder.py +164 -0
  422. gini_toolkit-6.0.1.dev0/tests/test_remote.py +72 -0
  423. gini_toolkit-6.0.1.dev0/tests/test_remote_gui.py +71 -0
  424. gini_toolkit-6.0.1.dev0/tests/test_rider_session.py +111 -0
  425. gini_toolkit-6.0.1.dev0/tests/test_riders.py +251 -0
  426. gini_toolkit-6.0.1.dev0/tests/test_router_lab.py +50 -0
  427. gini_toolkit-6.0.1.dev0/tests/test_routetable.py +50 -0
  428. gini_toolkit-6.0.1.dev0/tests/test_scaffold.py +120 -0
  429. gini_toolkit-6.0.1.dev0/tests/test_scoring.py +37 -0
  430. gini_toolkit-6.0.1.dev0/tests/test_sdn.py +93 -0
  431. gini_toolkit-6.0.1.dev0/tests/test_sdn_dashboard.py +101 -0
  432. gini_toolkit-6.0.1.dev0/tests/test_sdn_orchestrator.py +61 -0
  433. gini_toolkit-6.0.1.dev0/tests/test_secgroup.py +76 -0
  434. gini_toolkit-6.0.1.dev0/tests/test_server.py +159 -0
  435. gini_toolkit-6.0.1.dev0/tests/test_serverless.py +138 -0
  436. gini_toolkit-6.0.1.dev0/tests/test_session.py +51 -0
  437. gini_toolkit-6.0.1.dev0/tests/test_settings.py +131 -0
  438. gini_toolkit-6.0.1.dev0/tests/test_setup.py +68 -0
  439. gini_toolkit-6.0.1.dev0/tests/test_sfc_chain.py +53 -0
  440. gini_toolkit-6.0.1.dev0/tests/test_sfc_ui.py +48 -0
  441. gini_toolkit-6.0.1.dev0/tests/test_shadow_store.py +29 -0
  442. gini_toolkit-6.0.1.dev0/tests/test_sizing.py +135 -0
  443. gini_toolkit-6.0.1.dev0/tests/test_slots.py +72 -0
  444. gini_toolkit-6.0.1.dev0/tests/test_social.py +146 -0
  445. gini_toolkit-6.0.1.dev0/tests/test_social_server.py +172 -0
  446. gini_toolkit-6.0.1.dev0/tests/test_sources_sinks.py +107 -0
  447. gini_toolkit-6.0.1.dev0/tests/test_sources_sinks_ui.py +178 -0
  448. gini_toolkit-6.0.1.dev0/tests/test_staging.py +174 -0
  449. gini_toolkit-6.0.1.dev0/tests/test_stars.py +43 -0
  450. gini_toolkit-6.0.1.dev0/tests/test_storage_lab.py +38 -0
  451. gini_toolkit-6.0.1.dev0/tests/test_store_features.py +172 -0
  452. gini_toolkit-6.0.1.dev0/tests/test_syscall_builder.py +73 -0
  453. gini_toolkit-6.0.1.dev0/tests/test_syscall_builder_ui.py +67 -0
  454. gini_toolkit-6.0.1.dev0/tests/test_tap_offload.py +188 -0
  455. gini_toolkit-6.0.1.dev0/tests/test_tc_delete.py +74 -0
  456. gini_toolkit-6.0.1.dev0/tests/test_tc_new_format.py +36 -0
  457. gini_toolkit-6.0.1.dev0/tests/test_teaching_center.py +126 -0
  458. gini_toolkit-6.0.1.dev0/tests/test_themes_runbutton.py +123 -0
  459. gini_toolkit-6.0.1.dev0/tests/test_topic_cloud.py +45 -0
  460. gini_toolkit-6.0.1.dev0/tests/test_topic_cloud_ui.py +55 -0
  461. gini_toolkit-6.0.1.dev0/tests/test_trap_fault_game.py +44 -0
  462. gini_toolkit-6.0.1.dev0/tests/test_trap_lab.py +166 -0
  463. gini_toolkit-6.0.1.dev0/tests/test_tutor.py +240 -0
  464. gini_toolkit-6.0.1.dev0/tests/test_twin.py +340 -0
  465. gini_toolkit-6.0.1.dev0/tests/test_twin_surfaces.py +169 -0
  466. gini_toolkit-6.0.1.dev0/tests/test_ui_tweaks.py +91 -0
  467. gini_toolkit-6.0.1.dev0/tests/test_understand.py +73 -0
  468. gini_toolkit-6.0.1.dev0/tests/test_unified_chat.py +135 -0
  469. gini_toolkit-6.0.1.dev0/tests/test_upload_build3.py +143 -0
  470. gini_toolkit-6.0.1.dev0/tests/test_user_pill.py +252 -0
  471. gini_toolkit-6.0.1.dev0/tests/test_validate.py +59 -0
  472. gini_toolkit-6.0.1.dev0/tests/test_vnf.py +56 -0
  473. gini_toolkit-6.0.1.dev0/tests/test_vpc.py +126 -0
  474. gini_toolkit-6.0.1.dev0/tests/test_vpc_canvas.py +56 -0
  475. gini_toolkit-6.0.1.dev0/tests/test_wizard.py +136 -0
  476. gini_toolkit-6.0.1.dev0/tests/test_wizard_engine.py +99 -0
  477. gini_toolkit-6.0.1.dev0/tests/test_xray.py +112 -0
  478. gini_toolkit-6.0.1.dev0/tests/test_xv6.py +353 -0
  479. gini_toolkit-6.0.1.dev0/tests/test_xv6_agent.py +62 -0
  480. gini_toolkit-6.0.1.dev0/tests/test_xv6_bridge.py +358 -0
  481. gini_toolkit-6.0.1.dev0/tests/test_xv6_compile.py +45 -0
  482. gini_toolkit-6.0.1.dev0/tests/test_xv6_fs.py +56 -0
  483. gini_toolkit-6.0.1.dev0/tests/test_xv6_modes.py +138 -0
  484. gini_toolkit-6.0.1.dev0/tests/test_xv6_pack.py +68 -0
  485. gini_toolkit-6.0.1.dev0/tests/test_xv6_patch.py +166 -0
  486. gini_toolkit-6.0.1.dev0/tests/test_xv6_runner.py +71 -0
  487. gini_toolkit-6.0.1.dev0/tests/test_xv6_vm.py +129 -0
  488. gini_toolkit-6.0.1.dev0/token.txt +1 -0
@@ -0,0 +1,77 @@
1
+ Metadata-Version: 2.4
2
+ Name: gini-toolkit
3
+ Version: 6.0.1.dev0
4
+ Summary: GINI gBuilder — next-generation topology builder for computer networks and cloud computing experimentation
5
+ Author: GINI Toolkit
6
+ License: GPL-3.0-or-later
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: PySide6-Essentials>=6.6
10
+ Requires-Dist: PyYAML>=6.0
11
+ Provides-Extra: agent
12
+ Requires-Dist: mcp>=1.0; extra == "agent"
13
+ Provides-Extra: graph
14
+ Requires-Dist: matplotlib>=3.7; extra == "graph"
15
+ Requires-Dist: numpy>=1.24; extra == "graph"
16
+ Provides-Extra: dev
17
+ Requires-Dist: pytest>=7; extra == "dev"
18
+ Requires-Dist: pytest-qt>=4; extra == "dev"
19
+ Requires-Dist: ruff>=0.4; extra == "dev"
20
+ Requires-Dist: mypy>=1.8; extra == "dev"
21
+
22
+ # GINI gBuilder — next generation
23
+
24
+ A ground-up rewrite of the GINI gBuilder frontend on **PySide6 (Qt 6) / Python 3**, expanding
25
+ GINI from a computer-networks lab into an **ultimate experimentation toolkit** spanning both
26
+ **computer networks** and **cloud computing**, with a first-class **AI agent layer** so agents can
27
+ build, inspect, and explain topologies for students.
28
+
29
+ ## What's here
30
+
31
+ ```
32
+ frontend-ng/
33
+ ├── pyproject.toml
34
+ ├── src/gini/
35
+ │ ├── __main__.py launch the app (python -m gini)
36
+ │ ├── domain/ pure-Python model — NO Qt
37
+ │ │ ├── devices.py device/element registry (networking + cloud)
38
+ │ │ └── topology.py Topology, DeviceInstance, Link
39
+ │ ├── app/
40
+ │ │ └── context.py AppContext + typed event bus (replaces global singletons)
41
+ │ ├── ui/
42
+ │ │ ├── main_window.py shell: toolbar, palette, canvas, inspector, console, assistant
43
+ │ │ ├── canvas.py QGraphicsView scene + node/edge items
44
+ │ │ ├── palette.py searchable, categorized device palette
45
+ │ │ ├── inspector.py tabbed property inspector
46
+ │ │ ├── assistant.py in-app "Ask GINI" AI assistant panel
47
+ │ │ └── theme/
48
+ │ │ ├── tokens.py themeable design tokens (dark / light / brand)
49
+ │ │ ├── manager.py token → QSS generator + ThemeManager
50
+ │ │ └── icons.py license-safe flat SVG icon set, recolored per category
51
+ │ └── agent/
52
+ │ ├── api.py programmatic GiniAPI: build / inspect / explain / run
53
+ │ └── mcp_server.py MCP server exposing GiniAPI to external agents
54
+ └── tests/
55
+ ```
56
+
57
+ ## Run it
58
+
59
+ ```bash
60
+ cd frontend-ng
61
+ pip install -e .
62
+ gbuilder # or: python -m gini
63
+ ```
64
+
65
+ Headless smoke test (no display needed):
66
+
67
+ ```bash
68
+ QT_QPA_PLATFORM=offscreen python -m gini --selftest
69
+ ```
70
+
71
+ ## Status
72
+
73
+ Early scaffold (Phase 2 of the evolution plan). The UI shell, themeable design system, icon
74
+ system, the expanded device taxonomy, and the agent API/MCP scaffold are in place and runnable.
75
+ The legacy `.gsav`/compiler/protocol services are being ported behind `services/` next.
76
+
77
+ See `../GINI Project/GINI_Frontend_Evolution_Plan.md` for the full roadmap.
@@ -0,0 +1,56 @@
1
+ # GINI gBuilder — next generation
2
+
3
+ A ground-up rewrite of the GINI gBuilder frontend on **PySide6 (Qt 6) / Python 3**, expanding
4
+ GINI from a computer-networks lab into an **ultimate experimentation toolkit** spanning both
5
+ **computer networks** and **cloud computing**, with a first-class **AI agent layer** so agents can
6
+ build, inspect, and explain topologies for students.
7
+
8
+ ## What's here
9
+
10
+ ```
11
+ frontend-ng/
12
+ ├── pyproject.toml
13
+ ├── src/gini/
14
+ │ ├── __main__.py launch the app (python -m gini)
15
+ │ ├── domain/ pure-Python model — NO Qt
16
+ │ │ ├── devices.py device/element registry (networking + cloud)
17
+ │ │ └── topology.py Topology, DeviceInstance, Link
18
+ │ ├── app/
19
+ │ │ └── context.py AppContext + typed event bus (replaces global singletons)
20
+ │ ├── ui/
21
+ │ │ ├── main_window.py shell: toolbar, palette, canvas, inspector, console, assistant
22
+ │ │ ├── canvas.py QGraphicsView scene + node/edge items
23
+ │ │ ├── palette.py searchable, categorized device palette
24
+ │ │ ├── inspector.py tabbed property inspector
25
+ │ │ ├── assistant.py in-app "Ask GINI" AI assistant panel
26
+ │ │ └── theme/
27
+ │ │ ├── tokens.py themeable design tokens (dark / light / brand)
28
+ │ │ ├── manager.py token → QSS generator + ThemeManager
29
+ │ │ └── icons.py license-safe flat SVG icon set, recolored per category
30
+ │ └── agent/
31
+ │ ├── api.py programmatic GiniAPI: build / inspect / explain / run
32
+ │ └── mcp_server.py MCP server exposing GiniAPI to external agents
33
+ └── tests/
34
+ ```
35
+
36
+ ## Run it
37
+
38
+ ```bash
39
+ cd frontend-ng
40
+ pip install -e .
41
+ gbuilder # or: python -m gini
42
+ ```
43
+
44
+ Headless smoke test (no display needed):
45
+
46
+ ```bash
47
+ QT_QPA_PLATFORM=offscreen python -m gini --selftest
48
+ ```
49
+
50
+ ## Status
51
+
52
+ Early scaffold (Phase 2 of the evolution plan). The UI shell, themeable design system, icon
53
+ system, the expanded device taxonomy, and the agent API/MCP scaffold are in place and runnable.
54
+ The legacy `.gsav`/compiler/protocol services are being ported behind `services/` next.
55
+
56
+ See `../GINI Project/GINI_Frontend_Evolution_Plan.md` for the full roadmap.
@@ -0,0 +1,60 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "setuptools-scm>=8"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "gini-toolkit"
7
+ dynamic = ["version"] # derived from git tags by setuptools-scm (see [tool.setuptools_scm])
8
+ description = "GINI gBuilder — next-generation topology builder for computer networks and cloud computing experimentation"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "GPL-3.0-or-later" }
12
+ authors = [{ name = "GINI Toolkit" }]
13
+ # `pip install gini-toolkit` gives a runnable desktop app: engine + the PySide6/Qt GUI. The
14
+ # container runtime (Docker/Colima) and images are brought in separately by the `gini-setup` command.
15
+ dependencies = [
16
+ "PySide6-Essentials>=6.6", # the Qt6 desktop GUI (gini.ui + the `gbuilder` entrypoint)
17
+ "PyYAML>=6.0", # reads authored Lesson packs (Missions / Teaching Center)
18
+ ]
19
+
20
+ [project.optional-dependencies]
21
+ agent = [
22
+ "mcp>=1.0", # Model Context Protocol server (in-app + external agents)
23
+ ]
24
+ graph = [
25
+ "matplotlib>=3.7", # router / instance statistics graphing
26
+ "numpy>=1.24",
27
+ ]
28
+ dev = [
29
+ "pytest>=7",
30
+ "pytest-qt>=4",
31
+ "ruff>=0.4",
32
+ "mypy>=1.8",
33
+ ]
34
+
35
+ [project.scripts]
36
+ gbuilder = "gini.__main__:main" # the desktop app
37
+ gini-setup = "gini.setup.cli:main" # one-time: bring in the container runtime + images
38
+
39
+ [tool.setuptools.packages.find]
40
+ where = ["src"]
41
+
42
+ [tool.setuptools.package-data]
43
+ "gini.ui" = ["assets/*.png", "assets/*.ico", "assets/*.icns"]
44
+ "gini.domain" = ["missions/**/*.yaml"]
45
+
46
+ # Version comes from git tags (e.g. `git tag v6.1.0` -> 6.1.0). The repo root is one level up from
47
+ # this pyproject, hence root = "..". A generated _version.py is written into the package at build
48
+ # time (gitignored). Untagged working trees get e.g. 6.1.0.dev3+g<hash>.
49
+ [tool.setuptools_scm]
50
+ root = ".."
51
+ version_file = "src/gini/_version.py"
52
+ # drop the "+g<hash>" local segment: tagged clean builds -> 6.0.0; between-tag builds -> 6.0.1.dev0
53
+ local_scheme = "no-local-version"
54
+
55
+ [tool.ruff]
56
+ line-length = 100
57
+ target-version = "py310"
58
+
59
+ [tool.pytest.ini_options]
60
+ testpaths = ["tests"]
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env python3
2
+ """Build the shipped semantic index for Ask GINI's L2 recall.
3
+
4
+ Embeds every KB document (`agent.embed.kb_documents()`) via an Ollama `/api/embed` call and
5
+ writes `src/gini/data/kb_index.json` (model tag + KB hash + id→vector). Run this whenever the
6
+ concept notes, recipes, or element catalog change — a test (`test_kb_index_sync`) fails if the
7
+ shipped index drifts from the live KB.
8
+
9
+ Requires a running Ollama with the embed model pulled, e.g.:
10
+
11
+ ollama pull all-minilm
12
+ GINI_LLM_URL=http://localhost:11434 python scripts/build_kb_index.py
13
+
14
+ Env: GINI_LLM_URL (default http://localhost:11434), GINI_EMBED_MODEL (default all-minilm).
15
+ """
16
+ from __future__ import annotations
17
+
18
+ import json
19
+ import os
20
+ import sys
21
+ from pathlib import Path
22
+
23
+ sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "src"))
24
+
25
+ from gini.agent.embed import _INDEX_PATH, kb_documents, kb_hash # noqa: E402
26
+ from gini.agent.llm import OllamaBackend # noqa: E402
27
+
28
+
29
+ def main() -> int:
30
+ url = os.environ.get("GINI_LLM_URL", "http://localhost:11434")
31
+ model = os.environ.get("GINI_EMBED_MODEL", "all-minilm")
32
+ backend = OllamaBackend(url, embed_model=model)
33
+ if not backend.available():
34
+ print(f"Ollama not reachable at {url} — start it and `ollama pull {model}`.")
35
+ return 1
36
+
37
+ docs = kb_documents()
38
+ ids = [d for d, _ in docs]
39
+ texts = [t for _, t in docs]
40
+ print(f"Embedding {len(texts)} KB documents with '{model}' …")
41
+
42
+ vectors: dict[str, list[float]] = {}
43
+ for i in range(0, len(texts), 32): # batch to be gentle on the server
44
+ chunk_ids = ids[i:i + 32]
45
+ chunk_vecs = backend.embed(texts[i:i + 32])
46
+ if len(chunk_vecs) != len(chunk_ids):
47
+ print(f" embed returned {len(chunk_vecs)} vectors for {len(chunk_ids)} docs — aborting.")
48
+ return 2
49
+ for did, vec in zip(chunk_ids, chunk_vecs):
50
+ vectors[did] = [round(float(x), 6) for x in vec]
51
+
52
+ dim = len(next(iter(vectors.values()))) if vectors else 0
53
+ index = {"model": model, "dim": dim, "kb_hash": kb_hash(), "vectors": vectors}
54
+ _INDEX_PATH.parent.mkdir(parents=True, exist_ok=True)
55
+ _INDEX_PATH.write_text(json.dumps(index))
56
+ print(f"Wrote {_INDEX_PATH} — {len(vectors)} vectors, dim {dim}.")
57
+ return 0
58
+
59
+
60
+ if __name__ == "__main__":
61
+ raise SystemExit(main())
@@ -0,0 +1,193 @@
1
+ """Generate the Cue Cards feature-tour screenshots from the real gBuilder UI, per theme.
2
+
3
+ Renders curated portions of the actual interface (no mockups) to PNGs under
4
+ ``src/gini/ui/assets/cue/<theme-slug>/<kind>.png`` — one set per theme, one image per card
5
+ in cue_cards.FEATURE_CARDS — so the tour matches whatever theme GINI is running. Re-run
6
+ after UI changes (best on macOS for native fonts)::
7
+
8
+ QT_QPA_PLATFORM=offscreen python -m scripts.gen_cue_shots
9
+ """
10
+ from __future__ import annotations
11
+
12
+ import os
13
+ import re
14
+ import tempfile
15
+ from pathlib import Path
16
+
17
+ os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
18
+ # write any settings to a throwaway home so the generator never changes the user's theme
19
+ os.environ["GINI_HOME_DIR"] = tempfile.mkdtemp(prefix="gini-genshots-")
20
+
21
+ SS = 2 # supersample factor — captures at 2x so the cards stay sharp on Retina
22
+
23
+ from PySide6.QtCore import QPoint, QRectF, Qt
24
+ from PySide6.QtGui import QImage, QPainter
25
+ from PySide6.QtWidgets import QApplication
26
+
27
+ OUT = Path(__file__).resolve().parents[1] / "src" / "gini" / "ui" / "assets" / "cue"
28
+ THEMES = ("Dark", "Light", "GINI Brand", "High Contrast", "Sand", "Blue", "Green")
29
+
30
+
31
+ def theme_slug(name: str) -> str:
32
+ return re.sub(r"[^a-z0-9]", "", (name or "dark").lower()) or "dark"
33
+
34
+
35
+ def _bg(theme) -> int:
36
+ c = theme.theme.bg
37
+ from gini.ui.cue_cards import _qcolor
38
+ return _qcolor(c).rgb()
39
+
40
+
41
+ def _save(img: QImage, name: str, outdir: Path) -> None:
42
+ outdir.mkdir(parents=True, exist_ok=True)
43
+ img.save(str(outdir / f"{name}.png"))
44
+
45
+
46
+ def _scene_shot(scene, name, outdir, bg, scale=2.8, pad=26) -> None:
47
+ rect = scene.itemsBoundingRect().adjusted(-pad, -pad, pad, pad)
48
+ img = QImage(max(1, int(rect.width() * scale)), max(1, int(rect.height() * scale)),
49
+ QImage.Format_ARGB32)
50
+ img.fill(bg)
51
+ p = QPainter(img)
52
+ p.setRenderHint(QPainter.Antialiasing, True)
53
+ p.setRenderHint(QPainter.SmoothPixmapTransform, True)
54
+ p.setRenderHint(QPainter.TextAntialiasing, True)
55
+ scene.render(p, QRectF(img.rect()), rect); p.end()
56
+ _save(img, name, outdir)
57
+
58
+
59
+ def _widget_shot(widget, name, outdir, bg, w, h) -> None:
60
+ # render through a painter scaled by SS so the PNG is high-res regardless of the
61
+ # platform's device-pixel-ratio (grab() alone is 1x offscreen on Linux).
62
+ widget.resize(w, h)
63
+ QApplication.processEvents()
64
+ sz = widget.size() # actual size (clamps to the size hint)
65
+ img = QImage(sz.width() * SS, sz.height() * SS, QImage.Format_ARGB32)
66
+ img.fill(bg)
67
+ p = QPainter(img)
68
+ p.scale(SS, SS)
69
+ widget.render(p, QPoint(0, 0))
70
+ p.end()
71
+ _save(img, name, outdir)
72
+
73
+
74
+ def _clear_warnings(win) -> None:
75
+ win.ctx.warnings = {}
76
+ for n in win.canvas.scene_.nodes.values():
77
+ n.update()
78
+
79
+
80
+ def _generate(win, app, outdir: Path) -> None:
81
+ """Render the full set of curated shots for the currently-applied theme."""
82
+ api = win.api
83
+ scene = win.canvas.scene_
84
+ bg = _bg(win.theme)
85
+
86
+ def reset():
87
+ for did in list(win.ctx.topology.devices):
88
+ api.remove_device(did)
89
+
90
+ # --- welcome / canvas / run: a small topology ---------------------------
91
+ reset()
92
+ h = api.add_device("host", x=-40, y=120)["id"]
93
+ s = api.add_device("switch", x=180, y=120)["id"]
94
+ r = api.add_device("router", x=400, y=120)["id"]
95
+ db = api.add_device("database", x=620, y=20)["id"]
96
+ wa = api.add_device("web_app", x=620, y=220)["id"]
97
+ for a, b in [(h, s), (s, r), (r, db), (r, wa)]:
98
+ win.ctx.topology.add_link(a, b)
99
+ win.ctx.bus.link_added.emit(list(win.ctx.topology.links)[-1])
100
+ app.processEvents(); _clear_warnings(win)
101
+ _scene_shot(scene, "welcome", outdir, bg)
102
+ _scene_shot(scene, "canvas", outdir, bg)
103
+ for n in scene.nodes.values():
104
+ n.set_status("running")
105
+ app.processEvents()
106
+ _scene_shot(scene, "run", outdir, bg)
107
+
108
+ # --- X-ray / Wizard: ghost ring around a router -------------------------
109
+ reset()
110
+ rr = api.add_device("router", x=120, y=120)["id"]
111
+ app.processEvents(); _clear_warnings(win)
112
+ try:
113
+ win.canvas._lp_node = scene.nodes[rr]
114
+ win.canvas._fire_xray(); app.processEvents()
115
+ _scene_shot(scene, "wizard", outdir, bg, scale=2.4)
116
+ win.canvas.clear_xray()
117
+ except Exception as e:
118
+ print("wizard skipped:", e)
119
+
120
+ # --- cloud & VPCs: a VPC box with services ------------------------------
121
+ reset()
122
+ vpc = api.add_device("vpc", x=20, y=20)["id"]
123
+ win.ctx.topology.devices[vpc].properties["Name"] = "prod"
124
+ api.add_device("database", x=150, y=150); api.add_device("cache", x=150, y=250)
125
+ app.processEvents(); _clear_warnings(win)
126
+ scene._on_device_changed(vpc)
127
+ _scene_shot(scene, "cloud", outdir, bg)
128
+
129
+ # --- serverless: the Function inspector ---------------------------------
130
+ reset()
131
+ fid = api.add_device("function")["id"]
132
+ api.set_property(fid, "Handler", "custom")
133
+ win.ctx.select(fid); win.inspector.set_live_running(True); app.processEvents()
134
+ _widget_shot(win.inspector, "serverless", outdir, bg, 360, 560)
135
+
136
+ # --- cost meter: the dashboard strip ------------------------------------
137
+ from gini.domain.pricing import bill
138
+ for tk in ("k8s_cluster", "pod", "function", "database", "host"):
139
+ api.add_device(tk)
140
+ win.dashboard.set_estimate(bill(win.ctx.topology, win.ctx.settings.prices))
141
+ app.processEvents()
142
+ _widget_shot(win.dashboard, "cost", outdir, bg, 760, 120)
143
+
144
+ # --- live metrics -------------------------------------------------------
145
+ try:
146
+ import math
147
+ from gini.ui.live_metrics import LiveMetrics
148
+ lm = LiveMetrics(win.theme)
149
+ for i in range(60):
150
+ lm.push(40 + 30 * math.sin(i / 6), 300 + 120 * math.sin(i / 9),
151
+ 50 + 40 * math.sin(i / 5), 8 + 5 * math.sin(i / 7))
152
+ _widget_shot(lm, "metrics", outdir, bg, 360, 300)
153
+ except Exception as e:
154
+ print("metrics skipped:", e)
155
+
156
+ # --- ask GINI: the assistant panel --------------------------------------
157
+ try:
158
+ _widget_shot(win.assistant, "ai", outdir, bg, 380, 420)
159
+ except Exception as e:
160
+ print("ai skipped:", e)
161
+
162
+ # --- settings: the tabbed dialog ----------------------------------------
163
+ from gini.ui.settings_dialog import SettingsDialog
164
+ dlg = SettingsDialog(win, win.ctx.settings)
165
+ _widget_shot(dlg, "settings", outdir, bg, 480, 360)
166
+
167
+ # --- router lab (best effort) -------------------------------------------
168
+ try:
169
+ reset()
170
+ rid = api.add_device("router")["id"]
171
+ win.ctx.select(rid); win._open_router_lab(rid)
172
+ _widget_shot(win._router_lab, "router", outdir, bg, 560, 420)
173
+ win._router_lab.close()
174
+ except Exception as e:
175
+ print("router skipped:", e)
176
+
177
+
178
+ def main() -> int:
179
+ app = QApplication.instance() or QApplication([])
180
+ from gini.ui.main_window import MainWindow
181
+ win = MainWindow(app)
182
+ for name in THEMES:
183
+ win.theme.set_theme(name)
184
+ app.processEvents()
185
+ outdir = OUT / theme_slug(name)
186
+ _generate(win, app, outdir)
187
+ print("theme done:", name, "->", outdir.name)
188
+ print("all done ->", OUT)
189
+ return 0
190
+
191
+
192
+ if __name__ == "__main__":
193
+ raise SystemExit(main())
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env python3
2
+ """image_report — what GINI actually ships, and what it costs.
3
+
4
+ Two things worth separating, because they get conflated and they have different fixes:
5
+
6
+ * IMAGE SIZE — hurts the FIRST run on a machine (build + pull), disk, and CI. On a warm Mac with
7
+ the layers already cached it costs comparatively little per boot.
8
+ * BOOT TIME — what a student actually feels. Driven by container create + whatever the entrypoint
9
+ does before it's useful (our shuttle, a database's initdb, k3s coming up), not by megabytes.
10
+
11
+ So this prints BOTH: the size of every image the topology uses, and the wall-clock time from
12
+ `docker compose up` to each service being up. Optimise what the numbers say, not what we assume.
13
+
14
+ python3 scripts/image_report.py # sizes of every GINI image present
15
+ python3 scripts/image_report.py --boot # …plus time a cold `up` of the running project
16
+ """
17
+ from __future__ import annotations
18
+
19
+ import argparse
20
+ import json
21
+ import subprocess
22
+ import time
23
+
24
+ # every image GINI can instantiate, and where it comes from
25
+ GINI_BUILT = {
26
+ "gini-machine": "Host / Machine — python:3.12-slim + the full book toolkit (apt)",
27
+ "gini-fabric": "the L2 fabric (all switches multiplexed) — python:3.12-slim",
28
+ "gini-grouter": "Router / OVS — debian:bookworm-slim + zig + gcc (single-stage)",
29
+ "gini-pox": "SDN controller — python:3.9-slim + POX",
30
+ "gini-xv6": "Machine (xv6) — debian:bookworm-slim + riscv toolchain + qemu (single-stage)",
31
+ "gini-faas": "serverless runtime — python:3.12-slim + pika/nats/kafka",
32
+ "gini-cloudfabric": "telemetry agent — python:3.12-slim + psycopg2",
33
+ "gini-sg": "security group — alpine:3.20 + iptables ← the lean one",
34
+ }
35
+ PULLED = {
36
+ "postgres:16-alpine": "Database", "redis:7-alpine": "Cache", "nginx:alpine": "Load Balancer",
37
+ "nats:latest": "Messaging", "nginxdemos/hello:latest": "Web App", "registry:2": "Registry",
38
+ "traefik:v3.1": "API Gateway / Proxy", "minio/minio:latest": "Object Store",
39
+ "rabbitmq:3-management-alpine": "Queue", "mongo:7": "NoSQL",
40
+ "redpandadata/redpanda:latest": "Stream", "prom/prometheus:latest": "Metrics",
41
+ "grafana/grafana:latest": "Dashboard", "jaegertracing/all-in-one:latest": "Tracing",
42
+ "fortio/fortio:latest": "Load Generator", "rancher/k3s:v1.30.6-k3s1": "K8s Cluster",
43
+ "gcr.io/cadvisor/cadvisor:v0.49.1": "container metrics",
44
+ }
45
+
46
+
47
+ def sh(cmd, cwd=None):
48
+ try:
49
+ r = subprocess.run(cmd, cwd=cwd, capture_output=True, text=True, timeout=60)
50
+ return r.returncode, (r.stdout or "") + (r.stderr or "")
51
+ except Exception as e: # noqa: BLE001
52
+ return 127, str(e)
53
+
54
+
55
+ def sizes() -> dict[str, str]:
56
+ code, out = sh(["docker", "images", "--format", "{{.Repository}}:{{.Tag}}\t{{.Size}}"])
57
+ if code != 0:
58
+ return {}
59
+ got = {}
60
+ for line in out.splitlines():
61
+ if "\t" not in line:
62
+ continue
63
+ name, size = line.split("\t", 1)
64
+ got[name.strip()] = size.strip()
65
+ got.setdefault(name.split(":")[0].strip(), size.strip()) # also match untagged lookups
66
+ return got
67
+
68
+
69
+ def main() -> int:
70
+ ap = argparse.ArgumentParser()
71
+ ap.add_argument("--boot", action="store_true", help="also time the running project's services")
72
+ a = ap.parse_args()
73
+
74
+ have = sizes()
75
+ if not have:
76
+ print("Docker isn't answering — is it running?")
77
+ return 1
78
+
79
+ def table(title, entries):
80
+ print(f"\n\033[1m{title}\033[0m")
81
+ missing = []
82
+ for img, what in entries.items():
83
+ size = have.get(img) or have.get(img.split(":")[0])
84
+ if size is None:
85
+ missing.append(img)
86
+ continue
87
+ print(f" {size:>9} {img:<34} {what}")
88
+ for img in missing:
89
+ print(f" {'—':>9} {img:<34} (not built/pulled here yet)")
90
+
91
+ table("BUILT BY GINI (docker build, on your machine)", GINI_BUILT)
92
+ table("PULLED FROM UPSTREAM", PULLED)
93
+
94
+ print("\n\033[1mNotes\033[0m")
95
+ print(" · gini-machine is instantiated ONCE PER HOST — it's both the fattest and the most")
96
+ print(" replicated image, so it's where any optimisation pays off the most.")
97
+ print(" · gini-grouter and gini-xv6 are SINGLE-STAGE: the compilers (zig/gcc, riscv toolchain,")
98
+ print(" qemu build deps) are still inside the shipped image. A multi-stage build drops them.")
99
+ print(" · ':latest' tags are not reproducible — two students can get different bytes.")
100
+
101
+ if a.boot:
102
+ code, out = sh(["docker", "compose", "ls", "--format", "json"])
103
+ rows = json.loads(out or "[]") if code == 0 else []
104
+ running = [r for r in rows if "running" in str(r.get("Status", "")).lower()]
105
+ if not running:
106
+ print("\n(no running lab to time — start one, then re-run with --boot)")
107
+ return 0
108
+ proj = running[0]["Name"]
109
+ wd = (running[0].get("ConfigFiles") or "").split(",")[0].rsplit("/", 1)[0]
110
+ print(f"\n\033[1mBOOT TIME — restarting '{proj}' to measure\033[0m")
111
+ sh(["docker", "compose", "-p", proj, "down"], cwd=wd)
112
+ t0 = time.time()
113
+ code, _ = sh(["docker", "compose", "-p", proj, "up", "-d"], cwd=wd)
114
+ dt = time.time() - t0
115
+ print(f" compose up returned in \033[1m{dt:.1f}s\033[0m (images already cached)")
116
+ print(" → if this is fast but the FIRST run on a fresh Mac is slow, the cost is image")
117
+ print(" build/pull, not boot: fix it with leaner images. If THIS is slow, the cost is")
118
+ print(" container startup, and leaner images will not help much.")
119
+ return 0
120
+
121
+
122
+ if __name__ == "__main__":
123
+ raise SystemExit(main())