amd-gaia 0.14.2__py3-none-any.whl → 0.14.3__py3-none-any.whl

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 (788) hide show
  1. {amd_gaia-0.14.2.dist-info → amd_gaia-0.14.3.dist-info}/METADATA +5 -2
  2. amd_gaia-0.14.3.dist-info/RECORD +168 -0
  3. {amd_gaia-0.14.2.dist-info → amd_gaia-0.14.3.dist-info}/entry_points.txt +1 -0
  4. gaia/__init__.py +28 -1
  5. gaia/agents/__init__.py +1 -1
  6. gaia/agents/base/__init__.py +1 -1
  7. gaia/agents/base/agent.py +110 -33
  8. gaia/agents/base/api_agent.py +1 -1
  9. gaia/agents/base/console.py +399 -15
  10. gaia/agents/base/errors.py +237 -0
  11. gaia/agents/base/mcp_agent.py +1 -1
  12. gaia/agents/base/tools.py +1 -1
  13. gaia/agents/blender/agent.py +1 -1
  14. gaia/agents/blender/agent_simple.py +1 -1
  15. gaia/agents/blender/app.py +1 -1
  16. gaia/agents/blender/app_simple.py +1 -1
  17. gaia/agents/blender/core/__init__.py +1 -1
  18. gaia/agents/blender/core/materials.py +1 -1
  19. gaia/agents/blender/core/objects.py +1 -1
  20. gaia/agents/blender/core/rendering.py +1 -1
  21. gaia/agents/blender/core/scene.py +1 -1
  22. gaia/agents/blender/core/view.py +1 -1
  23. gaia/agents/chat/__init__.py +1 -1
  24. gaia/agents/chat/agent.py +36 -153
  25. gaia/agents/chat/app.py +1 -1
  26. gaia/agents/chat/session.py +1 -1
  27. gaia/agents/chat/tools/__init__.py +1 -1
  28. gaia/agents/chat/tools/file_tools.py +1 -1
  29. gaia/agents/chat/tools/rag_tools.py +1 -1
  30. gaia/agents/chat/tools/shell_tools.py +1 -1
  31. gaia/agents/code/__init__.py +1 -1
  32. gaia/agents/code/agent.py +3 -1
  33. gaia/agents/code/orchestration/__init__.py +1 -1
  34. gaia/agents/code/orchestration/checklist_executor.py +1 -1
  35. gaia/agents/code/orchestration/checklist_generator.py +1 -1
  36. gaia/agents/code/orchestration/factories/__init__.py +1 -1
  37. gaia/agents/code/orchestration/factories/base.py +1 -1
  38. gaia/agents/code/orchestration/factories/nextjs_factory.py +1 -1
  39. gaia/agents/code/orchestration/factories/python_factory.py +1 -1
  40. gaia/agents/code/orchestration/orchestrator.py +212 -1
  41. gaia/agents/code/orchestration/project_analyzer.py +1 -1
  42. gaia/agents/code/orchestration/steps/__init__.py +1 -1
  43. gaia/agents/code/orchestration/steps/base.py +1 -1
  44. gaia/agents/code/orchestration/steps/error_handler.py +1 -1
  45. gaia/agents/code/orchestration/steps/nextjs.py +1 -1
  46. gaia/agents/code/orchestration/steps/python.py +1 -1
  47. gaia/agents/code/orchestration/template_catalog.py +1 -1
  48. gaia/agents/code/orchestration/workflows/__init__.py +1 -1
  49. gaia/agents/code/orchestration/workflows/base.py +1 -1
  50. gaia/agents/code/orchestration/workflows/nextjs.py +1 -1
  51. gaia/agents/code/orchestration/workflows/python.py +1 -1
  52. gaia/agents/code/prompts/__init__.py +1 -1
  53. gaia/agents/code/prompts/base_prompt.py +1 -1
  54. gaia/agents/code/prompts/code_patterns.py +1 -1
  55. gaia/agents/code/prompts/nextjs_prompt.py +1 -1
  56. gaia/agents/code/prompts/python_prompt.py +1 -1
  57. gaia/agents/code/schema_inference.py +1 -1
  58. gaia/agents/code/system_prompt.py +1 -1
  59. gaia/agents/code/tools/__init__.py +1 -1
  60. gaia/agents/code/tools/cli_tools.py +1 -1
  61. gaia/agents/code/tools/code_formatting.py +1 -1
  62. gaia/agents/code/tools/code_tools.py +1 -1
  63. gaia/agents/code/tools/error_fixing.py +1 -1
  64. gaia/agents/code/tools/external_tools.py +1 -1
  65. gaia/agents/code/tools/prisma_tools.py +1 -1
  66. gaia/agents/code/tools/project_management.py +1 -1
  67. gaia/agents/code/tools/testing.py +1 -1
  68. gaia/agents/code/tools/typescript_tools.py +1 -1
  69. gaia/agents/code/tools/validation_parsing.py +1 -1
  70. gaia/agents/code/tools/validation_tools.py +5 -2
  71. gaia/agents/code/tools/web_dev_tools.py +1 -2
  72. gaia/agents/docker/__init__.py +1 -1
  73. gaia/agents/emr/__init__.py +8 -0
  74. gaia/agents/emr/agent.py +1506 -0
  75. gaia/agents/emr/cli.py +1322 -0
  76. gaia/agents/emr/constants.py +475 -0
  77. gaia/agents/emr/dashboard/__init__.py +4 -0
  78. gaia/agents/emr/dashboard/server.py +1974 -0
  79. gaia/agents/routing/__init__.py +1 -1
  80. gaia/agents/routing/agent.py +65 -7
  81. gaia/agents/routing/system_prompt.py +1 -1
  82. gaia/api/__init__.py +1 -1
  83. gaia/api/agent_registry.py +1 -1
  84. gaia/api/app.py +1 -1
  85. gaia/api/openai_server.py +1 -1
  86. gaia/api/schemas.py +1 -1
  87. gaia/api/sse_handler.py +5 -2
  88. gaia/apps/__init__.py +1 -1
  89. gaia/apps/llm/__init__.py +1 -1
  90. gaia/audio/__init__.py +1 -1
  91. gaia/audio/audio_client.py +1 -1
  92. gaia/audio/audio_recorder.py +1 -1
  93. gaia/audio/kokoro_tts.py +1 -1
  94. gaia/audio/whisper_asr.py +1 -1
  95. gaia/chat/__init__.py +1 -1
  96. gaia/chat/prompts.py +1 -1
  97. gaia/chat/sdk.py +25 -0
  98. gaia/cli.py +2 -2
  99. gaia/database/__init__.py +10 -0
  100. gaia/database/agent.py +176 -0
  101. gaia/database/mixin.py +290 -0
  102. gaia/database/testing.py +64 -0
  103. gaia/eval/batch_experiment.py +1 -1
  104. gaia/eval/claude.py +1 -1
  105. gaia/eval/config.py +1 -1
  106. gaia/eval/email_generator.py +1 -1
  107. gaia/eval/eval.py +1 -1
  108. gaia/eval/groundtruth.py +1 -1
  109. gaia/eval/transcript_generator.py +1 -1
  110. gaia/eval/webapp/public/app.js +1 -1
  111. gaia/eval/webapp/server.js +1 -1
  112. gaia/eval/webapp/test-setup.js +1 -1
  113. gaia/llm/__init__.py +1 -1
  114. gaia/llm/lemonade_client.py +149 -11
  115. gaia/llm/lemonade_manager.py +36 -11
  116. gaia/llm/llm_client.py +1 -1
  117. gaia/llm/vlm_client.py +93 -18
  118. gaia/logger.py +1 -1
  119. gaia/mcp/agent_mcp_server.py +1 -1
  120. gaia/mcp/blender_mcp_client.py +1 -1
  121. gaia/mcp/blender_mcp_server.py +1 -1
  122. gaia/mcp/context7_cache.py +1 -1
  123. gaia/mcp/servers/__init__.py +1 -1
  124. gaia/mcp/servers/docker_mcp.py +1 -1
  125. gaia/security.py +1 -1
  126. gaia/testing/__init__.py +87 -0
  127. gaia/testing/assertions.py +330 -0
  128. gaia/testing/fixtures.py +333 -0
  129. gaia/testing/mocks.py +493 -0
  130. gaia/util.py +1 -1
  131. gaia/utils/__init__.py +33 -0
  132. gaia/utils/file_watcher.py +675 -0
  133. gaia/utils/parsing.py +223 -0
  134. gaia/version.py +2 -2
  135. amd_gaia-0.14.2.dist-info/RECORD +0 -800
  136. gaia/eval/webapp/node_modules/.bin/mime +0 -16
  137. gaia/eval/webapp/node_modules/.bin/mime.cmd +0 -17
  138. gaia/eval/webapp/node_modules/.bin/mime.ps1 +0 -28
  139. gaia/eval/webapp/node_modules/.package-lock.json +0 -865
  140. gaia/eval/webapp/node_modules/accepts/HISTORY.md +0 -243
  141. gaia/eval/webapp/node_modules/accepts/LICENSE +0 -23
  142. gaia/eval/webapp/node_modules/accepts/README.md +0 -140
  143. gaia/eval/webapp/node_modules/accepts/index.js +0 -238
  144. gaia/eval/webapp/node_modules/accepts/package.json +0 -47
  145. gaia/eval/webapp/node_modules/array-flatten/LICENSE +0 -21
  146. gaia/eval/webapp/node_modules/array-flatten/README.md +0 -43
  147. gaia/eval/webapp/node_modules/array-flatten/array-flatten.js +0 -64
  148. gaia/eval/webapp/node_modules/array-flatten/package.json +0 -39
  149. gaia/eval/webapp/node_modules/body-parser/HISTORY.md +0 -672
  150. gaia/eval/webapp/node_modules/body-parser/LICENSE +0 -23
  151. gaia/eval/webapp/node_modules/body-parser/README.md +0 -476
  152. gaia/eval/webapp/node_modules/body-parser/SECURITY.md +0 -25
  153. gaia/eval/webapp/node_modules/body-parser/index.js +0 -156
  154. gaia/eval/webapp/node_modules/body-parser/lib/read.js +0 -205
  155. gaia/eval/webapp/node_modules/body-parser/lib/types/json.js +0 -247
  156. gaia/eval/webapp/node_modules/body-parser/lib/types/raw.js +0 -101
  157. gaia/eval/webapp/node_modules/body-parser/lib/types/text.js +0 -121
  158. gaia/eval/webapp/node_modules/body-parser/lib/types/urlencoded.js +0 -307
  159. gaia/eval/webapp/node_modules/body-parser/package.json +0 -56
  160. gaia/eval/webapp/node_modules/bytes/History.md +0 -97
  161. gaia/eval/webapp/node_modules/bytes/LICENSE +0 -23
  162. gaia/eval/webapp/node_modules/bytes/Readme.md +0 -152
  163. gaia/eval/webapp/node_modules/bytes/index.js +0 -170
  164. gaia/eval/webapp/node_modules/bytes/package.json +0 -42
  165. gaia/eval/webapp/node_modules/call-bind-apply-helpers/.eslintrc +0 -17
  166. gaia/eval/webapp/node_modules/call-bind-apply-helpers/.github/FUNDING.yml +0 -12
  167. gaia/eval/webapp/node_modules/call-bind-apply-helpers/.nycrc +0 -9
  168. gaia/eval/webapp/node_modules/call-bind-apply-helpers/CHANGELOG.md +0 -30
  169. gaia/eval/webapp/node_modules/call-bind-apply-helpers/LICENSE +0 -21
  170. gaia/eval/webapp/node_modules/call-bind-apply-helpers/README.md +0 -62
  171. gaia/eval/webapp/node_modules/call-bind-apply-helpers/actualApply.d.ts +0 -1
  172. gaia/eval/webapp/node_modules/call-bind-apply-helpers/actualApply.js +0 -10
  173. gaia/eval/webapp/node_modules/call-bind-apply-helpers/applyBind.d.ts +0 -19
  174. gaia/eval/webapp/node_modules/call-bind-apply-helpers/applyBind.js +0 -10
  175. gaia/eval/webapp/node_modules/call-bind-apply-helpers/functionApply.d.ts +0 -1
  176. gaia/eval/webapp/node_modules/call-bind-apply-helpers/functionApply.js +0 -4
  177. gaia/eval/webapp/node_modules/call-bind-apply-helpers/functionCall.d.ts +0 -1
  178. gaia/eval/webapp/node_modules/call-bind-apply-helpers/functionCall.js +0 -4
  179. gaia/eval/webapp/node_modules/call-bind-apply-helpers/index.d.ts +0 -64
  180. gaia/eval/webapp/node_modules/call-bind-apply-helpers/index.js +0 -15
  181. gaia/eval/webapp/node_modules/call-bind-apply-helpers/package.json +0 -85
  182. gaia/eval/webapp/node_modules/call-bind-apply-helpers/reflectApply.d.ts +0 -3
  183. gaia/eval/webapp/node_modules/call-bind-apply-helpers/reflectApply.js +0 -4
  184. gaia/eval/webapp/node_modules/call-bind-apply-helpers/test/index.js +0 -63
  185. gaia/eval/webapp/node_modules/call-bind-apply-helpers/tsconfig.json +0 -9
  186. gaia/eval/webapp/node_modules/call-bound/.eslintrc +0 -13
  187. gaia/eval/webapp/node_modules/call-bound/.github/FUNDING.yml +0 -12
  188. gaia/eval/webapp/node_modules/call-bound/.nycrc +0 -9
  189. gaia/eval/webapp/node_modules/call-bound/CHANGELOG.md +0 -42
  190. gaia/eval/webapp/node_modules/call-bound/LICENSE +0 -21
  191. gaia/eval/webapp/node_modules/call-bound/README.md +0 -53
  192. gaia/eval/webapp/node_modules/call-bound/index.d.ts +0 -94
  193. gaia/eval/webapp/node_modules/call-bound/index.js +0 -19
  194. gaia/eval/webapp/node_modules/call-bound/package.json +0 -99
  195. gaia/eval/webapp/node_modules/call-bound/test/index.js +0 -61
  196. gaia/eval/webapp/node_modules/call-bound/tsconfig.json +0 -10
  197. gaia/eval/webapp/node_modules/content-disposition/HISTORY.md +0 -60
  198. gaia/eval/webapp/node_modules/content-disposition/LICENSE +0 -22
  199. gaia/eval/webapp/node_modules/content-disposition/README.md +0 -142
  200. gaia/eval/webapp/node_modules/content-disposition/index.js +0 -458
  201. gaia/eval/webapp/node_modules/content-disposition/package.json +0 -44
  202. gaia/eval/webapp/node_modules/content-type/HISTORY.md +0 -29
  203. gaia/eval/webapp/node_modules/content-type/LICENSE +0 -22
  204. gaia/eval/webapp/node_modules/content-type/README.md +0 -94
  205. gaia/eval/webapp/node_modules/content-type/index.js +0 -225
  206. gaia/eval/webapp/node_modules/content-type/package.json +0 -42
  207. gaia/eval/webapp/node_modules/cookie/LICENSE +0 -24
  208. gaia/eval/webapp/node_modules/cookie/README.md +0 -317
  209. gaia/eval/webapp/node_modules/cookie/SECURITY.md +0 -25
  210. gaia/eval/webapp/node_modules/cookie/index.js +0 -334
  211. gaia/eval/webapp/node_modules/cookie/package.json +0 -44
  212. gaia/eval/webapp/node_modules/cookie-signature/.npmignore +0 -4
  213. gaia/eval/webapp/node_modules/cookie-signature/History.md +0 -38
  214. gaia/eval/webapp/node_modules/cookie-signature/Readme.md +0 -42
  215. gaia/eval/webapp/node_modules/cookie-signature/index.js +0 -51
  216. gaia/eval/webapp/node_modules/cookie-signature/package.json +0 -18
  217. gaia/eval/webapp/node_modules/debug/.coveralls.yml +0 -1
  218. gaia/eval/webapp/node_modules/debug/.eslintrc +0 -11
  219. gaia/eval/webapp/node_modules/debug/.npmignore +0 -9
  220. gaia/eval/webapp/node_modules/debug/.travis.yml +0 -14
  221. gaia/eval/webapp/node_modules/debug/CHANGELOG.md +0 -362
  222. gaia/eval/webapp/node_modules/debug/LICENSE +0 -19
  223. gaia/eval/webapp/node_modules/debug/Makefile +0 -50
  224. gaia/eval/webapp/node_modules/debug/README.md +0 -312
  225. gaia/eval/webapp/node_modules/debug/component.json +0 -19
  226. gaia/eval/webapp/node_modules/debug/karma.conf.js +0 -70
  227. gaia/eval/webapp/node_modules/debug/node.js +0 -1
  228. gaia/eval/webapp/node_modules/debug/package.json +0 -49
  229. gaia/eval/webapp/node_modules/debug/src/browser.js +0 -185
  230. gaia/eval/webapp/node_modules/debug/src/debug.js +0 -202
  231. gaia/eval/webapp/node_modules/debug/src/index.js +0 -10
  232. gaia/eval/webapp/node_modules/debug/src/inspector-log.js +0 -15
  233. gaia/eval/webapp/node_modules/debug/src/node.js +0 -248
  234. gaia/eval/webapp/node_modules/depd/History.md +0 -103
  235. gaia/eval/webapp/node_modules/depd/LICENSE +0 -22
  236. gaia/eval/webapp/node_modules/depd/Readme.md +0 -280
  237. gaia/eval/webapp/node_modules/depd/index.js +0 -538
  238. gaia/eval/webapp/node_modules/depd/lib/browser/index.js +0 -77
  239. gaia/eval/webapp/node_modules/depd/package.json +0 -45
  240. gaia/eval/webapp/node_modules/destroy/LICENSE +0 -23
  241. gaia/eval/webapp/node_modules/destroy/README.md +0 -63
  242. gaia/eval/webapp/node_modules/destroy/index.js +0 -209
  243. gaia/eval/webapp/node_modules/destroy/package.json +0 -48
  244. gaia/eval/webapp/node_modules/dunder-proto/.eslintrc +0 -5
  245. gaia/eval/webapp/node_modules/dunder-proto/.github/FUNDING.yml +0 -12
  246. gaia/eval/webapp/node_modules/dunder-proto/.nycrc +0 -13
  247. gaia/eval/webapp/node_modules/dunder-proto/CHANGELOG.md +0 -24
  248. gaia/eval/webapp/node_modules/dunder-proto/LICENSE +0 -21
  249. gaia/eval/webapp/node_modules/dunder-proto/README.md +0 -54
  250. gaia/eval/webapp/node_modules/dunder-proto/get.d.ts +0 -5
  251. gaia/eval/webapp/node_modules/dunder-proto/get.js +0 -30
  252. gaia/eval/webapp/node_modules/dunder-proto/package.json +0 -76
  253. gaia/eval/webapp/node_modules/dunder-proto/set.d.ts +0 -5
  254. gaia/eval/webapp/node_modules/dunder-proto/set.js +0 -35
  255. gaia/eval/webapp/node_modules/dunder-proto/test/get.js +0 -34
  256. gaia/eval/webapp/node_modules/dunder-proto/test/index.js +0 -4
  257. gaia/eval/webapp/node_modules/dunder-proto/test/set.js +0 -50
  258. gaia/eval/webapp/node_modules/dunder-proto/tsconfig.json +0 -9
  259. gaia/eval/webapp/node_modules/ee-first/LICENSE +0 -22
  260. gaia/eval/webapp/node_modules/ee-first/README.md +0 -80
  261. gaia/eval/webapp/node_modules/ee-first/index.js +0 -95
  262. gaia/eval/webapp/node_modules/ee-first/package.json +0 -29
  263. gaia/eval/webapp/node_modules/encodeurl/LICENSE +0 -22
  264. gaia/eval/webapp/node_modules/encodeurl/README.md +0 -109
  265. gaia/eval/webapp/node_modules/encodeurl/index.js +0 -60
  266. gaia/eval/webapp/node_modules/encodeurl/package.json +0 -40
  267. gaia/eval/webapp/node_modules/es-define-property/.eslintrc +0 -13
  268. gaia/eval/webapp/node_modules/es-define-property/.github/FUNDING.yml +0 -12
  269. gaia/eval/webapp/node_modules/es-define-property/.nycrc +0 -9
  270. gaia/eval/webapp/node_modules/es-define-property/CHANGELOG.md +0 -29
  271. gaia/eval/webapp/node_modules/es-define-property/LICENSE +0 -21
  272. gaia/eval/webapp/node_modules/es-define-property/README.md +0 -49
  273. gaia/eval/webapp/node_modules/es-define-property/index.d.ts +0 -3
  274. gaia/eval/webapp/node_modules/es-define-property/index.js +0 -14
  275. gaia/eval/webapp/node_modules/es-define-property/package.json +0 -81
  276. gaia/eval/webapp/node_modules/es-define-property/test/index.js +0 -56
  277. gaia/eval/webapp/node_modules/es-define-property/tsconfig.json +0 -10
  278. gaia/eval/webapp/node_modules/es-errors/.eslintrc +0 -5
  279. gaia/eval/webapp/node_modules/es-errors/.github/FUNDING.yml +0 -12
  280. gaia/eval/webapp/node_modules/es-errors/CHANGELOG.md +0 -40
  281. gaia/eval/webapp/node_modules/es-errors/LICENSE +0 -21
  282. gaia/eval/webapp/node_modules/es-errors/README.md +0 -55
  283. gaia/eval/webapp/node_modules/es-errors/eval.d.ts +0 -3
  284. gaia/eval/webapp/node_modules/es-errors/eval.js +0 -4
  285. gaia/eval/webapp/node_modules/es-errors/index.d.ts +0 -3
  286. gaia/eval/webapp/node_modules/es-errors/index.js +0 -4
  287. gaia/eval/webapp/node_modules/es-errors/package.json +0 -80
  288. gaia/eval/webapp/node_modules/es-errors/range.d.ts +0 -3
  289. gaia/eval/webapp/node_modules/es-errors/range.js +0 -4
  290. gaia/eval/webapp/node_modules/es-errors/ref.d.ts +0 -3
  291. gaia/eval/webapp/node_modules/es-errors/ref.js +0 -4
  292. gaia/eval/webapp/node_modules/es-errors/syntax.d.ts +0 -3
  293. gaia/eval/webapp/node_modules/es-errors/syntax.js +0 -4
  294. gaia/eval/webapp/node_modules/es-errors/test/index.js +0 -19
  295. gaia/eval/webapp/node_modules/es-errors/tsconfig.json +0 -49
  296. gaia/eval/webapp/node_modules/es-errors/type.d.ts +0 -3
  297. gaia/eval/webapp/node_modules/es-errors/type.js +0 -4
  298. gaia/eval/webapp/node_modules/es-errors/uri.d.ts +0 -3
  299. gaia/eval/webapp/node_modules/es-errors/uri.js +0 -4
  300. gaia/eval/webapp/node_modules/es-object-atoms/.eslintrc +0 -16
  301. gaia/eval/webapp/node_modules/es-object-atoms/.github/FUNDING.yml +0 -12
  302. gaia/eval/webapp/node_modules/es-object-atoms/CHANGELOG.md +0 -37
  303. gaia/eval/webapp/node_modules/es-object-atoms/LICENSE +0 -21
  304. gaia/eval/webapp/node_modules/es-object-atoms/README.md +0 -63
  305. gaia/eval/webapp/node_modules/es-object-atoms/RequireObjectCoercible.d.ts +0 -3
  306. gaia/eval/webapp/node_modules/es-object-atoms/RequireObjectCoercible.js +0 -11
  307. gaia/eval/webapp/node_modules/es-object-atoms/ToObject.d.ts +0 -7
  308. gaia/eval/webapp/node_modules/es-object-atoms/ToObject.js +0 -10
  309. gaia/eval/webapp/node_modules/es-object-atoms/index.d.ts +0 -3
  310. gaia/eval/webapp/node_modules/es-object-atoms/index.js +0 -4
  311. gaia/eval/webapp/node_modules/es-object-atoms/isObject.d.ts +0 -3
  312. gaia/eval/webapp/node_modules/es-object-atoms/isObject.js +0 -6
  313. gaia/eval/webapp/node_modules/es-object-atoms/package.json +0 -80
  314. gaia/eval/webapp/node_modules/es-object-atoms/test/index.js +0 -38
  315. gaia/eval/webapp/node_modules/es-object-atoms/tsconfig.json +0 -6
  316. gaia/eval/webapp/node_modules/escape-html/LICENSE +0 -24
  317. gaia/eval/webapp/node_modules/escape-html/Readme.md +0 -43
  318. gaia/eval/webapp/node_modules/escape-html/index.js +0 -78
  319. gaia/eval/webapp/node_modules/escape-html/package.json +0 -24
  320. gaia/eval/webapp/node_modules/etag/HISTORY.md +0 -83
  321. gaia/eval/webapp/node_modules/etag/LICENSE +0 -22
  322. gaia/eval/webapp/node_modules/etag/README.md +0 -159
  323. gaia/eval/webapp/node_modules/etag/index.js +0 -131
  324. gaia/eval/webapp/node_modules/etag/package.json +0 -47
  325. gaia/eval/webapp/node_modules/express/History.md +0 -3656
  326. gaia/eval/webapp/node_modules/express/LICENSE +0 -24
  327. gaia/eval/webapp/node_modules/express/Readme.md +0 -260
  328. gaia/eval/webapp/node_modules/express/index.js +0 -11
  329. gaia/eval/webapp/node_modules/express/lib/application.js +0 -661
  330. gaia/eval/webapp/node_modules/express/lib/express.js +0 -116
  331. gaia/eval/webapp/node_modules/express/lib/middleware/init.js +0 -43
  332. gaia/eval/webapp/node_modules/express/lib/middleware/query.js +0 -47
  333. gaia/eval/webapp/node_modules/express/lib/request.js +0 -525
  334. gaia/eval/webapp/node_modules/express/lib/response.js +0 -1179
  335. gaia/eval/webapp/node_modules/express/lib/router/index.js +0 -673
  336. gaia/eval/webapp/node_modules/express/lib/router/layer.js +0 -181
  337. gaia/eval/webapp/node_modules/express/lib/router/route.js +0 -230
  338. gaia/eval/webapp/node_modules/express/lib/utils.js +0 -303
  339. gaia/eval/webapp/node_modules/express/lib/view.js +0 -182
  340. gaia/eval/webapp/node_modules/express/package.json +0 -102
  341. gaia/eval/webapp/node_modules/finalhandler/HISTORY.md +0 -210
  342. gaia/eval/webapp/node_modules/finalhandler/LICENSE +0 -22
  343. gaia/eval/webapp/node_modules/finalhandler/README.md +0 -147
  344. gaia/eval/webapp/node_modules/finalhandler/SECURITY.md +0 -25
  345. gaia/eval/webapp/node_modules/finalhandler/index.js +0 -341
  346. gaia/eval/webapp/node_modules/finalhandler/package.json +0 -47
  347. gaia/eval/webapp/node_modules/forwarded/HISTORY.md +0 -21
  348. gaia/eval/webapp/node_modules/forwarded/LICENSE +0 -22
  349. gaia/eval/webapp/node_modules/forwarded/README.md +0 -57
  350. gaia/eval/webapp/node_modules/forwarded/index.js +0 -90
  351. gaia/eval/webapp/node_modules/forwarded/package.json +0 -45
  352. gaia/eval/webapp/node_modules/fresh/HISTORY.md +0 -70
  353. gaia/eval/webapp/node_modules/fresh/LICENSE +0 -23
  354. gaia/eval/webapp/node_modules/fresh/README.md +0 -119
  355. gaia/eval/webapp/node_modules/fresh/index.js +0 -137
  356. gaia/eval/webapp/node_modules/fresh/package.json +0 -46
  357. gaia/eval/webapp/node_modules/fs/README.md +0 -9
  358. gaia/eval/webapp/node_modules/fs/package.json +0 -20
  359. gaia/eval/webapp/node_modules/function-bind/.eslintrc +0 -21
  360. gaia/eval/webapp/node_modules/function-bind/.github/FUNDING.yml +0 -12
  361. gaia/eval/webapp/node_modules/function-bind/.github/SECURITY.md +0 -3
  362. gaia/eval/webapp/node_modules/function-bind/.nycrc +0 -13
  363. gaia/eval/webapp/node_modules/function-bind/CHANGELOG.md +0 -136
  364. gaia/eval/webapp/node_modules/function-bind/LICENSE +0 -20
  365. gaia/eval/webapp/node_modules/function-bind/README.md +0 -46
  366. gaia/eval/webapp/node_modules/function-bind/implementation.js +0 -84
  367. gaia/eval/webapp/node_modules/function-bind/index.js +0 -5
  368. gaia/eval/webapp/node_modules/function-bind/package.json +0 -87
  369. gaia/eval/webapp/node_modules/function-bind/test/.eslintrc +0 -9
  370. gaia/eval/webapp/node_modules/function-bind/test/index.js +0 -252
  371. gaia/eval/webapp/node_modules/get-intrinsic/.eslintrc +0 -42
  372. gaia/eval/webapp/node_modules/get-intrinsic/.github/FUNDING.yml +0 -12
  373. gaia/eval/webapp/node_modules/get-intrinsic/.nycrc +0 -9
  374. gaia/eval/webapp/node_modules/get-intrinsic/CHANGELOG.md +0 -186
  375. gaia/eval/webapp/node_modules/get-intrinsic/LICENSE +0 -21
  376. gaia/eval/webapp/node_modules/get-intrinsic/README.md +0 -71
  377. gaia/eval/webapp/node_modules/get-intrinsic/index.js +0 -378
  378. gaia/eval/webapp/node_modules/get-intrinsic/package.json +0 -97
  379. gaia/eval/webapp/node_modules/get-intrinsic/test/GetIntrinsic.js +0 -274
  380. gaia/eval/webapp/node_modules/get-proto/.eslintrc +0 -10
  381. gaia/eval/webapp/node_modules/get-proto/.github/FUNDING.yml +0 -12
  382. gaia/eval/webapp/node_modules/get-proto/.nycrc +0 -9
  383. gaia/eval/webapp/node_modules/get-proto/CHANGELOG.md +0 -21
  384. gaia/eval/webapp/node_modules/get-proto/LICENSE +0 -21
  385. gaia/eval/webapp/node_modules/get-proto/Object.getPrototypeOf.d.ts +0 -5
  386. gaia/eval/webapp/node_modules/get-proto/Object.getPrototypeOf.js +0 -6
  387. gaia/eval/webapp/node_modules/get-proto/README.md +0 -50
  388. gaia/eval/webapp/node_modules/get-proto/Reflect.getPrototypeOf.d.ts +0 -3
  389. gaia/eval/webapp/node_modules/get-proto/Reflect.getPrototypeOf.js +0 -4
  390. gaia/eval/webapp/node_modules/get-proto/index.d.ts +0 -5
  391. gaia/eval/webapp/node_modules/get-proto/index.js +0 -27
  392. gaia/eval/webapp/node_modules/get-proto/package.json +0 -81
  393. gaia/eval/webapp/node_modules/get-proto/test/index.js +0 -68
  394. gaia/eval/webapp/node_modules/get-proto/tsconfig.json +0 -9
  395. gaia/eval/webapp/node_modules/gopd/.eslintrc +0 -16
  396. gaia/eval/webapp/node_modules/gopd/.github/FUNDING.yml +0 -12
  397. gaia/eval/webapp/node_modules/gopd/CHANGELOG.md +0 -45
  398. gaia/eval/webapp/node_modules/gopd/LICENSE +0 -21
  399. gaia/eval/webapp/node_modules/gopd/README.md +0 -40
  400. gaia/eval/webapp/node_modules/gopd/gOPD.d.ts +0 -1
  401. gaia/eval/webapp/node_modules/gopd/gOPD.js +0 -4
  402. gaia/eval/webapp/node_modules/gopd/index.d.ts +0 -5
  403. gaia/eval/webapp/node_modules/gopd/index.js +0 -15
  404. gaia/eval/webapp/node_modules/gopd/package.json +0 -77
  405. gaia/eval/webapp/node_modules/gopd/test/index.js +0 -36
  406. gaia/eval/webapp/node_modules/gopd/tsconfig.json +0 -9
  407. gaia/eval/webapp/node_modules/has-symbols/.eslintrc +0 -11
  408. gaia/eval/webapp/node_modules/has-symbols/.github/FUNDING.yml +0 -12
  409. gaia/eval/webapp/node_modules/has-symbols/.nycrc +0 -9
  410. gaia/eval/webapp/node_modules/has-symbols/CHANGELOG.md +0 -91
  411. gaia/eval/webapp/node_modules/has-symbols/LICENSE +0 -21
  412. gaia/eval/webapp/node_modules/has-symbols/README.md +0 -46
  413. gaia/eval/webapp/node_modules/has-symbols/index.d.ts +0 -3
  414. gaia/eval/webapp/node_modules/has-symbols/index.js +0 -14
  415. gaia/eval/webapp/node_modules/has-symbols/package.json +0 -111
  416. gaia/eval/webapp/node_modules/has-symbols/shams.d.ts +0 -3
  417. gaia/eval/webapp/node_modules/has-symbols/shams.js +0 -45
  418. gaia/eval/webapp/node_modules/has-symbols/test/index.js +0 -22
  419. gaia/eval/webapp/node_modules/has-symbols/test/shams/core-js.js +0 -29
  420. gaia/eval/webapp/node_modules/has-symbols/test/shams/get-own-property-symbols.js +0 -29
  421. gaia/eval/webapp/node_modules/has-symbols/test/tests.js +0 -58
  422. gaia/eval/webapp/node_modules/has-symbols/tsconfig.json +0 -10
  423. gaia/eval/webapp/node_modules/hasown/.eslintrc +0 -5
  424. gaia/eval/webapp/node_modules/hasown/.github/FUNDING.yml +0 -12
  425. gaia/eval/webapp/node_modules/hasown/.nycrc +0 -13
  426. gaia/eval/webapp/node_modules/hasown/CHANGELOG.md +0 -40
  427. gaia/eval/webapp/node_modules/hasown/LICENSE +0 -21
  428. gaia/eval/webapp/node_modules/hasown/README.md +0 -40
  429. gaia/eval/webapp/node_modules/hasown/index.d.ts +0 -3
  430. gaia/eval/webapp/node_modules/hasown/index.js +0 -8
  431. gaia/eval/webapp/node_modules/hasown/package.json +0 -92
  432. gaia/eval/webapp/node_modules/hasown/tsconfig.json +0 -6
  433. gaia/eval/webapp/node_modules/http-errors/HISTORY.md +0 -180
  434. gaia/eval/webapp/node_modules/http-errors/LICENSE +0 -23
  435. gaia/eval/webapp/node_modules/http-errors/README.md +0 -169
  436. gaia/eval/webapp/node_modules/http-errors/index.js +0 -289
  437. gaia/eval/webapp/node_modules/http-errors/package.json +0 -50
  438. gaia/eval/webapp/node_modules/iconv-lite/Changelog.md +0 -162
  439. gaia/eval/webapp/node_modules/iconv-lite/LICENSE +0 -21
  440. gaia/eval/webapp/node_modules/iconv-lite/README.md +0 -156
  441. gaia/eval/webapp/node_modules/iconv-lite/encodings/dbcs-codec.js +0 -555
  442. gaia/eval/webapp/node_modules/iconv-lite/encodings/dbcs-data.js +0 -176
  443. gaia/eval/webapp/node_modules/iconv-lite/encodings/index.js +0 -22
  444. gaia/eval/webapp/node_modules/iconv-lite/encodings/internal.js +0 -188
  445. gaia/eval/webapp/node_modules/iconv-lite/encodings/sbcs-codec.js +0 -72
  446. gaia/eval/webapp/node_modules/iconv-lite/encodings/sbcs-data-generated.js +0 -451
  447. gaia/eval/webapp/node_modules/iconv-lite/encodings/sbcs-data.js +0 -174
  448. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/big5-added.json +0 -122
  449. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/cp936.json +0 -264
  450. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/cp949.json +0 -273
  451. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/cp950.json +0 -177
  452. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/eucjp.json +0 -182
  453. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/gb18030-ranges.json +0 -1
  454. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/gbk-added.json +0 -55
  455. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/shiftjis.json +0 -125
  456. gaia/eval/webapp/node_modules/iconv-lite/encodings/utf16.js +0 -177
  457. gaia/eval/webapp/node_modules/iconv-lite/encodings/utf7.js +0 -290
  458. gaia/eval/webapp/node_modules/iconv-lite/lib/bom-handling.js +0 -52
  459. gaia/eval/webapp/node_modules/iconv-lite/lib/extend-node.js +0 -217
  460. gaia/eval/webapp/node_modules/iconv-lite/lib/index.d.ts +0 -24
  461. gaia/eval/webapp/node_modules/iconv-lite/lib/index.js +0 -153
  462. gaia/eval/webapp/node_modules/iconv-lite/lib/streams.js +0 -121
  463. gaia/eval/webapp/node_modules/iconv-lite/package.json +0 -46
  464. gaia/eval/webapp/node_modules/inherits/LICENSE +0 -16
  465. gaia/eval/webapp/node_modules/inherits/README.md +0 -42
  466. gaia/eval/webapp/node_modules/inherits/inherits.js +0 -9
  467. gaia/eval/webapp/node_modules/inherits/inherits_browser.js +0 -27
  468. gaia/eval/webapp/node_modules/inherits/package.json +0 -29
  469. gaia/eval/webapp/node_modules/ipaddr.js/LICENSE +0 -19
  470. gaia/eval/webapp/node_modules/ipaddr.js/README.md +0 -233
  471. gaia/eval/webapp/node_modules/ipaddr.js/ipaddr.min.js +0 -1
  472. gaia/eval/webapp/node_modules/ipaddr.js/lib/ipaddr.js +0 -673
  473. gaia/eval/webapp/node_modules/ipaddr.js/lib/ipaddr.js.d.ts +0 -68
  474. gaia/eval/webapp/node_modules/ipaddr.js/package.json +0 -35
  475. gaia/eval/webapp/node_modules/math-intrinsics/.eslintrc +0 -16
  476. gaia/eval/webapp/node_modules/math-intrinsics/.github/FUNDING.yml +0 -12
  477. gaia/eval/webapp/node_modules/math-intrinsics/CHANGELOG.md +0 -24
  478. gaia/eval/webapp/node_modules/math-intrinsics/LICENSE +0 -21
  479. gaia/eval/webapp/node_modules/math-intrinsics/README.md +0 -50
  480. gaia/eval/webapp/node_modules/math-intrinsics/abs.d.ts +0 -1
  481. gaia/eval/webapp/node_modules/math-intrinsics/abs.js +0 -4
  482. gaia/eval/webapp/node_modules/math-intrinsics/constants/maxArrayLength.d.ts +0 -3
  483. gaia/eval/webapp/node_modules/math-intrinsics/constants/maxArrayLength.js +0 -4
  484. gaia/eval/webapp/node_modules/math-intrinsics/constants/maxSafeInteger.d.ts +0 -3
  485. gaia/eval/webapp/node_modules/math-intrinsics/constants/maxSafeInteger.js +0 -5
  486. gaia/eval/webapp/node_modules/math-intrinsics/constants/maxValue.d.ts +0 -3
  487. gaia/eval/webapp/node_modules/math-intrinsics/constants/maxValue.js +0 -5
  488. gaia/eval/webapp/node_modules/math-intrinsics/floor.d.ts +0 -1
  489. gaia/eval/webapp/node_modules/math-intrinsics/floor.js +0 -4
  490. gaia/eval/webapp/node_modules/math-intrinsics/isFinite.d.ts +0 -3
  491. gaia/eval/webapp/node_modules/math-intrinsics/isFinite.js +0 -12
  492. gaia/eval/webapp/node_modules/math-intrinsics/isInteger.d.ts +0 -3
  493. gaia/eval/webapp/node_modules/math-intrinsics/isInteger.js +0 -16
  494. gaia/eval/webapp/node_modules/math-intrinsics/isNaN.d.ts +0 -1
  495. gaia/eval/webapp/node_modules/math-intrinsics/isNaN.js +0 -6
  496. gaia/eval/webapp/node_modules/math-intrinsics/isNegativeZero.d.ts +0 -3
  497. gaia/eval/webapp/node_modules/math-intrinsics/isNegativeZero.js +0 -6
  498. gaia/eval/webapp/node_modules/math-intrinsics/max.d.ts +0 -1
  499. gaia/eval/webapp/node_modules/math-intrinsics/max.js +0 -4
  500. gaia/eval/webapp/node_modules/math-intrinsics/min.d.ts +0 -1
  501. gaia/eval/webapp/node_modules/math-intrinsics/min.js +0 -4
  502. gaia/eval/webapp/node_modules/math-intrinsics/mod.d.ts +0 -3
  503. gaia/eval/webapp/node_modules/math-intrinsics/mod.js +0 -9
  504. gaia/eval/webapp/node_modules/math-intrinsics/package.json +0 -86
  505. gaia/eval/webapp/node_modules/math-intrinsics/pow.d.ts +0 -1
  506. gaia/eval/webapp/node_modules/math-intrinsics/pow.js +0 -4
  507. gaia/eval/webapp/node_modules/math-intrinsics/round.d.ts +0 -1
  508. gaia/eval/webapp/node_modules/math-intrinsics/round.js +0 -4
  509. gaia/eval/webapp/node_modules/math-intrinsics/sign.d.ts +0 -3
  510. gaia/eval/webapp/node_modules/math-intrinsics/sign.js +0 -11
  511. gaia/eval/webapp/node_modules/math-intrinsics/test/index.js +0 -192
  512. gaia/eval/webapp/node_modules/math-intrinsics/tsconfig.json +0 -3
  513. gaia/eval/webapp/node_modules/media-typer/HISTORY.md +0 -22
  514. gaia/eval/webapp/node_modules/media-typer/LICENSE +0 -22
  515. gaia/eval/webapp/node_modules/media-typer/README.md +0 -81
  516. gaia/eval/webapp/node_modules/media-typer/index.js +0 -270
  517. gaia/eval/webapp/node_modules/media-typer/package.json +0 -26
  518. gaia/eval/webapp/node_modules/merge-descriptors/HISTORY.md +0 -21
  519. gaia/eval/webapp/node_modules/merge-descriptors/LICENSE +0 -23
  520. gaia/eval/webapp/node_modules/merge-descriptors/README.md +0 -49
  521. gaia/eval/webapp/node_modules/merge-descriptors/index.js +0 -60
  522. gaia/eval/webapp/node_modules/merge-descriptors/package.json +0 -39
  523. gaia/eval/webapp/node_modules/methods/HISTORY.md +0 -29
  524. gaia/eval/webapp/node_modules/methods/LICENSE +0 -24
  525. gaia/eval/webapp/node_modules/methods/README.md +0 -51
  526. gaia/eval/webapp/node_modules/methods/index.js +0 -69
  527. gaia/eval/webapp/node_modules/methods/package.json +0 -36
  528. gaia/eval/webapp/node_modules/mime/.npmignore +0 -0
  529. gaia/eval/webapp/node_modules/mime/CHANGELOG.md +0 -164
  530. gaia/eval/webapp/node_modules/mime/LICENSE +0 -21
  531. gaia/eval/webapp/node_modules/mime/README.md +0 -90
  532. gaia/eval/webapp/node_modules/mime/cli.js +0 -8
  533. gaia/eval/webapp/node_modules/mime/mime.js +0 -108
  534. gaia/eval/webapp/node_modules/mime/package.json +0 -44
  535. gaia/eval/webapp/node_modules/mime/src/build.js +0 -53
  536. gaia/eval/webapp/node_modules/mime/src/test.js +0 -60
  537. gaia/eval/webapp/node_modules/mime/types.json +0 -1
  538. gaia/eval/webapp/node_modules/mime-db/HISTORY.md +0 -507
  539. gaia/eval/webapp/node_modules/mime-db/LICENSE +0 -23
  540. gaia/eval/webapp/node_modules/mime-db/README.md +0 -100
  541. gaia/eval/webapp/node_modules/mime-db/db.json +0 -8519
  542. gaia/eval/webapp/node_modules/mime-db/index.js +0 -12
  543. gaia/eval/webapp/node_modules/mime-db/package.json +0 -60
  544. gaia/eval/webapp/node_modules/mime-types/HISTORY.md +0 -397
  545. gaia/eval/webapp/node_modules/mime-types/LICENSE +0 -23
  546. gaia/eval/webapp/node_modules/mime-types/README.md +0 -113
  547. gaia/eval/webapp/node_modules/mime-types/index.js +0 -188
  548. gaia/eval/webapp/node_modules/mime-types/package.json +0 -44
  549. gaia/eval/webapp/node_modules/ms/index.js +0 -152
  550. gaia/eval/webapp/node_modules/ms/license.md +0 -21
  551. gaia/eval/webapp/node_modules/ms/package.json +0 -37
  552. gaia/eval/webapp/node_modules/ms/readme.md +0 -51
  553. gaia/eval/webapp/node_modules/negotiator/HISTORY.md +0 -108
  554. gaia/eval/webapp/node_modules/negotiator/LICENSE +0 -24
  555. gaia/eval/webapp/node_modules/negotiator/README.md +0 -203
  556. gaia/eval/webapp/node_modules/negotiator/index.js +0 -82
  557. gaia/eval/webapp/node_modules/negotiator/lib/charset.js +0 -169
  558. gaia/eval/webapp/node_modules/negotiator/lib/encoding.js +0 -184
  559. gaia/eval/webapp/node_modules/negotiator/lib/language.js +0 -179
  560. gaia/eval/webapp/node_modules/negotiator/lib/mediaType.js +0 -294
  561. gaia/eval/webapp/node_modules/negotiator/package.json +0 -42
  562. gaia/eval/webapp/node_modules/object-inspect/.eslintrc +0 -53
  563. gaia/eval/webapp/node_modules/object-inspect/.github/FUNDING.yml +0 -12
  564. gaia/eval/webapp/node_modules/object-inspect/.nycrc +0 -13
  565. gaia/eval/webapp/node_modules/object-inspect/CHANGELOG.md +0 -424
  566. gaia/eval/webapp/node_modules/object-inspect/LICENSE +0 -21
  567. gaia/eval/webapp/node_modules/object-inspect/example/all.js +0 -23
  568. gaia/eval/webapp/node_modules/object-inspect/example/circular.js +0 -6
  569. gaia/eval/webapp/node_modules/object-inspect/example/fn.js +0 -5
  570. gaia/eval/webapp/node_modules/object-inspect/example/inspect.js +0 -10
  571. gaia/eval/webapp/node_modules/object-inspect/index.js +0 -544
  572. gaia/eval/webapp/node_modules/object-inspect/package-support.json +0 -20
  573. gaia/eval/webapp/node_modules/object-inspect/package.json +0 -105
  574. gaia/eval/webapp/node_modules/object-inspect/readme.markdown +0 -84
  575. gaia/eval/webapp/node_modules/object-inspect/test/bigint.js +0 -58
  576. gaia/eval/webapp/node_modules/object-inspect/test/browser/dom.js +0 -15
  577. gaia/eval/webapp/node_modules/object-inspect/test/circular.js +0 -16
  578. gaia/eval/webapp/node_modules/object-inspect/test/deep.js +0 -12
  579. gaia/eval/webapp/node_modules/object-inspect/test/element.js +0 -53
  580. gaia/eval/webapp/node_modules/object-inspect/test/err.js +0 -48
  581. gaia/eval/webapp/node_modules/object-inspect/test/fakes.js +0 -29
  582. gaia/eval/webapp/node_modules/object-inspect/test/fn.js +0 -76
  583. gaia/eval/webapp/node_modules/object-inspect/test/global.js +0 -17
  584. gaia/eval/webapp/node_modules/object-inspect/test/has.js +0 -15
  585. gaia/eval/webapp/node_modules/object-inspect/test/holes.js +0 -15
  586. gaia/eval/webapp/node_modules/object-inspect/test/indent-option.js +0 -271
  587. gaia/eval/webapp/node_modules/object-inspect/test/inspect.js +0 -139
  588. gaia/eval/webapp/node_modules/object-inspect/test/lowbyte.js +0 -12
  589. gaia/eval/webapp/node_modules/object-inspect/test/number.js +0 -58
  590. gaia/eval/webapp/node_modules/object-inspect/test/quoteStyle.js +0 -26
  591. gaia/eval/webapp/node_modules/object-inspect/test/toStringTag.js +0 -40
  592. gaia/eval/webapp/node_modules/object-inspect/test/undef.js +0 -12
  593. gaia/eval/webapp/node_modules/object-inspect/test/values.js +0 -261
  594. gaia/eval/webapp/node_modules/object-inspect/test-core-js.js +0 -26
  595. gaia/eval/webapp/node_modules/object-inspect/util.inspect.js +0 -1
  596. gaia/eval/webapp/node_modules/on-finished/HISTORY.md +0 -98
  597. gaia/eval/webapp/node_modules/on-finished/LICENSE +0 -23
  598. gaia/eval/webapp/node_modules/on-finished/README.md +0 -162
  599. gaia/eval/webapp/node_modules/on-finished/index.js +0 -234
  600. gaia/eval/webapp/node_modules/on-finished/package.json +0 -39
  601. gaia/eval/webapp/node_modules/parseurl/HISTORY.md +0 -58
  602. gaia/eval/webapp/node_modules/parseurl/LICENSE +0 -24
  603. gaia/eval/webapp/node_modules/parseurl/README.md +0 -133
  604. gaia/eval/webapp/node_modules/parseurl/index.js +0 -158
  605. gaia/eval/webapp/node_modules/parseurl/package.json +0 -40
  606. gaia/eval/webapp/node_modules/path/.npmignore +0 -1
  607. gaia/eval/webapp/node_modules/path/LICENSE +0 -18
  608. gaia/eval/webapp/node_modules/path/README.md +0 -15
  609. gaia/eval/webapp/node_modules/path/package.json +0 -24
  610. gaia/eval/webapp/node_modules/path/path.js +0 -628
  611. gaia/eval/webapp/node_modules/path-to-regexp/LICENSE +0 -21
  612. gaia/eval/webapp/node_modules/path-to-regexp/Readme.md +0 -35
  613. gaia/eval/webapp/node_modules/path-to-regexp/index.js +0 -156
  614. gaia/eval/webapp/node_modules/path-to-regexp/package.json +0 -30
  615. gaia/eval/webapp/node_modules/process/.eslintrc +0 -21
  616. gaia/eval/webapp/node_modules/process/LICENSE +0 -22
  617. gaia/eval/webapp/node_modules/process/README.md +0 -26
  618. gaia/eval/webapp/node_modules/process/browser.js +0 -184
  619. gaia/eval/webapp/node_modules/process/index.js +0 -2
  620. gaia/eval/webapp/node_modules/process/package.json +0 -27
  621. gaia/eval/webapp/node_modules/process/test.js +0 -199
  622. gaia/eval/webapp/node_modules/proxy-addr/HISTORY.md +0 -161
  623. gaia/eval/webapp/node_modules/proxy-addr/LICENSE +0 -22
  624. gaia/eval/webapp/node_modules/proxy-addr/README.md +0 -139
  625. gaia/eval/webapp/node_modules/proxy-addr/index.js +0 -327
  626. gaia/eval/webapp/node_modules/proxy-addr/package.json +0 -47
  627. gaia/eval/webapp/node_modules/qs/.editorconfig +0 -46
  628. gaia/eval/webapp/node_modules/qs/.eslintrc +0 -38
  629. gaia/eval/webapp/node_modules/qs/.github/FUNDING.yml +0 -12
  630. gaia/eval/webapp/node_modules/qs/.nycrc +0 -13
  631. gaia/eval/webapp/node_modules/qs/CHANGELOG.md +0 -600
  632. gaia/eval/webapp/node_modules/qs/LICENSE.md +0 -29
  633. gaia/eval/webapp/node_modules/qs/README.md +0 -709
  634. gaia/eval/webapp/node_modules/qs/dist/qs.js +0 -90
  635. gaia/eval/webapp/node_modules/qs/lib/formats.js +0 -23
  636. gaia/eval/webapp/node_modules/qs/lib/index.js +0 -11
  637. gaia/eval/webapp/node_modules/qs/lib/parse.js +0 -296
  638. gaia/eval/webapp/node_modules/qs/lib/stringify.js +0 -351
  639. gaia/eval/webapp/node_modules/qs/lib/utils.js +0 -265
  640. gaia/eval/webapp/node_modules/qs/package.json +0 -91
  641. gaia/eval/webapp/node_modules/qs/test/empty-keys-cases.js +0 -267
  642. gaia/eval/webapp/node_modules/qs/test/parse.js +0 -1170
  643. gaia/eval/webapp/node_modules/qs/test/stringify.js +0 -1298
  644. gaia/eval/webapp/node_modules/qs/test/utils.js +0 -136
  645. gaia/eval/webapp/node_modules/range-parser/HISTORY.md +0 -56
  646. gaia/eval/webapp/node_modules/range-parser/LICENSE +0 -23
  647. gaia/eval/webapp/node_modules/range-parser/README.md +0 -84
  648. gaia/eval/webapp/node_modules/range-parser/index.js +0 -162
  649. gaia/eval/webapp/node_modules/range-parser/package.json +0 -44
  650. gaia/eval/webapp/node_modules/raw-body/HISTORY.md +0 -308
  651. gaia/eval/webapp/node_modules/raw-body/LICENSE +0 -22
  652. gaia/eval/webapp/node_modules/raw-body/README.md +0 -223
  653. gaia/eval/webapp/node_modules/raw-body/SECURITY.md +0 -24
  654. gaia/eval/webapp/node_modules/raw-body/index.d.ts +0 -87
  655. gaia/eval/webapp/node_modules/raw-body/index.js +0 -336
  656. gaia/eval/webapp/node_modules/raw-body/package.json +0 -49
  657. gaia/eval/webapp/node_modules/safe-buffer/LICENSE +0 -21
  658. gaia/eval/webapp/node_modules/safe-buffer/README.md +0 -584
  659. gaia/eval/webapp/node_modules/safe-buffer/index.d.ts +0 -187
  660. gaia/eval/webapp/node_modules/safe-buffer/index.js +0 -65
  661. gaia/eval/webapp/node_modules/safe-buffer/package.json +0 -51
  662. gaia/eval/webapp/node_modules/safer-buffer/LICENSE +0 -21
  663. gaia/eval/webapp/node_modules/safer-buffer/Porting-Buffer.md +0 -268
  664. gaia/eval/webapp/node_modules/safer-buffer/Readme.md +0 -156
  665. gaia/eval/webapp/node_modules/safer-buffer/dangerous.js +0 -58
  666. gaia/eval/webapp/node_modules/safer-buffer/package.json +0 -34
  667. gaia/eval/webapp/node_modules/safer-buffer/safer.js +0 -77
  668. gaia/eval/webapp/node_modules/safer-buffer/tests.js +0 -406
  669. gaia/eval/webapp/node_modules/send/HISTORY.md +0 -526
  670. gaia/eval/webapp/node_modules/send/LICENSE +0 -23
  671. gaia/eval/webapp/node_modules/send/README.md +0 -327
  672. gaia/eval/webapp/node_modules/send/SECURITY.md +0 -24
  673. gaia/eval/webapp/node_modules/send/index.js +0 -1142
  674. gaia/eval/webapp/node_modules/send/node_modules/encodeurl/HISTORY.md +0 -14
  675. gaia/eval/webapp/node_modules/send/node_modules/encodeurl/LICENSE +0 -22
  676. gaia/eval/webapp/node_modules/send/node_modules/encodeurl/README.md +0 -128
  677. gaia/eval/webapp/node_modules/send/node_modules/encodeurl/index.js +0 -60
  678. gaia/eval/webapp/node_modules/send/node_modules/encodeurl/package.json +0 -40
  679. gaia/eval/webapp/node_modules/send/node_modules/ms/index.js +0 -162
  680. gaia/eval/webapp/node_modules/send/node_modules/ms/license.md +0 -21
  681. gaia/eval/webapp/node_modules/send/node_modules/ms/package.json +0 -38
  682. gaia/eval/webapp/node_modules/send/node_modules/ms/readme.md +0 -59
  683. gaia/eval/webapp/node_modules/send/package.json +0 -62
  684. gaia/eval/webapp/node_modules/serve-static/HISTORY.md +0 -487
  685. gaia/eval/webapp/node_modules/serve-static/LICENSE +0 -25
  686. gaia/eval/webapp/node_modules/serve-static/README.md +0 -257
  687. gaia/eval/webapp/node_modules/serve-static/index.js +0 -209
  688. gaia/eval/webapp/node_modules/serve-static/package.json +0 -42
  689. gaia/eval/webapp/node_modules/setprototypeof/LICENSE +0 -13
  690. gaia/eval/webapp/node_modules/setprototypeof/README.md +0 -31
  691. gaia/eval/webapp/node_modules/setprototypeof/index.d.ts +0 -2
  692. gaia/eval/webapp/node_modules/setprototypeof/index.js +0 -17
  693. gaia/eval/webapp/node_modules/setprototypeof/package.json +0 -38
  694. gaia/eval/webapp/node_modules/setprototypeof/test/index.js +0 -24
  695. gaia/eval/webapp/node_modules/side-channel/.editorconfig +0 -9
  696. gaia/eval/webapp/node_modules/side-channel/.eslintrc +0 -12
  697. gaia/eval/webapp/node_modules/side-channel/.github/FUNDING.yml +0 -12
  698. gaia/eval/webapp/node_modules/side-channel/.nycrc +0 -13
  699. gaia/eval/webapp/node_modules/side-channel/CHANGELOG.md +0 -110
  700. gaia/eval/webapp/node_modules/side-channel/LICENSE +0 -21
  701. gaia/eval/webapp/node_modules/side-channel/README.md +0 -61
  702. gaia/eval/webapp/node_modules/side-channel/index.d.ts +0 -14
  703. gaia/eval/webapp/node_modules/side-channel/index.js +0 -43
  704. gaia/eval/webapp/node_modules/side-channel/package.json +0 -85
  705. gaia/eval/webapp/node_modules/side-channel/test/index.js +0 -104
  706. gaia/eval/webapp/node_modules/side-channel/tsconfig.json +0 -9
  707. gaia/eval/webapp/node_modules/side-channel-list/.editorconfig +0 -9
  708. gaia/eval/webapp/node_modules/side-channel-list/.eslintrc +0 -11
  709. gaia/eval/webapp/node_modules/side-channel-list/.github/FUNDING.yml +0 -12
  710. gaia/eval/webapp/node_modules/side-channel-list/.nycrc +0 -13
  711. gaia/eval/webapp/node_modules/side-channel-list/CHANGELOG.md +0 -15
  712. gaia/eval/webapp/node_modules/side-channel-list/LICENSE +0 -21
  713. gaia/eval/webapp/node_modules/side-channel-list/README.md +0 -62
  714. gaia/eval/webapp/node_modules/side-channel-list/index.d.ts +0 -13
  715. gaia/eval/webapp/node_modules/side-channel-list/index.js +0 -113
  716. gaia/eval/webapp/node_modules/side-channel-list/list.d.ts +0 -14
  717. gaia/eval/webapp/node_modules/side-channel-list/package.json +0 -77
  718. gaia/eval/webapp/node_modules/side-channel-list/test/index.js +0 -104
  719. gaia/eval/webapp/node_modules/side-channel-list/tsconfig.json +0 -9
  720. gaia/eval/webapp/node_modules/side-channel-map/.editorconfig +0 -9
  721. gaia/eval/webapp/node_modules/side-channel-map/.eslintrc +0 -11
  722. gaia/eval/webapp/node_modules/side-channel-map/.github/FUNDING.yml +0 -12
  723. gaia/eval/webapp/node_modules/side-channel-map/.nycrc +0 -13
  724. gaia/eval/webapp/node_modules/side-channel-map/CHANGELOG.md +0 -22
  725. gaia/eval/webapp/node_modules/side-channel-map/LICENSE +0 -21
  726. gaia/eval/webapp/node_modules/side-channel-map/README.md +0 -62
  727. gaia/eval/webapp/node_modules/side-channel-map/index.d.ts +0 -15
  728. gaia/eval/webapp/node_modules/side-channel-map/index.js +0 -68
  729. gaia/eval/webapp/node_modules/side-channel-map/package.json +0 -80
  730. gaia/eval/webapp/node_modules/side-channel-map/test/index.js +0 -114
  731. gaia/eval/webapp/node_modules/side-channel-map/tsconfig.json +0 -9
  732. gaia/eval/webapp/node_modules/side-channel-weakmap/.editorconfig +0 -9
  733. gaia/eval/webapp/node_modules/side-channel-weakmap/.eslintrc +0 -12
  734. gaia/eval/webapp/node_modules/side-channel-weakmap/.github/FUNDING.yml +0 -12
  735. gaia/eval/webapp/node_modules/side-channel-weakmap/.nycrc +0 -13
  736. gaia/eval/webapp/node_modules/side-channel-weakmap/CHANGELOG.md +0 -28
  737. gaia/eval/webapp/node_modules/side-channel-weakmap/LICENSE +0 -21
  738. gaia/eval/webapp/node_modules/side-channel-weakmap/README.md +0 -62
  739. gaia/eval/webapp/node_modules/side-channel-weakmap/index.d.ts +0 -15
  740. gaia/eval/webapp/node_modules/side-channel-weakmap/index.js +0 -84
  741. gaia/eval/webapp/node_modules/side-channel-weakmap/package.json +0 -87
  742. gaia/eval/webapp/node_modules/side-channel-weakmap/test/index.js +0 -114
  743. gaia/eval/webapp/node_modules/side-channel-weakmap/tsconfig.json +0 -9
  744. gaia/eval/webapp/node_modules/statuses/HISTORY.md +0 -82
  745. gaia/eval/webapp/node_modules/statuses/LICENSE +0 -23
  746. gaia/eval/webapp/node_modules/statuses/README.md +0 -136
  747. gaia/eval/webapp/node_modules/statuses/codes.json +0 -65
  748. gaia/eval/webapp/node_modules/statuses/index.js +0 -146
  749. gaia/eval/webapp/node_modules/statuses/package.json +0 -49
  750. gaia/eval/webapp/node_modules/toidentifier/HISTORY.md +0 -9
  751. gaia/eval/webapp/node_modules/toidentifier/LICENSE +0 -21
  752. gaia/eval/webapp/node_modules/toidentifier/README.md +0 -61
  753. gaia/eval/webapp/node_modules/toidentifier/index.js +0 -32
  754. gaia/eval/webapp/node_modules/toidentifier/package.json +0 -38
  755. gaia/eval/webapp/node_modules/type-is/HISTORY.md +0 -259
  756. gaia/eval/webapp/node_modules/type-is/LICENSE +0 -23
  757. gaia/eval/webapp/node_modules/type-is/README.md +0 -170
  758. gaia/eval/webapp/node_modules/type-is/index.js +0 -266
  759. gaia/eval/webapp/node_modules/type-is/package.json +0 -45
  760. gaia/eval/webapp/node_modules/unpipe/HISTORY.md +0 -4
  761. gaia/eval/webapp/node_modules/unpipe/LICENSE +0 -22
  762. gaia/eval/webapp/node_modules/unpipe/README.md +0 -43
  763. gaia/eval/webapp/node_modules/unpipe/index.js +0 -69
  764. gaia/eval/webapp/node_modules/unpipe/package.json +0 -27
  765. gaia/eval/webapp/node_modules/util/LICENSE +0 -18
  766. gaia/eval/webapp/node_modules/util/README.md +0 -15
  767. gaia/eval/webapp/node_modules/util/node_modules/inherits/LICENSE +0 -16
  768. gaia/eval/webapp/node_modules/util/node_modules/inherits/README.md +0 -42
  769. gaia/eval/webapp/node_modules/util/node_modules/inherits/inherits.js +0 -7
  770. gaia/eval/webapp/node_modules/util/node_modules/inherits/inherits_browser.js +0 -23
  771. gaia/eval/webapp/node_modules/util/node_modules/inherits/package.json +0 -29
  772. gaia/eval/webapp/node_modules/util/package.json +0 -35
  773. gaia/eval/webapp/node_modules/util/support/isBuffer.js +0 -3
  774. gaia/eval/webapp/node_modules/util/support/isBufferBrowser.js +0 -6
  775. gaia/eval/webapp/node_modules/util/util.js +0 -586
  776. gaia/eval/webapp/node_modules/utils-merge/.npmignore +0 -9
  777. gaia/eval/webapp/node_modules/utils-merge/LICENSE +0 -20
  778. gaia/eval/webapp/node_modules/utils-merge/README.md +0 -34
  779. gaia/eval/webapp/node_modules/utils-merge/index.js +0 -23
  780. gaia/eval/webapp/node_modules/utils-merge/package.json +0 -40
  781. gaia/eval/webapp/node_modules/vary/HISTORY.md +0 -39
  782. gaia/eval/webapp/node_modules/vary/LICENSE +0 -22
  783. gaia/eval/webapp/node_modules/vary/README.md +0 -101
  784. gaia/eval/webapp/node_modules/vary/index.js +0 -149
  785. gaia/eval/webapp/node_modules/vary/package.json +0 -43
  786. {amd_gaia-0.14.2.dist-info → amd_gaia-0.14.3.dist-info}/WHEEL +0 -0
  787. {amd_gaia-0.14.2.dist-info → amd_gaia-0.14.3.dist-info}/licenses/LICENSE.md +0 -0
  788. {amd_gaia-0.14.2.dist-info → amd_gaia-0.14.3.dist-info}/top_level.txt +0 -0
gaia/agents/emr/cli.py ADDED
@@ -0,0 +1,1322 @@
1
+ # Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ """CLI for Medical Intake Agent."""
5
+
6
+ import argparse
7
+ import logging
8
+ import sys
9
+ from pathlib import Path
10
+
11
+ from rich.console import Console
12
+ from rich.panel import Panel
13
+ from rich.table import Table
14
+
15
+ from gaia.agents.emr.agent import MedicalIntakeAgent
16
+
17
+ logger = logging.getLogger(__name__)
18
+ console = Console()
19
+
20
+
21
+ def _print_header(watch_dir: str, db_path: str):
22
+ """Print a styled header for the CLI."""
23
+ console.print()
24
+ console.print(
25
+ Panel.fit(
26
+ "[bold cyan]Medical Intake Agent[/bold cyan]\n"
27
+ "[dim]Automatic Patient Form Processing[/dim]",
28
+ border_style="cyan",
29
+ )
30
+ )
31
+
32
+ # Status table
33
+ table = Table(show_header=False, box=None, padding=(0, 2))
34
+ table.add_column(style="dim")
35
+ table.add_column()
36
+ table.add_row("📁 Watch folder:", watch_dir)
37
+ table.add_row("💾 Database:", db_path)
38
+ console.print(table)
39
+ console.print()
40
+
41
+ # Commands help
42
+ console.print("[dim]Commands:[/dim]")
43
+ console.print(" [cyan]stats[/cyan] Show processing statistics")
44
+ console.print(" [cyan]quit[/cyan] Stop and exit")
45
+ console.print(" [dim]Or type questions about patients[/dim]")
46
+ console.print()
47
+
48
+
49
+ def _print_prompt():
50
+ """Print the input prompt with visual separators."""
51
+ console.print("─" * 80, style="dim")
52
+ console.print("> ", end="", style="bold green")
53
+ sys.stdout.flush() # Ensure prompt is displayed before input() blocks
54
+
55
+
56
+ def cmd_watch(args):
57
+ """Start watching directory for intake forms."""
58
+ _print_header(args.watch_dir, args.db)
59
+
60
+ console.print("[dim]Starting agent...[/dim]")
61
+
62
+ agent = MedicalIntakeAgent(
63
+ watch_dir=args.watch_dir,
64
+ db_path=args.db,
65
+ vlm_model=args.vlm_model,
66
+ )
67
+
68
+ console.print("[green]✓ Ready![/green] Drop intake forms to process them.\n")
69
+ sys.stdout.flush() # Ensure Ready message appears before prompt
70
+
71
+ try:
72
+ while True:
73
+ try:
74
+ _print_prompt()
75
+ user_input = input().strip()
76
+ except EOFError:
77
+ break
78
+
79
+ if not user_input:
80
+ continue
81
+
82
+ if user_input.lower() in ("quit", "exit", "q"):
83
+ break
84
+
85
+ console.print("─" * 80, style="dim")
86
+
87
+ if user_input.lower() == "stats":
88
+ cmd_stats_inline(agent)
89
+ else:
90
+ # Process the query
91
+ agent.process_query(user_input)
92
+ print()
93
+
94
+ except KeyboardInterrupt:
95
+ print()
96
+ finally:
97
+ console.print("[dim]Stopping agent...[/dim]")
98
+ agent.stop()
99
+ console.print("[green]✓ Stopped[/green]")
100
+
101
+
102
+ def cmd_stats_inline(agent):
103
+ """Show stats inline during watch mode."""
104
+ try:
105
+ stats = agent.get_stats()
106
+ _print_stats_table(stats)
107
+ except Exception as e:
108
+ console.print(f"[red]Error getting stats: {e}[/red]")
109
+
110
+
111
+ def cmd_process(args):
112
+ """Process a single intake form file."""
113
+ if not Path(args.file).exists():
114
+ console.print(f"[red]Error: File not found: {args.file}[/red]")
115
+ return 1
116
+
117
+ console.print(f"[dim]Processing: {args.file}[/dim]")
118
+
119
+ agent = MedicalIntakeAgent(
120
+ watch_dir=args.watch_dir,
121
+ db_path=args.db,
122
+ vlm_model=args.vlm_model,
123
+ auto_start_watching=False,
124
+ )
125
+
126
+ try:
127
+ # pylint: disable=protected-access
128
+ patient_data = agent._process_intake_form(args.file)
129
+
130
+ if patient_data:
131
+ # Agent already prints success and patient details
132
+ return 0
133
+ else:
134
+ console.print(f"[red]Failed to process: {args.file}[/red]")
135
+ return 1
136
+
137
+ finally:
138
+ agent.stop()
139
+
140
+
141
+ def cmd_query(args):
142
+ """Query patient database."""
143
+ agent = MedicalIntakeAgent(
144
+ watch_dir=args.watch_dir,
145
+ db_path=args.db,
146
+ auto_start_watching=False,
147
+ )
148
+
149
+ try:
150
+ agent.process_query(args.question)
151
+ return 0
152
+ finally:
153
+ agent.stop()
154
+
155
+
156
+ def _print_stats_table(stats: dict):
157
+ """Print statistics using Rich formatting."""
158
+ console.print()
159
+
160
+ # Time savings highlight
161
+ time_table = Table(show_header=False, box=None, padding=(0, 1))
162
+ time_table.add_column(style="bold green")
163
+ time_table.add_column(style="green")
164
+ time_table.add_row(
165
+ f"⏱️ {stats['time_saved_minutes']} min saved",
166
+ f"({stats['time_saved_percent']} faster)",
167
+ )
168
+ console.print(Panel(time_table, title="Time Savings", border_style="green"))
169
+
170
+ # Main stats grid
171
+ grid = Table.grid(expand=True, padding=(0, 2))
172
+ grid.add_column()
173
+ grid.add_column()
174
+
175
+ # Patients table
176
+ patients = Table(show_header=False, box=None)
177
+ patients.add_column(style="dim")
178
+ patients.add_column(style="bold")
179
+ patients.add_row("Total", str(stats["total_patients"]))
180
+ patients.add_row("New", str(stats["new_patients"]))
181
+ patients.add_row("Returning", str(stats["returning_patients"]))
182
+ patients.add_row("Today", str(stats["processed_today"]))
183
+
184
+ # Processing table
185
+ processing = Table(show_header=False, box=None)
186
+ processing.add_column(style="dim")
187
+ processing.add_column(style="bold")
188
+ processing.add_row("Processed", str(stats["files_processed"]))
189
+ processing.add_row("Success", str(stats["extraction_success"]))
190
+ processing.add_row("Failed", str(stats["extraction_failed"]))
191
+ processing.add_row("Rate", stats["success_rate"])
192
+
193
+ grid.add_row(
194
+ Panel(patients, title="👥 Patients", border_style="cyan"),
195
+ Panel(processing, title="📋 Processing", border_style="cyan"),
196
+ )
197
+ console.print(grid)
198
+
199
+ # Alerts (if any)
200
+ if stats.get("unacknowledged_alerts", 0) > 0:
201
+ console.print(
202
+ f"[bold red]🚨 {stats['unacknowledged_alerts']} unacknowledged alert(s)[/bold red]"
203
+ )
204
+ console.print()
205
+
206
+
207
+ def cmd_stats(args):
208
+ """Show processing statistics."""
209
+ agent = MedicalIntakeAgent(
210
+ watch_dir=args.watch_dir,
211
+ db_path=args.db,
212
+ auto_start_watching=False,
213
+ silent_mode=True,
214
+ )
215
+
216
+ try:
217
+ stats = agent.get_stats()
218
+ _print_stats_table(stats)
219
+ return 0
220
+ finally:
221
+ agent.stop()
222
+
223
+
224
+ def cmd_reset(args):
225
+ """Reset by deleting the database file."""
226
+ import os
227
+
228
+ from rich.prompt import Confirm
229
+
230
+ db_path = Path(args.db)
231
+
232
+ # Check if database exists
233
+ if not db_path.exists():
234
+ console.print("[dim]Database file does not exist. Nothing to reset.[/dim]")
235
+ return 0
236
+
237
+ # Get stats before deletion to show what will be deleted
238
+ total_patients = 0
239
+ agent = None
240
+ try:
241
+ agent = MedicalIntakeAgent(
242
+ watch_dir=args.watch_dir,
243
+ db_path=args.db,
244
+ auto_start_watching=False,
245
+ silent_mode=True,
246
+ )
247
+ stats = agent.get_stats()
248
+ total_patients = stats.get("total_patients", 0)
249
+ except Exception:
250
+ pass # If we can't read stats, proceed anyway
251
+ finally:
252
+ if agent:
253
+ agent.stop()
254
+
255
+ # Confirmation prompt unless --force is used
256
+ if not args.force:
257
+ console.print()
258
+ console.print(
259
+ "[bold yellow]⚠️ WARNING:[/bold yellow] This will permanently delete:"
260
+ )
261
+ if total_patients > 0:
262
+ console.print(f" • {total_patients} patient record(s)")
263
+ console.print(" • All associated alerts and intake sessions")
264
+ console.print(f" • Database file: {db_path}")
265
+ console.print()
266
+
267
+ if not Confirm.ask("[bold red]Are you sure you want to continue?[/bold red]"):
268
+ console.print("[dim]Cancelled.[/dim]")
269
+ return 0
270
+
271
+ # Delete the database file
272
+ try:
273
+ os.remove(db_path)
274
+ console.print()
275
+ console.print("[bold green]✓ Database deleted successfully[/bold green]")
276
+ console.print(f" Removed: {db_path}")
277
+ console.print()
278
+ console.print(
279
+ "[dim]A fresh database will be created when you next run the agent.[/dim]"
280
+ )
281
+ return 0
282
+ except Exception as e:
283
+ console.print(f"[red]Error deleting database: {e}[/red]")
284
+ return 1
285
+
286
+
287
+ def cmd_init(args):
288
+ """Initialize EMR agent by downloading and loading required models."""
289
+ import time
290
+
291
+ from gaia.llm.lemonade_client import LemonadeClient
292
+
293
+ console.print()
294
+ console.print(
295
+ Panel.fit(
296
+ "[bold cyan]EMR Agent Setup[/bold cyan]\n"
297
+ "[dim]Downloading and loading required models[/dim]",
298
+ border_style="cyan",
299
+ )
300
+ )
301
+ console.print()
302
+
303
+ # Required models for EMR agent
304
+ vlm_model = args.vlm_model # Default: Qwen3-VL-4B-Instruct-GGUF
305
+ llm_model = "Qwen3-Coder-30B-A3B-Instruct-GGUF" # For chat/query processing
306
+ embed_model = "nomic-embed-text-v2-moe-GGUF" # For similarity search
307
+
308
+ REQUIRED_CONTEXT_SIZE = 32768
309
+
310
+ # Step 1: Check Lemonade server and context size
311
+ console.print("[bold]Step 1:[/bold] Checking Lemonade server...")
312
+ try:
313
+ client = LemonadeClient(model=vlm_model)
314
+ health = client.health_check()
315
+ if health.get("status") == "ok":
316
+ console.print(" [green]✓[/green] Lemonade server is running")
317
+
318
+ # Check context size
319
+ context_size = health.get("context_size", 0)
320
+ if context_size >= REQUIRED_CONTEXT_SIZE:
321
+ console.print(
322
+ f" [green]✓[/green] Context size: [cyan]{context_size:,}[/cyan] tokens (recommended: {REQUIRED_CONTEXT_SIZE:,})"
323
+ )
324
+ elif context_size > 0:
325
+ console.print(
326
+ f" [yellow]⚠[/yellow] Context size: [yellow]{context_size:,}[/yellow] tokens"
327
+ )
328
+ console.print(
329
+ f" [yellow]Warning:[/yellow] Context size should be at least [cyan]{REQUIRED_CONTEXT_SIZE:,}[/cyan] for reliable form processing"
330
+ )
331
+ console.print(
332
+ " [dim]To fix: Right-click Lemonade tray → Settings → Context Size → 32768[/dim]"
333
+ )
334
+ else:
335
+ console.print(
336
+ " [dim]Context size: Not reported (will check after model load)[/dim]"
337
+ )
338
+ else:
339
+ console.print(" [red]✗[/red] Lemonade server not responding")
340
+ console.print()
341
+ console.print("[yellow]Please start Lemonade server first:[/yellow]")
342
+ console.print(" 1. Open Lemonade from the system tray")
343
+ console.print(" 2. Or run: [cyan]lemonade-server[/cyan]")
344
+ return 1
345
+ except Exception as e:
346
+ console.print(f" [red]✗[/red] Cannot connect to Lemonade: {e}")
347
+ console.print()
348
+ console.print("[yellow]Please start Lemonade server first:[/yellow]")
349
+ console.print(" 1. Open Lemonade from the system tray")
350
+ console.print(" 2. Or run: [cyan]lemonade-server[/cyan]")
351
+ return 1
352
+
353
+ # Step 2: Check required models
354
+ console.print()
355
+ console.print("[bold]Step 2:[/bold] Checking required models...")
356
+
357
+ try:
358
+ models_response = client.list_models()
359
+ available_models = models_response.get("data", [])
360
+ downloaded_model_ids = [m.get("id", "") for m in available_models]
361
+
362
+ # Check each required model
363
+ required_models = [
364
+ ("VLM", vlm_model, "Form extraction"),
365
+ ("LLM", llm_model, "Chat/query processing"),
366
+ ("Embedding", embed_model, "Similarity search"),
367
+ ]
368
+
369
+ models_to_download = []
370
+ for model_type, model_name, _purpose in required_models:
371
+ is_downloaded = model_name in downloaded_model_ids
372
+ if is_downloaded:
373
+ console.print(
374
+ f" [green]✓[/green] {model_type}: [cyan]{model_name}[/cyan]"
375
+ )
376
+ else:
377
+ console.print(
378
+ f" [dim]○[/dim] {model_type}: [cyan]{model_name}[/cyan] [dim](not downloaded)[/dim]"
379
+ )
380
+ models_to_download.append((model_type, model_name))
381
+
382
+ if models_to_download:
383
+ console.print()
384
+ console.print(
385
+ f" [yellow]⚠️ {len(models_to_download)} model(s) need to be downloaded[/yellow]"
386
+ )
387
+
388
+ except Exception as e:
389
+ console.print(f" [red]✗[/red] Failed to check models: {e}")
390
+ return 1
391
+
392
+ # Step 3: Load all required models
393
+ console.print()
394
+ console.print("[bold]Step 3:[/bold] Loading required models...")
395
+ console.print(" [dim]Loading models into memory for fast inference...[/dim]")
396
+ console.print()
397
+
398
+ models_loaded = {}
399
+
400
+ # Load VLM model first (most important for form processing)
401
+ for model_type, model_name in [
402
+ ("VLM", vlm_model),
403
+ ("LLM", llm_model),
404
+ ("Embedding", embed_model),
405
+ ]:
406
+ console.print(f" Loading {model_type}: [cyan]{model_name}[/cyan]...")
407
+
408
+ try:
409
+ start_time = time.time()
410
+ client.load_model(model_name, timeout=1800, auto_download=True)
411
+ elapsed = time.time() - start_time
412
+ models_loaded[model_type] = True
413
+ console.print(f" [green]✓[/green] {model_type} loaded ({elapsed:.1f}s)")
414
+ except Exception as e:
415
+ error_msg = str(e)
416
+ models_loaded[model_type] = False
417
+
418
+ # Check for common errors
419
+ if "being used by another process" in error_msg:
420
+ console.print(
421
+ f" [yellow]![/yellow] {model_type}: File locked, try again later"
422
+ )
423
+ elif (
424
+ "not found" in error_msg.lower()
425
+ or "does not exist" in error_msg.lower()
426
+ ):
427
+ console.print(
428
+ f" [yellow]![/yellow] {model_type}: Model not available in registry"
429
+ )
430
+ else:
431
+ console.print(f" [yellow]![/yellow] {model_type}: {error_msg[:50]}...")
432
+
433
+ # Check if critical models loaded
434
+ if not models_loaded.get("VLM"):
435
+ console.print()
436
+ console.print(
437
+ "[red]✗ VLM model failed to load - form processing will not work[/red]"
438
+ )
439
+ return 1
440
+
441
+ # Clear VLM context to ensure fresh memory allocation
442
+ console.print()
443
+ console.print(" [dim]Clearing VLM context for clean memory...[/dim]")
444
+ try:
445
+ client.unload_model()
446
+ client.load_model(vlm_model, timeout=300, auto_download=True)
447
+ console.print(" [green]✓[/green] VLM context cleared")
448
+ except Exception as e:
449
+ console.print(f" [dim]Context clear skipped: {e}[/dim]")
450
+
451
+ # Step 4: Verify models and check context size
452
+ console.print()
453
+ console.print("[bold]Step 4:[/bold] Verifying models are ready...")
454
+
455
+ vlm_ready = False
456
+ llm_ready = False
457
+ embed_ready = False
458
+ final_context_size = 0
459
+
460
+ try:
461
+ # Check health for context size
462
+ health = client.health_check()
463
+ final_context_size = health.get("context_size", 0)
464
+
465
+ # Check each model
466
+ vlm_ready = client.check_model_loaded(vlm_model)
467
+ llm_ready = client.check_model_loaded(llm_model)
468
+ embed_ready = client.check_model_loaded(embed_model)
469
+
470
+ if vlm_ready:
471
+ console.print(" [green]✓[/green] VLM: Ready for form extraction")
472
+ else:
473
+ console.print(" [yellow]![/yellow] VLM: Will load on first use")
474
+
475
+ if llm_ready:
476
+ console.print(" [green]✓[/green] LLM: Ready for chat queries")
477
+ else:
478
+ console.print(" [dim]○[/dim] LLM: Will load on first use")
479
+
480
+ if embed_ready:
481
+ console.print(" [green]✓[/green] Embedding: Ready for search")
482
+ else:
483
+ console.print(" [dim]○[/dim] Embedding: Will load on first use")
484
+
485
+ # Report context size
486
+ if final_context_size >= REQUIRED_CONTEXT_SIZE:
487
+ console.print(
488
+ f" [green]✓[/green] Context size: [cyan]{final_context_size:,}[/cyan] tokens"
489
+ )
490
+ elif final_context_size > 0:
491
+ console.print(
492
+ f" [yellow]⚠[/yellow] Context size: [yellow]{final_context_size:,}[/yellow] tokens (need {REQUIRED_CONTEXT_SIZE:,})"
493
+ )
494
+
495
+ except Exception as e:
496
+ console.print(f" [yellow]![/yellow] Could not verify: {e}")
497
+
498
+ # Step 5: Show all downloaded and loaded models
499
+ console.print()
500
+ console.print("[bold]Step 5:[/bold] Model inventory...")
501
+
502
+ try:
503
+ models_response = client.list_models()
504
+ all_models = models_response.get("data", [])
505
+
506
+ # Categorize models
507
+ vlm_models = []
508
+ llm_models = []
509
+ embed_models = []
510
+
511
+ for m in all_models:
512
+ model_id = m.get("id", "")
513
+ model_lower = model_id.lower()
514
+
515
+ if "vl" in model_lower or "vision" in model_lower or "vlm" in model_lower:
516
+ vlm_models.append(model_id)
517
+ elif (
518
+ "embed" in model_lower
519
+ or "bge" in model_lower
520
+ or "e5" in model_lower
521
+ or "nomic" in model_lower
522
+ ):
523
+ embed_models.append(model_id)
524
+ else:
525
+ llm_models.append(model_id)
526
+
527
+ # Show categorized models
528
+ if vlm_models:
529
+ console.print(
530
+ f" [cyan]VLM Models:[/cyan] {', '.join(vlm_models[:3])}"
531
+ + (f" (+{len(vlm_models)-3} more)" if len(vlm_models) > 3 else "")
532
+ )
533
+ if llm_models:
534
+ console.print(
535
+ f" [cyan]LLM Models:[/cyan] {', '.join(llm_models[:3])}"
536
+ + (f" (+{len(llm_models)-3} more)" if len(llm_models) > 3 else "")
537
+ )
538
+ if embed_models:
539
+ console.print(
540
+ f" [cyan]Embedding Models:[/cyan] {', '.join(embed_models[:3])}"
541
+ + (f" (+{len(embed_models)-3} more)" if len(embed_models) > 3 else "")
542
+ )
543
+
544
+ console.print(f" [dim]Total models available: {len(all_models)}[/dim]")
545
+
546
+ except Exception as e:
547
+ console.print(f" [dim]Could not list models: {e}[/dim]")
548
+
549
+ # Success summary
550
+ console.print()
551
+
552
+ # Build model status lines
553
+ model_status_lines = []
554
+
555
+ # VLM status
556
+ if vlm_ready:
557
+ model_status_lines.append(
558
+ f"[green]✓[/green] VLM: [cyan]{vlm_model}[/cyan] - Ready"
559
+ )
560
+ else:
561
+ model_status_lines.append(
562
+ f"[yellow]![/yellow] VLM: [cyan]{vlm_model}[/cyan] - Will load on first use"
563
+ )
564
+
565
+ # LLM status
566
+ if llm_ready:
567
+ model_status_lines.append(
568
+ f"[green]✓[/green] LLM: [cyan]{llm_model}[/cyan] - Ready"
569
+ )
570
+ else:
571
+ model_status_lines.append(
572
+ f"[dim]○[/dim] LLM: [cyan]{llm_model}[/cyan] - Will load on first use"
573
+ )
574
+
575
+ # Embedding status
576
+ if embed_ready:
577
+ model_status_lines.append(
578
+ f"[green]✓[/green] Embedding: [cyan]{embed_model}[/cyan] - Ready"
579
+ )
580
+ else:
581
+ model_status_lines.append(
582
+ f"[dim]○[/dim] Embedding: [cyan]{embed_model}[/cyan] - Will load on first use"
583
+ )
584
+
585
+ # Context size status
586
+ if final_context_size >= REQUIRED_CONTEXT_SIZE:
587
+ model_status_lines.append(
588
+ f"[green]✓[/green] Context size: {final_context_size:,} tokens"
589
+ )
590
+ elif final_context_size > 0:
591
+ model_status_lines.append(
592
+ f"[yellow]⚠[/yellow] Context size: {final_context_size:,} tokens (need {REQUIRED_CONTEXT_SIZE:,})"
593
+ )
594
+
595
+ # Count ready models
596
+ ready_count = sum([vlm_ready, llm_ready, embed_ready])
597
+
598
+ console.print(
599
+ Panel.fit(
600
+ f"[bold green]✓ EMR Agent initialized ({ready_count}/3 models ready)[/bold green]\n\n"
601
+ + "\n".join(model_status_lines)
602
+ + "\n\n"
603
+ "[dim]You can now run:[/dim]\n"
604
+ " [cyan]gaia-emr dashboard[/cyan] - Start the web dashboard\n"
605
+ " [cyan]gaia-emr watch[/cyan] - Watch folder for intake forms\n"
606
+ " [cyan]gaia-emr process <file>[/cyan] - Process a single file",
607
+ border_style="green",
608
+ )
609
+ )
610
+ console.print()
611
+
612
+ # Context size warning if needed
613
+ if 0 < final_context_size < REQUIRED_CONTEXT_SIZE:
614
+ console.print(
615
+ Panel.fit(
616
+ "[yellow]⚠️ Context Size Warning[/yellow]\n\n"
617
+ f"Current context size ({final_context_size:,}) may be too small for processing intake forms.\n"
618
+ "Large images can require 4,000-8,000+ tokens.\n\n"
619
+ "[bold]To fix:[/bold]\n"
620
+ " 1. Right-click Lemonade tray icon → Settings\n"
621
+ " 2. Set Context Size to [cyan]32768[/cyan]\n"
622
+ " 3. Click Apply and restart the model",
623
+ border_style="yellow",
624
+ )
625
+ )
626
+ console.print()
627
+
628
+ return 0
629
+
630
+
631
+ def cmd_test(args):
632
+ """Test VLM extraction pipeline on a single file."""
633
+ import io
634
+ import json
635
+ import time
636
+
637
+ from PIL import Image
638
+
639
+ from gaia.llm.vlm_client import VLMClient
640
+
641
+ file_path = Path(args.file)
642
+ if not file_path.exists():
643
+ console.print(f"[red]Error: File not found: {file_path}[/red]")
644
+ return 1
645
+
646
+ console.print()
647
+ console.print(
648
+ Panel.fit(
649
+ "[bold cyan]EMR Agent - VLM Pipeline Test[/bold cyan]\n"
650
+ f"[dim]Testing extraction on: {file_path.name}[/dim]",
651
+ border_style="cyan",
652
+ )
653
+ )
654
+ console.print()
655
+
656
+ # Step 1: Read and analyze file
657
+ console.print("[bold]Step 1:[/bold] Reading file...")
658
+ try:
659
+ raw_bytes = file_path.read_bytes()
660
+ file_size_kb = len(raw_bytes) / 1024
661
+ console.print(f" File size: {file_size_kb:.1f} KB")
662
+
663
+ # Get image dimensions
664
+ img = Image.open(io.BytesIO(raw_bytes))
665
+ orig_width, orig_height = img.size
666
+ console.print(f" Dimensions: {orig_width}x{orig_height} pixels")
667
+
668
+ # Auto-rotate based on EXIF orientation
669
+ try:
670
+ from PIL import ExifTags
671
+
672
+ exif = img._getexif() # pylint: disable=protected-access
673
+ if exif:
674
+ for tag, value in exif.items():
675
+ if ExifTags.TAGS.get(tag) == "Orientation":
676
+ if value == 3:
677
+ img = img.rotate(180, expand=True)
678
+ console.print(" [dim]Auto-rotated 180°[/dim]")
679
+ elif value == 6:
680
+ img = img.rotate(270, expand=True)
681
+ console.print(" [dim]Auto-rotated 90° CW[/dim]")
682
+ elif value == 8:
683
+ img = img.rotate(90, expand=True)
684
+ console.print(" [dim]Auto-rotated 90° CCW[/dim]")
685
+ orig_width, orig_height = img.size
686
+ break
687
+ except Exception:
688
+ pass # No EXIF or rotation info
689
+ except Exception as e:
690
+ console.print(f" [red]✗[/red] Failed to read file: {e}")
691
+ return 1
692
+
693
+ # Step 2: Optimize image (same as agent)
694
+ console.print()
695
+ console.print("[bold]Step 2:[/bold] Optimizing image...")
696
+ max_dimension = args.max_dimension
697
+ jpeg_quality = args.jpeg_quality
698
+
699
+ try:
700
+ if orig_width > max_dimension or orig_height > max_dimension:
701
+ scale = min(max_dimension / orig_width, max_dimension / orig_height)
702
+ new_width = int(orig_width * scale)
703
+ new_height = int(orig_height * scale)
704
+ img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
705
+ console.print(
706
+ f" Resized: {orig_width}x{orig_height} → {new_width}x{new_height}"
707
+ )
708
+ else:
709
+ new_width, new_height = orig_width, orig_height
710
+ console.print(f" No resize needed (under {max_dimension}px)")
711
+
712
+ # Convert to RGB and JPEG
713
+ if img.mode in ("RGBA", "P"):
714
+ img = img.convert("RGB")
715
+
716
+ output = io.BytesIO()
717
+ img.save(output, format="JPEG", quality=jpeg_quality, optimize=True)
718
+ image_bytes = output.getvalue()
719
+
720
+ opt_size_kb = len(image_bytes) / 1024
721
+ reduction = (1 - opt_size_kb / file_size_kb) * 100
722
+ console.print(
723
+ f" Optimized: {file_size_kb:.0f}KB → {opt_size_kb:.0f}KB ({reduction:.0f}% smaller)"
724
+ )
725
+
726
+ # Estimate image tokens (rough: ~1 token per 14x14 pixel patch)
727
+ est_img_tokens = (new_width // 14) * (new_height // 14)
728
+ console.print(f" Est. image tokens: ~{est_img_tokens:,}")
729
+ except Exception as e:
730
+ console.print(f" [red]✗[/red] Failed to optimize: {e}")
731
+ return 1
732
+
733
+ # Step 3: Initialize VLM
734
+ console.print()
735
+ console.print("[bold]Step 3:[/bold] Initializing VLM...")
736
+ try:
737
+ vlm = VLMClient(vlm_model=args.vlm_model)
738
+
739
+ # Clear context if requested (unload and reload model)
740
+ if getattr(args, "clear_context", False):
741
+ console.print(" [dim]Clearing VLM context (unload + reload)...[/dim]")
742
+ try:
743
+ vlm.client.unload_model()
744
+ vlm.client.load_model(args.vlm_model, timeout=300, auto_download=True)
745
+ console.print(" [green]✓[/green] Context cleared")
746
+ except Exception as e:
747
+ console.print(f" [yellow]⚠[/yellow] Could not clear context: {e}")
748
+
749
+ console.print(f" [green]✓[/green] VLM ready: [cyan]{vlm.vlm_model}[/cyan]")
750
+ except Exception as e:
751
+ console.print(f" [red]✗[/red] Failed to initialize VLM: {e}")
752
+ return 1
753
+
754
+ # Step 4: Extract data with auto-retry on memory errors
755
+ console.print()
756
+ console.print("[bold]Step 4:[/bold] Extracting patient data...")
757
+
758
+ extraction_prompt = """Extract ALL patient information from this medical intake form.
759
+
760
+ Return a JSON object with these fields (use null for missing/unclear):
761
+ {
762
+ "form_date": "YYYY-MM-DD (date form was filled, today's date)",
763
+ "first_name": "...",
764
+ "last_name": "...",
765
+ "date_of_birth": "YYYY-MM-DD",
766
+ "age": "patient's age if listed",
767
+ "gender": "Male/Female/Other",
768
+ "preferred_pronouns": "he/him, she/her, they/them if listed",
769
+ "ssn": "XXX-XX-XXXX (social security number)",
770
+ "marital_status": "Single/Married/Divorced/Widowed/Partnered",
771
+ "spouse_name": "spouse's name if listed",
772
+ "phone": "home phone number",
773
+ "mobile_phone": "cell/mobile phone number",
774
+ "work_phone": "work phone number",
775
+ "email": "...",
776
+ "address": "street address",
777
+ "city": "...",
778
+ "state": "...",
779
+ "zip_code": "...",
780
+ "preferred_language": "English/Spanish/etc if listed",
781
+ "race": "if listed",
782
+ "ethnicity": "if listed",
783
+ "contact_preference": "preferred contact method if listed",
784
+ "emergency_contact_name": "name of emergency contact person",
785
+ "emergency_contact_relationship": "relationship to patient (e.g. Mom, Spouse, Friend)",
786
+ "emergency_contact_phone": "emergency contact's phone number",
787
+ "referring_physician": "name of referring physician/doctor",
788
+ "referring_physician_phone": "phone number next to referring physician",
789
+ "primary_care_physician": "PCP name if different from referring",
790
+ "preferred_pharmacy": "pharmacy name if listed",
791
+ "employment_status": "Employed/Self Employed/Unemployed/Retired/Student/Disabled/Military",
792
+ "occupation": "job title if listed",
793
+ "employer": "employer/company name",
794
+ "employer_address": "employer address if listed",
795
+ "insurance_provider": "insurance company name",
796
+ "insurance_id": "policy number",
797
+ "insurance_group_number": "group number",
798
+ "insured_name": "name of insured person (may differ from patient)",
799
+ "insured_dob": "YYYY-MM-DD",
800
+ "insurance_phone": "insurance contact number",
801
+ "billing_address": "billing address if different from home",
802
+ "guarantor_name": "person responsible for payment if listed",
803
+ "reason_for_visit": "chief complaint or reason for visit",
804
+ "date_of_injury": "YYYY-MM-DD (date of injury or onset of symptoms)",
805
+ "pain_location": "where pain is located if listed",
806
+ "pain_onset": "when pain began (e.g. three months ago)",
807
+ "pain_cause": "what caused the pain/condition",
808
+ "pain_progression": "Improved/Worsened/Stayed the same",
809
+ "work_related_injury": "Yes/No",
810
+ "car_accident": "Yes/No",
811
+ "medical_conditions": "existing medical conditions",
812
+ "allergies": "known allergies",
813
+ "medications": "current medications",
814
+ "signature_date": "YYYY-MM-DD (date signed)"
815
+ }
816
+
817
+ IMPORTANT: Return ONLY the JSON object, no other text."""
818
+
819
+ # Retry loop with progressively smaller images on memory errors
820
+ max_retries = 3
821
+ current_img = img
822
+ current_bytes = image_bytes
823
+ current_width, current_height = new_width, new_height
824
+ current_size_kb = opt_size_kb
825
+
826
+ for attempt in range(max_retries):
827
+ est_img_tokens = (current_width // 14) * (current_height // 14)
828
+ console.print(
829
+ f" Image: {current_width}x{current_height}, {current_size_kb:.0f}KB (~{est_img_tokens:,} tokens)"
830
+ )
831
+
832
+ if attempt == 0:
833
+ console.print(" [dim]This may take 30-60 seconds...[/dim]")
834
+ else:
835
+ console.print(
836
+ f" [dim]Retry {attempt}/{max_retries-1} with smaller image...[/dim]"
837
+ )
838
+
839
+ try:
840
+ start_time = time.time()
841
+ raw_text = vlm.extract_from_image(
842
+ image_bytes=current_bytes,
843
+ prompt=extraction_prompt,
844
+ )
845
+ extraction_time = time.time() - start_time
846
+
847
+ # Check for memory-related errors
848
+ if (
849
+ "failed to process image" in raw_text
850
+ or "memory slot" in raw_text.lower()
851
+ ):
852
+ if attempt < max_retries - 1:
853
+ console.print(
854
+ " [yellow]⚠[/yellow] Memory error, reducing image size..."
855
+ )
856
+ # Reduce image to 75% of current size
857
+ scale = 0.75
858
+ current_width = int(current_width * scale)
859
+ current_height = int(current_height * scale)
860
+ current_img = current_img.resize(
861
+ (current_width, current_height), Image.Resampling.LANCZOS
862
+ )
863
+ output = io.BytesIO()
864
+ current_img.save(
865
+ output, format="JPEG", quality=jpeg_quality, optimize=True
866
+ )
867
+ current_bytes = output.getvalue()
868
+ current_size_kb = len(current_bytes) / 1024
869
+ continue
870
+ else:
871
+ console.print(f" [red]✗[/red] {raw_text}")
872
+ console.print()
873
+ console.print("[yellow]Suggestions:[/yellow]")
874
+ console.print(" 1. Try with smaller image: --max-dimension 640")
875
+ console.print(" 2. Restart Lemonade Server to clear memory")
876
+ console.print(" 3. Reload the VLM model in Lemonade")
877
+ return 1
878
+
879
+ if raw_text.startswith("[VLM extraction failed:"):
880
+ console.print(f" [red]✗[/red] {raw_text}")
881
+ return 1
882
+
883
+ # Success!
884
+ console.print(
885
+ f" [green]✓[/green] Extraction complete ({len(raw_text)} chars, {extraction_time:.1f}s)"
886
+ )
887
+
888
+ # Estimate tokens/sec (output tokens only)
889
+ est_output_tokens = len(raw_text) / 4
890
+ tps = est_output_tokens / extraction_time if extraction_time > 0 else 0
891
+ console.print(
892
+ f" Output: ~{est_output_tokens:.0f} tokens at ~{tps:.1f} TPS"
893
+ )
894
+
895
+ # Total throughput including prompt processing
896
+ total_tokens = (
897
+ est_img_tokens + 200 + est_output_tokens
898
+ ) # img + prompt + output
899
+ total_tps = total_tokens / extraction_time if extraction_time > 0 else 0
900
+ console.print(
901
+ f" Total throughput: ~{total_tps:.0f} TPS (incl. {est_img_tokens:,} image tokens)"
902
+ )
903
+
904
+ # Update dimensions for final report
905
+ new_width, new_height = current_width, current_height
906
+ break
907
+
908
+ except Exception as e:
909
+ console.print(f" [red]✗[/red] Extraction failed: {e}")
910
+ return 1
911
+ else:
912
+ # All retries exhausted
913
+ console.print(" [red]✗[/red] All retries failed")
914
+ return 1
915
+
916
+ # Step 5: Parse JSON
917
+ console.print()
918
+ console.print("[bold]Step 5:[/bold] Parsing JSON...")
919
+ try:
920
+ # Try direct parse
921
+ patient_data = json.loads(raw_text)
922
+ console.print(" [green]✓[/green] JSON parsed successfully")
923
+ except json.JSONDecodeError:
924
+ # Try to find JSON in text
925
+ try:
926
+ start = raw_text.find("{")
927
+ end = raw_text.rfind("}") + 1
928
+ if start >= 0 and end > start:
929
+ patient_data = json.loads(raw_text[start:end])
930
+ console.print(" [green]✓[/green] JSON extracted from response")
931
+ else:
932
+ console.print(" [red]✗[/red] No JSON found in response")
933
+ console.print()
934
+ console.print("[bold]Raw VLM Output:[/bold]")
935
+ console.print(raw_text[:500])
936
+ return 1
937
+ except json.JSONDecodeError as e:
938
+ console.print(f" [red]✗[/red] JSON parse failed: {e}")
939
+ return 1
940
+
941
+ # Display results
942
+ console.print()
943
+ console.print(
944
+ Panel.fit(
945
+ "[bold green]✓ Extraction Successful[/bold green]",
946
+ border_style="green",
947
+ )
948
+ )
949
+
950
+ # Show extracted fields
951
+ console.print()
952
+ console.print("[bold]Extracted Fields:[/bold]")
953
+ fields_found = 0
954
+ for key, value in patient_data.items():
955
+ if value and value != "null":
956
+ fields_found += 1
957
+ console.print(f" [cyan]{key}:[/cyan] {value}")
958
+
959
+ console.print()
960
+ console.print(f"[dim]Fields extracted: {fields_found}/53[/dim]")
961
+ console.print()
962
+
963
+ # Timing breakdown section
964
+ console.print("[bold]⏱️ TIMING BREAKDOWN[/bold]")
965
+ console.print("-" * 40)
966
+ console.print(f" Model: {args.vlm_model}")
967
+ console.print(f" Image dimensions: {new_width}x{new_height}")
968
+ console.print(f" VLM extraction: {extraction_time:.2f}s")
969
+ console.print(f" Est. image tokens: ~{est_img_tokens:,}")
970
+ console.print(f" Est. output tokens: ~{int(est_output_tokens)}")
971
+ console.print(f" Est. tokens/sec: ~{tps:.1f} TPS")
972
+ console.print()
973
+
974
+ # Success summary
975
+ if patient_data.get("first_name") and patient_data.get("last_name"):
976
+ console.print(
977
+ f" Patient: {patient_data.get('first_name', '')} {patient_data.get('last_name', '')}"
978
+ )
979
+ console.print(" [green]✓ Pipeline test PASSED[/green]")
980
+ else:
981
+ console.print(" [yellow]⚠ Missing required name fields[/yellow]")
982
+ console.print(" [red]✗ Pipeline test FAILED[/red]")
983
+ console.print()
984
+
985
+ return 0
986
+
987
+
988
+ def _launch_electron(url: str, delay: float = 1.5) -> bool:
989
+ """
990
+ Launch Electron app to display the dashboard.
991
+
992
+ Returns True if Electron was launched successfully, False otherwise.
993
+ """
994
+ import os
995
+ import platform
996
+ import shutil
997
+ import subprocess
998
+ import time
999
+
1000
+ time.sleep(delay) # Wait for server to start
1001
+
1002
+ # Find the Electron wrapper directory
1003
+ electron_dir = Path(__file__).parent / "dashboard" / "electron"
1004
+ main_js = electron_dir / "main.js"
1005
+
1006
+ if not main_js.exists():
1007
+ logger.warning(f"Electron wrapper not found at {electron_dir}")
1008
+ return False
1009
+
1010
+ # On Windows, use npm.cmd and npx.cmd
1011
+ is_windows = platform.system() == "Windows"
1012
+ npm_cmd = "npm.cmd" if is_windows else "npm"
1013
+ npx_cmd = "npx.cmd" if is_windows else "npx"
1014
+
1015
+ # Check if npx/electron is available
1016
+ npx_path = shutil.which(npx_cmd)
1017
+ if not npx_path:
1018
+ logger.warning(f"{npx_cmd} not found in PATH, cannot launch Electron")
1019
+ return False
1020
+
1021
+ try:
1022
+ # Check if node_modules exists, if not run npm install first
1023
+ node_modules = electron_dir / "node_modules"
1024
+ if not node_modules.exists():
1025
+ console.print("[dim]Installing Electron dependencies...[/dim]")
1026
+ subprocess.run(
1027
+ [npm_cmd, "install"],
1028
+ cwd=str(electron_dir),
1029
+ capture_output=True,
1030
+ check=True,
1031
+ shell=is_windows, # Use shell on Windows for .cmd files
1032
+ )
1033
+
1034
+ # Launch Electron with the dashboard URL
1035
+ env = os.environ.copy()
1036
+ env["EMR_DASHBOARD_URL"] = url
1037
+
1038
+ subprocess.Popen(
1039
+ [npx_cmd, "electron", "."],
1040
+ cwd=str(electron_dir),
1041
+ env=env,
1042
+ stdout=subprocess.DEVNULL,
1043
+ stderr=subprocess.DEVNULL,
1044
+ shell=is_windows, # Use shell on Windows for .cmd files
1045
+ )
1046
+ return True
1047
+ except Exception as e:
1048
+ logger.warning(f"Failed to launch Electron: {e}")
1049
+ return False
1050
+
1051
+
1052
+ def cmd_dashboard(args):
1053
+ """Start web dashboard."""
1054
+ import threading
1055
+ import time
1056
+ import webbrowser
1057
+
1058
+ def open_browser(url: str, delay: float = 1.5):
1059
+ """Open browser after a short delay to allow server to start."""
1060
+ time.sleep(delay)
1061
+ webbrowser.open(url)
1062
+
1063
+ def open_electron_or_browser(url: str, use_browser: bool, delay: float = 1.5):
1064
+ """Open Electron app, falling back to browser if needed."""
1065
+ if use_browser:
1066
+ open_browser(url, delay)
1067
+ else:
1068
+ if not _launch_electron(url, delay):
1069
+ console.print(
1070
+ "[yellow]Electron not available, opening in browser instead...[/yellow]"
1071
+ )
1072
+ open_browser(url, delay)
1073
+
1074
+ try:
1075
+ from gaia.agents.emr.dashboard.server import run_dashboard
1076
+
1077
+ console.print()
1078
+ console.print(
1079
+ Panel.fit(
1080
+ "[bold cyan]EMR Dashboard[/bold cyan]\n"
1081
+ "[dim]Real-time Patient Processing Monitor[/dim]",
1082
+ border_style="cyan",
1083
+ )
1084
+ )
1085
+
1086
+ url = f"http://localhost:{args.port}"
1087
+
1088
+ table = Table(show_header=False, box=None, padding=(0, 2))
1089
+ table.add_column(style="dim")
1090
+ table.add_column()
1091
+ table.add_row("📁 Watch folder:", args.watch_dir)
1092
+ table.add_row("💾 Database:", args.db)
1093
+ table.add_row("🌐 URL:", f"[bold cyan]{url}[/bold cyan]")
1094
+ console.print(table)
1095
+ console.print("\n[dim]Press Ctrl+C to stop[/dim]\n")
1096
+
1097
+ # Auto-open unless --no-open flag is set
1098
+ if not getattr(args, "no_open", False):
1099
+ use_browser = getattr(args, "browser", False)
1100
+ if use_browser:
1101
+ console.print("[dim]Opening dashboard in browser...[/dim]\n")
1102
+ else:
1103
+ console.print("[dim]Opening dashboard in Electron app...[/dim]\n")
1104
+
1105
+ open_thread = threading.Thread(
1106
+ target=open_electron_or_browser,
1107
+ args=(url, use_browser),
1108
+ daemon=True,
1109
+ )
1110
+ open_thread.start()
1111
+
1112
+ run_dashboard(
1113
+ watch_dir=args.watch_dir,
1114
+ db_path=args.db,
1115
+ host=args.host,
1116
+ port=args.port,
1117
+ )
1118
+ except ImportError:
1119
+ console.print("[red]Error: Dashboard dependencies not installed[/red]")
1120
+ console.print("Install with: [cyan]pip install 'amd-gaia[api]'[/cyan]")
1121
+ return 1
1122
+ except KeyboardInterrupt:
1123
+ console.print("\n[dim]Shutting down dashboard...[/dim]")
1124
+ return 0
1125
+
1126
+
1127
+ def _add_common_args(parser):
1128
+ """Add common arguments to a parser."""
1129
+ parser.add_argument(
1130
+ "--watch-dir",
1131
+ default="./intake_forms",
1132
+ help="Directory to watch for intake forms (default: ./intake_forms)",
1133
+ )
1134
+ parser.add_argument(
1135
+ "--db",
1136
+ default="./data/patients.db",
1137
+ help="Path to patient database (default: ./data/patients.db)",
1138
+ )
1139
+ parser.add_argument(
1140
+ "--vlm-model",
1141
+ default="Qwen3-VL-4B-Instruct-GGUF",
1142
+ help="VLM model for extraction (default: Qwen3-VL-4B-Instruct-GGUF)",
1143
+ )
1144
+ parser.add_argument(
1145
+ "--debug",
1146
+ action="store_true",
1147
+ help="Enable debug logging",
1148
+ )
1149
+
1150
+
1151
+ def main():
1152
+ """Main CLI entry point."""
1153
+ parser = argparse.ArgumentParser(
1154
+ description="Medical Intake Agent CLI",
1155
+ formatter_class=argparse.RawDescriptionHelpFormatter,
1156
+ )
1157
+
1158
+ subparsers = parser.add_subparsers(dest="command", help="Command to run")
1159
+
1160
+ # Watch command
1161
+ parser_watch = subparsers.add_parser(
1162
+ "watch",
1163
+ help="Watch directory for new intake forms",
1164
+ )
1165
+ _add_common_args(parser_watch)
1166
+ parser_watch.set_defaults(func=cmd_watch)
1167
+
1168
+ # Process command
1169
+ parser_process = subparsers.add_parser(
1170
+ "process",
1171
+ help="Process a single intake form",
1172
+ )
1173
+ _add_common_args(parser_process)
1174
+ parser_process.add_argument("file", help="Path to intake form file")
1175
+ parser_process.set_defaults(func=cmd_process)
1176
+
1177
+ # Query command
1178
+ parser_query = subparsers.add_parser(
1179
+ "query",
1180
+ help="Query patient database",
1181
+ )
1182
+ _add_common_args(parser_query)
1183
+ parser_query.add_argument("question", help="Question to ask")
1184
+ parser_query.set_defaults(func=cmd_query)
1185
+
1186
+ # Stats command
1187
+ parser_stats = subparsers.add_parser(
1188
+ "stats",
1189
+ help="Show processing statistics",
1190
+ )
1191
+ _add_common_args(parser_stats)
1192
+ parser_stats.set_defaults(func=cmd_stats)
1193
+
1194
+ # Reset command
1195
+ parser_reset = subparsers.add_parser(
1196
+ "reset",
1197
+ help="Clear all patient data from the database",
1198
+ )
1199
+ _add_common_args(parser_reset)
1200
+ parser_reset.add_argument(
1201
+ "--force",
1202
+ "-f",
1203
+ action="store_true",
1204
+ help="Skip confirmation prompt",
1205
+ )
1206
+ parser_reset.set_defaults(func=cmd_reset)
1207
+
1208
+ # Init command
1209
+ parser_init = subparsers.add_parser(
1210
+ "init",
1211
+ help="Download and setup required VLM models",
1212
+ )
1213
+ parser_init.add_argument(
1214
+ "--vlm-model",
1215
+ default="Qwen3-VL-4B-Instruct-GGUF",
1216
+ help="VLM model to download (default: Qwen3-VL-4B-Instruct-GGUF)",
1217
+ )
1218
+ parser_init.add_argument(
1219
+ "--debug",
1220
+ action="store_true",
1221
+ help="Enable debug logging",
1222
+ )
1223
+ parser_init.set_defaults(func=cmd_init)
1224
+
1225
+ # Test command
1226
+ parser_test = subparsers.add_parser(
1227
+ "test",
1228
+ help="Test VLM extraction pipeline on a single file",
1229
+ )
1230
+ parser_test.add_argument(
1231
+ "file",
1232
+ help="Path to intake form image (PNG, JPG, PDF)",
1233
+ )
1234
+ parser_test.add_argument(
1235
+ "--vlm-model",
1236
+ default="Qwen3-VL-4B-Instruct-GGUF",
1237
+ help="VLM model to use (default: Qwen3-VL-4B-Instruct-GGUF)",
1238
+ )
1239
+ parser_test.add_argument(
1240
+ "--max-dimension",
1241
+ type=int,
1242
+ default=1024,
1243
+ help="Max image dimension in pixels (default: 1024)",
1244
+ )
1245
+ parser_test.add_argument(
1246
+ "--jpeg-quality",
1247
+ type=int,
1248
+ default=85,
1249
+ help="JPEG compression quality (default: 85)",
1250
+ )
1251
+ parser_test.add_argument(
1252
+ "--clear-context",
1253
+ action="store_true",
1254
+ help="Clear VLM context before processing (fixes memory errors)",
1255
+ )
1256
+ parser_test.add_argument(
1257
+ "--debug",
1258
+ action="store_true",
1259
+ help="Enable debug logging",
1260
+ )
1261
+ parser_test.set_defaults(func=cmd_test)
1262
+
1263
+ # Dashboard command
1264
+ parser_dashboard = subparsers.add_parser(
1265
+ "dashboard",
1266
+ help="Start web dashboard",
1267
+ )
1268
+ _add_common_args(parser_dashboard)
1269
+ parser_dashboard.add_argument(
1270
+ "--host",
1271
+ default="127.0.0.1",
1272
+ help="Dashboard host (default: 127.0.0.1)",
1273
+ )
1274
+ parser_dashboard.add_argument(
1275
+ "--port",
1276
+ type=int,
1277
+ default=8080,
1278
+ help="Dashboard port (default: 8080)",
1279
+ )
1280
+ parser_dashboard.add_argument(
1281
+ "--no-open",
1282
+ action="store_true",
1283
+ help="Don't automatically open dashboard",
1284
+ )
1285
+ parser_dashboard.add_argument(
1286
+ "--browser",
1287
+ action="store_true",
1288
+ help="Open in web browser instead of Electron app",
1289
+ )
1290
+ parser_dashboard.set_defaults(func=cmd_dashboard)
1291
+
1292
+ args = parser.parse_args()
1293
+
1294
+ # Run command
1295
+ if not args.command:
1296
+ parser.print_help()
1297
+ return 0
1298
+
1299
+ # Configure logging - WARNING by default, DEBUG with --debug flag
1300
+ if getattr(args, "debug", False):
1301
+ logging.basicConfig(
1302
+ level=logging.DEBUG,
1303
+ format="%(asctime)s | %(levelname)s | %(name)s | %(message)s",
1304
+ datefmt="%H:%M:%S",
1305
+ )
1306
+ else:
1307
+ # Suppress all logs from gaia modules for cleaner output
1308
+ logging.basicConfig(level=logging.WARNING)
1309
+ for logger_name in [
1310
+ "gaia",
1311
+ "gaia.llm",
1312
+ "gaia.database",
1313
+ "gaia.agents",
1314
+ "gaia.utils",
1315
+ ]:
1316
+ logging.getLogger(logger_name).setLevel(logging.WARNING)
1317
+
1318
+ return args.func(args)
1319
+
1320
+
1321
+ if __name__ == "__main__":
1322
+ sys.exit(main())