amd-gaia 0.14.1__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.
- amd_gaia-0.14.3.dist-info/METADATA +223 -0
- amd_gaia-0.14.3.dist-info/RECORD +168 -0
- {amd_gaia-0.14.1.dist-info → amd_gaia-0.14.3.dist-info}/entry_points.txt +1 -0
- gaia/__init__.py +28 -1
- gaia/agents/__init__.py +1 -1
- gaia/agents/base/__init__.py +1 -1
- gaia/agents/base/agent.py +142 -37
- gaia/agents/base/api_agent.py +1 -1
- gaia/agents/base/console.py +400 -16
- gaia/agents/base/errors.py +237 -0
- gaia/agents/base/mcp_agent.py +1 -1
- gaia/agents/base/tools.py +1 -1
- gaia/agents/blender/agent.py +1 -1
- gaia/agents/blender/agent_simple.py +1 -1
- gaia/agents/blender/app.py +1 -1
- gaia/agents/blender/app_simple.py +1 -1
- gaia/agents/blender/core/__init__.py +1 -1
- gaia/agents/blender/core/materials.py +1 -1
- gaia/agents/blender/core/objects.py +1 -1
- gaia/agents/blender/core/rendering.py +1 -1
- gaia/agents/blender/core/scene.py +1 -1
- gaia/agents/blender/core/view.py +1 -1
- gaia/agents/chat/__init__.py +1 -1
- gaia/agents/chat/agent.py +41 -181
- gaia/agents/chat/app.py +1 -1
- gaia/agents/chat/session.py +1 -1
- gaia/agents/chat/tools/__init__.py +1 -1
- gaia/agents/chat/tools/file_tools.py +1 -1
- gaia/agents/chat/tools/rag_tools.py +1 -1
- gaia/agents/chat/tools/shell_tools.py +1 -1
- gaia/agents/code/__init__.py +1 -1
- gaia/agents/code/agent.py +3 -1
- gaia/agents/code/orchestration/__init__.py +1 -1
- gaia/agents/code/orchestration/checklist_executor.py +27 -3
- gaia/agents/code/orchestration/checklist_generator.py +8 -4
- gaia/agents/code/orchestration/factories/__init__.py +1 -1
- gaia/agents/code/orchestration/factories/base.py +1 -1
- gaia/agents/code/orchestration/factories/nextjs_factory.py +1 -1
- gaia/agents/code/orchestration/factories/python_factory.py +1 -1
- gaia/agents/code/orchestration/orchestrator.py +276 -45
- gaia/agents/code/orchestration/project_analyzer.py +1 -1
- gaia/agents/code/orchestration/steps/__init__.py +1 -1
- gaia/agents/code/orchestration/steps/base.py +1 -1
- gaia/agents/code/orchestration/steps/error_handler.py +2 -2
- gaia/agents/code/orchestration/steps/nextjs.py +1 -1
- gaia/agents/code/orchestration/steps/python.py +1 -1
- gaia/agents/code/orchestration/template_catalog.py +8 -2
- gaia/agents/code/orchestration/workflows/__init__.py +1 -1
- gaia/agents/code/orchestration/workflows/base.py +1 -1
- gaia/agents/code/orchestration/workflows/nextjs.py +1 -1
- gaia/agents/code/orchestration/workflows/python.py +1 -1
- gaia/agents/code/prompts/__init__.py +1 -1
- gaia/agents/code/prompts/base_prompt.py +1 -1
- gaia/agents/code/prompts/code_patterns.py +129 -18
- gaia/agents/code/prompts/nextjs_prompt.py +1 -1
- gaia/agents/code/prompts/python_prompt.py +1 -1
- gaia/agents/code/schema_inference.py +1 -1
- gaia/agents/code/system_prompt.py +1 -1
- gaia/agents/code/tools/__init__.py +1 -1
- gaia/agents/code/tools/cli_tools.py +1 -1
- gaia/agents/code/tools/code_formatting.py +2 -2
- gaia/agents/code/tools/code_tools.py +2 -2
- gaia/agents/code/tools/error_fixing.py +1 -1
- gaia/agents/code/tools/external_tools.py +1 -1
- gaia/agents/code/tools/prisma_tools.py +1 -1
- gaia/agents/code/tools/project_management.py +1 -1
- gaia/agents/code/tools/testing.py +1 -1
- gaia/agents/code/tools/typescript_tools.py +1 -1
- gaia/agents/code/tools/validation_parsing.py +1 -1
- gaia/agents/code/tools/validation_tools.py +5 -2
- gaia/agents/code/tools/web_dev_tools.py +17 -3
- gaia/agents/docker/__init__.py +1 -1
- gaia/agents/emr/__init__.py +8 -0
- gaia/agents/emr/agent.py +1506 -0
- gaia/agents/emr/cli.py +1322 -0
- gaia/agents/emr/constants.py +475 -0
- gaia/agents/emr/dashboard/__init__.py +4 -0
- gaia/agents/emr/dashboard/server.py +1974 -0
- gaia/agents/routing/__init__.py +1 -1
- gaia/agents/routing/agent.py +65 -7
- gaia/agents/routing/system_prompt.py +1 -1
- gaia/api/__init__.py +1 -1
- gaia/api/agent_registry.py +1 -1
- gaia/api/app.py +1 -1
- gaia/api/openai_server.py +1 -1
- gaia/api/schemas.py +1 -1
- gaia/api/sse_handler.py +5 -2
- gaia/apps/__init__.py +1 -1
- gaia/apps/llm/__init__.py +1 -1
- gaia/apps/summarize/pdf_formatter.py +1 -1
- gaia/audio/__init__.py +1 -1
- gaia/audio/audio_client.py +3 -3
- gaia/audio/audio_recorder.py +1 -1
- gaia/audio/kokoro_tts.py +3 -3
- gaia/audio/whisper_asr.py +3 -3
- gaia/chat/__init__.py +1 -1
- gaia/chat/prompts.py +1 -1
- gaia/chat/sdk.py +26 -1
- gaia/cli.py +18 -18
- gaia/database/__init__.py +10 -0
- gaia/database/agent.py +176 -0
- gaia/database/mixin.py +290 -0
- gaia/database/testing.py +64 -0
- gaia/eval/batch_experiment.py +2 -2
- gaia/eval/claude.py +5 -5
- gaia/eval/config.py +1 -1
- gaia/eval/email_generator.py +1 -1
- gaia/eval/eval.py +1 -1
- gaia/eval/groundtruth.py +1 -1
- gaia/eval/transcript_generator.py +1 -1
- gaia/eval/webapp/public/app.js +1 -1
- gaia/eval/webapp/server.js +1 -1
- gaia/eval/webapp/test-setup.js +1 -1
- gaia/llm/__init__.py +1 -1
- gaia/llm/lemonade_client.py +149 -11
- gaia/llm/lemonade_manager.py +36 -11
- gaia/llm/llm_client.py +2 -2
- gaia/llm/vlm_client.py +93 -18
- gaia/logger.py +1 -1
- gaia/mcp/agent_mcp_server.py +1 -1
- gaia/mcp/blender_mcp_client.py +1 -1
- gaia/mcp/blender_mcp_server.py +1 -1
- gaia/mcp/context7_cache.py +1 -1
- gaia/mcp/servers/__init__.py +1 -1
- gaia/mcp/servers/docker_mcp.py +1 -1
- gaia/rag/demo.py +5 -5
- gaia/rag/pdf_utils.py +1 -1
- gaia/rag/sdk.py +2 -2
- gaia/security.py +1 -1
- gaia/talk/sdk.py +1 -1
- gaia/testing/__init__.py +87 -0
- gaia/testing/assertions.py +330 -0
- gaia/testing/fixtures.py +333 -0
- gaia/testing/mocks.py +493 -0
- gaia/util.py +1 -1
- gaia/utils/__init__.py +33 -0
- gaia/utils/file_watcher.py +675 -0
- gaia/utils/parsing.py +223 -0
- gaia/version.py +2 -2
- amd_gaia-0.14.1.dist-info/METADATA +0 -768
- amd_gaia-0.14.1.dist-info/RECORD +0 -800
- gaia/eval/webapp/node_modules/.bin/mime +0 -16
- gaia/eval/webapp/node_modules/.bin/mime.cmd +0 -17
- gaia/eval/webapp/node_modules/.bin/mime.ps1 +0 -28
- gaia/eval/webapp/node_modules/.package-lock.json +0 -865
- gaia/eval/webapp/node_modules/accepts/HISTORY.md +0 -243
- gaia/eval/webapp/node_modules/accepts/LICENSE +0 -23
- gaia/eval/webapp/node_modules/accepts/README.md +0 -140
- gaia/eval/webapp/node_modules/accepts/index.js +0 -238
- gaia/eval/webapp/node_modules/accepts/package.json +0 -47
- gaia/eval/webapp/node_modules/array-flatten/LICENSE +0 -21
- gaia/eval/webapp/node_modules/array-flatten/README.md +0 -43
- gaia/eval/webapp/node_modules/array-flatten/array-flatten.js +0 -64
- gaia/eval/webapp/node_modules/array-flatten/package.json +0 -39
- gaia/eval/webapp/node_modules/body-parser/HISTORY.md +0 -672
- gaia/eval/webapp/node_modules/body-parser/LICENSE +0 -23
- gaia/eval/webapp/node_modules/body-parser/README.md +0 -476
- gaia/eval/webapp/node_modules/body-parser/SECURITY.md +0 -25
- gaia/eval/webapp/node_modules/body-parser/index.js +0 -156
- gaia/eval/webapp/node_modules/body-parser/lib/read.js +0 -205
- gaia/eval/webapp/node_modules/body-parser/lib/types/json.js +0 -247
- gaia/eval/webapp/node_modules/body-parser/lib/types/raw.js +0 -101
- gaia/eval/webapp/node_modules/body-parser/lib/types/text.js +0 -121
- gaia/eval/webapp/node_modules/body-parser/lib/types/urlencoded.js +0 -307
- gaia/eval/webapp/node_modules/body-parser/package.json +0 -56
- gaia/eval/webapp/node_modules/bytes/History.md +0 -97
- gaia/eval/webapp/node_modules/bytes/LICENSE +0 -23
- gaia/eval/webapp/node_modules/bytes/Readme.md +0 -152
- gaia/eval/webapp/node_modules/bytes/index.js +0 -170
- gaia/eval/webapp/node_modules/bytes/package.json +0 -42
- gaia/eval/webapp/node_modules/call-bind-apply-helpers/.eslintrc +0 -17
- gaia/eval/webapp/node_modules/call-bind-apply-helpers/.github/FUNDING.yml +0 -12
- gaia/eval/webapp/node_modules/call-bind-apply-helpers/.nycrc +0 -9
- gaia/eval/webapp/node_modules/call-bind-apply-helpers/CHANGELOG.md +0 -30
- gaia/eval/webapp/node_modules/call-bind-apply-helpers/LICENSE +0 -21
- gaia/eval/webapp/node_modules/call-bind-apply-helpers/README.md +0 -62
- gaia/eval/webapp/node_modules/call-bind-apply-helpers/actualApply.d.ts +0 -1
- gaia/eval/webapp/node_modules/call-bind-apply-helpers/actualApply.js +0 -10
- gaia/eval/webapp/node_modules/call-bind-apply-helpers/applyBind.d.ts +0 -19
- gaia/eval/webapp/node_modules/call-bind-apply-helpers/applyBind.js +0 -10
- gaia/eval/webapp/node_modules/call-bind-apply-helpers/functionApply.d.ts +0 -1
- gaia/eval/webapp/node_modules/call-bind-apply-helpers/functionApply.js +0 -4
- gaia/eval/webapp/node_modules/call-bind-apply-helpers/functionCall.d.ts +0 -1
- gaia/eval/webapp/node_modules/call-bind-apply-helpers/functionCall.js +0 -4
- gaia/eval/webapp/node_modules/call-bind-apply-helpers/index.d.ts +0 -64
- gaia/eval/webapp/node_modules/call-bind-apply-helpers/index.js +0 -15
- gaia/eval/webapp/node_modules/call-bind-apply-helpers/package.json +0 -85
- gaia/eval/webapp/node_modules/call-bind-apply-helpers/reflectApply.d.ts +0 -3
- gaia/eval/webapp/node_modules/call-bind-apply-helpers/reflectApply.js +0 -4
- gaia/eval/webapp/node_modules/call-bind-apply-helpers/test/index.js +0 -63
- gaia/eval/webapp/node_modules/call-bind-apply-helpers/tsconfig.json +0 -9
- gaia/eval/webapp/node_modules/call-bound/.eslintrc +0 -13
- gaia/eval/webapp/node_modules/call-bound/.github/FUNDING.yml +0 -12
- gaia/eval/webapp/node_modules/call-bound/.nycrc +0 -9
- gaia/eval/webapp/node_modules/call-bound/CHANGELOG.md +0 -42
- gaia/eval/webapp/node_modules/call-bound/LICENSE +0 -21
- gaia/eval/webapp/node_modules/call-bound/README.md +0 -53
- gaia/eval/webapp/node_modules/call-bound/index.d.ts +0 -94
- gaia/eval/webapp/node_modules/call-bound/index.js +0 -19
- gaia/eval/webapp/node_modules/call-bound/package.json +0 -99
- gaia/eval/webapp/node_modules/call-bound/test/index.js +0 -61
- gaia/eval/webapp/node_modules/call-bound/tsconfig.json +0 -10
- gaia/eval/webapp/node_modules/content-disposition/HISTORY.md +0 -60
- gaia/eval/webapp/node_modules/content-disposition/LICENSE +0 -22
- gaia/eval/webapp/node_modules/content-disposition/README.md +0 -142
- gaia/eval/webapp/node_modules/content-disposition/index.js +0 -458
- gaia/eval/webapp/node_modules/content-disposition/package.json +0 -44
- gaia/eval/webapp/node_modules/content-type/HISTORY.md +0 -29
- gaia/eval/webapp/node_modules/content-type/LICENSE +0 -22
- gaia/eval/webapp/node_modules/content-type/README.md +0 -94
- gaia/eval/webapp/node_modules/content-type/index.js +0 -225
- gaia/eval/webapp/node_modules/content-type/package.json +0 -42
- gaia/eval/webapp/node_modules/cookie/LICENSE +0 -24
- gaia/eval/webapp/node_modules/cookie/README.md +0 -317
- gaia/eval/webapp/node_modules/cookie/SECURITY.md +0 -25
- gaia/eval/webapp/node_modules/cookie/index.js +0 -334
- gaia/eval/webapp/node_modules/cookie/package.json +0 -44
- gaia/eval/webapp/node_modules/cookie-signature/.npmignore +0 -4
- gaia/eval/webapp/node_modules/cookie-signature/History.md +0 -38
- gaia/eval/webapp/node_modules/cookie-signature/Readme.md +0 -42
- gaia/eval/webapp/node_modules/cookie-signature/index.js +0 -51
- gaia/eval/webapp/node_modules/cookie-signature/package.json +0 -18
- gaia/eval/webapp/node_modules/debug/.coveralls.yml +0 -1
- gaia/eval/webapp/node_modules/debug/.eslintrc +0 -11
- gaia/eval/webapp/node_modules/debug/.npmignore +0 -9
- gaia/eval/webapp/node_modules/debug/.travis.yml +0 -14
- gaia/eval/webapp/node_modules/debug/CHANGELOG.md +0 -362
- gaia/eval/webapp/node_modules/debug/LICENSE +0 -19
- gaia/eval/webapp/node_modules/debug/Makefile +0 -50
- gaia/eval/webapp/node_modules/debug/README.md +0 -312
- gaia/eval/webapp/node_modules/debug/component.json +0 -19
- gaia/eval/webapp/node_modules/debug/karma.conf.js +0 -70
- gaia/eval/webapp/node_modules/debug/node.js +0 -1
- gaia/eval/webapp/node_modules/debug/package.json +0 -49
- gaia/eval/webapp/node_modules/debug/src/browser.js +0 -185
- gaia/eval/webapp/node_modules/debug/src/debug.js +0 -202
- gaia/eval/webapp/node_modules/debug/src/index.js +0 -10
- gaia/eval/webapp/node_modules/debug/src/inspector-log.js +0 -15
- gaia/eval/webapp/node_modules/debug/src/node.js +0 -248
- gaia/eval/webapp/node_modules/depd/History.md +0 -103
- gaia/eval/webapp/node_modules/depd/LICENSE +0 -22
- gaia/eval/webapp/node_modules/depd/Readme.md +0 -280
- gaia/eval/webapp/node_modules/depd/index.js +0 -538
- gaia/eval/webapp/node_modules/depd/lib/browser/index.js +0 -77
- gaia/eval/webapp/node_modules/depd/package.json +0 -45
- gaia/eval/webapp/node_modules/destroy/LICENSE +0 -23
- gaia/eval/webapp/node_modules/destroy/README.md +0 -63
- gaia/eval/webapp/node_modules/destroy/index.js +0 -209
- gaia/eval/webapp/node_modules/destroy/package.json +0 -48
- gaia/eval/webapp/node_modules/dunder-proto/.eslintrc +0 -5
- gaia/eval/webapp/node_modules/dunder-proto/.github/FUNDING.yml +0 -12
- gaia/eval/webapp/node_modules/dunder-proto/.nycrc +0 -13
- gaia/eval/webapp/node_modules/dunder-proto/CHANGELOG.md +0 -24
- gaia/eval/webapp/node_modules/dunder-proto/LICENSE +0 -21
- gaia/eval/webapp/node_modules/dunder-proto/README.md +0 -54
- gaia/eval/webapp/node_modules/dunder-proto/get.d.ts +0 -5
- gaia/eval/webapp/node_modules/dunder-proto/get.js +0 -30
- gaia/eval/webapp/node_modules/dunder-proto/package.json +0 -76
- gaia/eval/webapp/node_modules/dunder-proto/set.d.ts +0 -5
- gaia/eval/webapp/node_modules/dunder-proto/set.js +0 -35
- gaia/eval/webapp/node_modules/dunder-proto/test/get.js +0 -34
- gaia/eval/webapp/node_modules/dunder-proto/test/index.js +0 -4
- gaia/eval/webapp/node_modules/dunder-proto/test/set.js +0 -50
- gaia/eval/webapp/node_modules/dunder-proto/tsconfig.json +0 -9
- gaia/eval/webapp/node_modules/ee-first/LICENSE +0 -22
- gaia/eval/webapp/node_modules/ee-first/README.md +0 -80
- gaia/eval/webapp/node_modules/ee-first/index.js +0 -95
- gaia/eval/webapp/node_modules/ee-first/package.json +0 -29
- gaia/eval/webapp/node_modules/encodeurl/LICENSE +0 -22
- gaia/eval/webapp/node_modules/encodeurl/README.md +0 -109
- gaia/eval/webapp/node_modules/encodeurl/index.js +0 -60
- gaia/eval/webapp/node_modules/encodeurl/package.json +0 -40
- gaia/eval/webapp/node_modules/es-define-property/.eslintrc +0 -13
- gaia/eval/webapp/node_modules/es-define-property/.github/FUNDING.yml +0 -12
- gaia/eval/webapp/node_modules/es-define-property/.nycrc +0 -9
- gaia/eval/webapp/node_modules/es-define-property/CHANGELOG.md +0 -29
- gaia/eval/webapp/node_modules/es-define-property/LICENSE +0 -21
- gaia/eval/webapp/node_modules/es-define-property/README.md +0 -49
- gaia/eval/webapp/node_modules/es-define-property/index.d.ts +0 -3
- gaia/eval/webapp/node_modules/es-define-property/index.js +0 -14
- gaia/eval/webapp/node_modules/es-define-property/package.json +0 -81
- gaia/eval/webapp/node_modules/es-define-property/test/index.js +0 -56
- gaia/eval/webapp/node_modules/es-define-property/tsconfig.json +0 -10
- gaia/eval/webapp/node_modules/es-errors/.eslintrc +0 -5
- gaia/eval/webapp/node_modules/es-errors/.github/FUNDING.yml +0 -12
- gaia/eval/webapp/node_modules/es-errors/CHANGELOG.md +0 -40
- gaia/eval/webapp/node_modules/es-errors/LICENSE +0 -21
- gaia/eval/webapp/node_modules/es-errors/README.md +0 -55
- gaia/eval/webapp/node_modules/es-errors/eval.d.ts +0 -3
- gaia/eval/webapp/node_modules/es-errors/eval.js +0 -4
- gaia/eval/webapp/node_modules/es-errors/index.d.ts +0 -3
- gaia/eval/webapp/node_modules/es-errors/index.js +0 -4
- gaia/eval/webapp/node_modules/es-errors/package.json +0 -80
- gaia/eval/webapp/node_modules/es-errors/range.d.ts +0 -3
- gaia/eval/webapp/node_modules/es-errors/range.js +0 -4
- gaia/eval/webapp/node_modules/es-errors/ref.d.ts +0 -3
- gaia/eval/webapp/node_modules/es-errors/ref.js +0 -4
- gaia/eval/webapp/node_modules/es-errors/syntax.d.ts +0 -3
- gaia/eval/webapp/node_modules/es-errors/syntax.js +0 -4
- gaia/eval/webapp/node_modules/es-errors/test/index.js +0 -19
- gaia/eval/webapp/node_modules/es-errors/tsconfig.json +0 -49
- gaia/eval/webapp/node_modules/es-errors/type.d.ts +0 -3
- gaia/eval/webapp/node_modules/es-errors/type.js +0 -4
- gaia/eval/webapp/node_modules/es-errors/uri.d.ts +0 -3
- gaia/eval/webapp/node_modules/es-errors/uri.js +0 -4
- gaia/eval/webapp/node_modules/es-object-atoms/.eslintrc +0 -16
- gaia/eval/webapp/node_modules/es-object-atoms/.github/FUNDING.yml +0 -12
- gaia/eval/webapp/node_modules/es-object-atoms/CHANGELOG.md +0 -37
- gaia/eval/webapp/node_modules/es-object-atoms/LICENSE +0 -21
- gaia/eval/webapp/node_modules/es-object-atoms/README.md +0 -63
- gaia/eval/webapp/node_modules/es-object-atoms/RequireObjectCoercible.d.ts +0 -3
- gaia/eval/webapp/node_modules/es-object-atoms/RequireObjectCoercible.js +0 -11
- gaia/eval/webapp/node_modules/es-object-atoms/ToObject.d.ts +0 -7
- gaia/eval/webapp/node_modules/es-object-atoms/ToObject.js +0 -10
- gaia/eval/webapp/node_modules/es-object-atoms/index.d.ts +0 -3
- gaia/eval/webapp/node_modules/es-object-atoms/index.js +0 -4
- gaia/eval/webapp/node_modules/es-object-atoms/isObject.d.ts +0 -3
- gaia/eval/webapp/node_modules/es-object-atoms/isObject.js +0 -6
- gaia/eval/webapp/node_modules/es-object-atoms/package.json +0 -80
- gaia/eval/webapp/node_modules/es-object-atoms/test/index.js +0 -38
- gaia/eval/webapp/node_modules/es-object-atoms/tsconfig.json +0 -6
- gaia/eval/webapp/node_modules/escape-html/LICENSE +0 -24
- gaia/eval/webapp/node_modules/escape-html/Readme.md +0 -43
- gaia/eval/webapp/node_modules/escape-html/index.js +0 -78
- gaia/eval/webapp/node_modules/escape-html/package.json +0 -24
- gaia/eval/webapp/node_modules/etag/HISTORY.md +0 -83
- gaia/eval/webapp/node_modules/etag/LICENSE +0 -22
- gaia/eval/webapp/node_modules/etag/README.md +0 -159
- gaia/eval/webapp/node_modules/etag/index.js +0 -131
- gaia/eval/webapp/node_modules/etag/package.json +0 -47
- gaia/eval/webapp/node_modules/express/History.md +0 -3656
- gaia/eval/webapp/node_modules/express/LICENSE +0 -24
- gaia/eval/webapp/node_modules/express/Readme.md +0 -260
- gaia/eval/webapp/node_modules/express/index.js +0 -11
- gaia/eval/webapp/node_modules/express/lib/application.js +0 -661
- gaia/eval/webapp/node_modules/express/lib/express.js +0 -116
- gaia/eval/webapp/node_modules/express/lib/middleware/init.js +0 -43
- gaia/eval/webapp/node_modules/express/lib/middleware/query.js +0 -47
- gaia/eval/webapp/node_modules/express/lib/request.js +0 -525
- gaia/eval/webapp/node_modules/express/lib/response.js +0 -1179
- gaia/eval/webapp/node_modules/express/lib/router/index.js +0 -673
- gaia/eval/webapp/node_modules/express/lib/router/layer.js +0 -181
- gaia/eval/webapp/node_modules/express/lib/router/route.js +0 -230
- gaia/eval/webapp/node_modules/express/lib/utils.js +0 -303
- gaia/eval/webapp/node_modules/express/lib/view.js +0 -182
- gaia/eval/webapp/node_modules/express/package.json +0 -102
- gaia/eval/webapp/node_modules/finalhandler/HISTORY.md +0 -210
- gaia/eval/webapp/node_modules/finalhandler/LICENSE +0 -22
- gaia/eval/webapp/node_modules/finalhandler/README.md +0 -147
- gaia/eval/webapp/node_modules/finalhandler/SECURITY.md +0 -25
- gaia/eval/webapp/node_modules/finalhandler/index.js +0 -341
- gaia/eval/webapp/node_modules/finalhandler/package.json +0 -47
- gaia/eval/webapp/node_modules/forwarded/HISTORY.md +0 -21
- gaia/eval/webapp/node_modules/forwarded/LICENSE +0 -22
- gaia/eval/webapp/node_modules/forwarded/README.md +0 -57
- gaia/eval/webapp/node_modules/forwarded/index.js +0 -90
- gaia/eval/webapp/node_modules/forwarded/package.json +0 -45
- gaia/eval/webapp/node_modules/fresh/HISTORY.md +0 -70
- gaia/eval/webapp/node_modules/fresh/LICENSE +0 -23
- gaia/eval/webapp/node_modules/fresh/README.md +0 -119
- gaia/eval/webapp/node_modules/fresh/index.js +0 -137
- gaia/eval/webapp/node_modules/fresh/package.json +0 -46
- gaia/eval/webapp/node_modules/fs/README.md +0 -9
- gaia/eval/webapp/node_modules/fs/package.json +0 -20
- gaia/eval/webapp/node_modules/function-bind/.eslintrc +0 -21
- gaia/eval/webapp/node_modules/function-bind/.github/FUNDING.yml +0 -12
- gaia/eval/webapp/node_modules/function-bind/.github/SECURITY.md +0 -3
- gaia/eval/webapp/node_modules/function-bind/.nycrc +0 -13
- gaia/eval/webapp/node_modules/function-bind/CHANGELOG.md +0 -136
- gaia/eval/webapp/node_modules/function-bind/LICENSE +0 -20
- gaia/eval/webapp/node_modules/function-bind/README.md +0 -46
- gaia/eval/webapp/node_modules/function-bind/implementation.js +0 -84
- gaia/eval/webapp/node_modules/function-bind/index.js +0 -5
- gaia/eval/webapp/node_modules/function-bind/package.json +0 -87
- gaia/eval/webapp/node_modules/function-bind/test/.eslintrc +0 -9
- gaia/eval/webapp/node_modules/function-bind/test/index.js +0 -252
- gaia/eval/webapp/node_modules/get-intrinsic/.eslintrc +0 -42
- gaia/eval/webapp/node_modules/get-intrinsic/.github/FUNDING.yml +0 -12
- gaia/eval/webapp/node_modules/get-intrinsic/.nycrc +0 -9
- gaia/eval/webapp/node_modules/get-intrinsic/CHANGELOG.md +0 -186
- gaia/eval/webapp/node_modules/get-intrinsic/LICENSE +0 -21
- gaia/eval/webapp/node_modules/get-intrinsic/README.md +0 -71
- gaia/eval/webapp/node_modules/get-intrinsic/index.js +0 -378
- gaia/eval/webapp/node_modules/get-intrinsic/package.json +0 -97
- gaia/eval/webapp/node_modules/get-intrinsic/test/GetIntrinsic.js +0 -274
- gaia/eval/webapp/node_modules/get-proto/.eslintrc +0 -10
- gaia/eval/webapp/node_modules/get-proto/.github/FUNDING.yml +0 -12
- gaia/eval/webapp/node_modules/get-proto/.nycrc +0 -9
- gaia/eval/webapp/node_modules/get-proto/CHANGELOG.md +0 -21
- gaia/eval/webapp/node_modules/get-proto/LICENSE +0 -21
- gaia/eval/webapp/node_modules/get-proto/Object.getPrototypeOf.d.ts +0 -5
- gaia/eval/webapp/node_modules/get-proto/Object.getPrototypeOf.js +0 -6
- gaia/eval/webapp/node_modules/get-proto/README.md +0 -50
- gaia/eval/webapp/node_modules/get-proto/Reflect.getPrototypeOf.d.ts +0 -3
- gaia/eval/webapp/node_modules/get-proto/Reflect.getPrototypeOf.js +0 -4
- gaia/eval/webapp/node_modules/get-proto/index.d.ts +0 -5
- gaia/eval/webapp/node_modules/get-proto/index.js +0 -27
- gaia/eval/webapp/node_modules/get-proto/package.json +0 -81
- gaia/eval/webapp/node_modules/get-proto/test/index.js +0 -68
- gaia/eval/webapp/node_modules/get-proto/tsconfig.json +0 -9
- gaia/eval/webapp/node_modules/gopd/.eslintrc +0 -16
- gaia/eval/webapp/node_modules/gopd/.github/FUNDING.yml +0 -12
- gaia/eval/webapp/node_modules/gopd/CHANGELOG.md +0 -45
- gaia/eval/webapp/node_modules/gopd/LICENSE +0 -21
- gaia/eval/webapp/node_modules/gopd/README.md +0 -40
- gaia/eval/webapp/node_modules/gopd/gOPD.d.ts +0 -1
- gaia/eval/webapp/node_modules/gopd/gOPD.js +0 -4
- gaia/eval/webapp/node_modules/gopd/index.d.ts +0 -5
- gaia/eval/webapp/node_modules/gopd/index.js +0 -15
- gaia/eval/webapp/node_modules/gopd/package.json +0 -77
- gaia/eval/webapp/node_modules/gopd/test/index.js +0 -36
- gaia/eval/webapp/node_modules/gopd/tsconfig.json +0 -9
- gaia/eval/webapp/node_modules/has-symbols/.eslintrc +0 -11
- gaia/eval/webapp/node_modules/has-symbols/.github/FUNDING.yml +0 -12
- gaia/eval/webapp/node_modules/has-symbols/.nycrc +0 -9
- gaia/eval/webapp/node_modules/has-symbols/CHANGELOG.md +0 -91
- gaia/eval/webapp/node_modules/has-symbols/LICENSE +0 -21
- gaia/eval/webapp/node_modules/has-symbols/README.md +0 -46
- gaia/eval/webapp/node_modules/has-symbols/index.d.ts +0 -3
- gaia/eval/webapp/node_modules/has-symbols/index.js +0 -14
- gaia/eval/webapp/node_modules/has-symbols/package.json +0 -111
- gaia/eval/webapp/node_modules/has-symbols/shams.d.ts +0 -3
- gaia/eval/webapp/node_modules/has-symbols/shams.js +0 -45
- gaia/eval/webapp/node_modules/has-symbols/test/index.js +0 -22
- gaia/eval/webapp/node_modules/has-symbols/test/shams/core-js.js +0 -29
- gaia/eval/webapp/node_modules/has-symbols/test/shams/get-own-property-symbols.js +0 -29
- gaia/eval/webapp/node_modules/has-symbols/test/tests.js +0 -58
- gaia/eval/webapp/node_modules/has-symbols/tsconfig.json +0 -10
- gaia/eval/webapp/node_modules/hasown/.eslintrc +0 -5
- gaia/eval/webapp/node_modules/hasown/.github/FUNDING.yml +0 -12
- gaia/eval/webapp/node_modules/hasown/.nycrc +0 -13
- gaia/eval/webapp/node_modules/hasown/CHANGELOG.md +0 -40
- gaia/eval/webapp/node_modules/hasown/LICENSE +0 -21
- gaia/eval/webapp/node_modules/hasown/README.md +0 -40
- gaia/eval/webapp/node_modules/hasown/index.d.ts +0 -3
- gaia/eval/webapp/node_modules/hasown/index.js +0 -8
- gaia/eval/webapp/node_modules/hasown/package.json +0 -92
- gaia/eval/webapp/node_modules/hasown/tsconfig.json +0 -6
- gaia/eval/webapp/node_modules/http-errors/HISTORY.md +0 -180
- gaia/eval/webapp/node_modules/http-errors/LICENSE +0 -23
- gaia/eval/webapp/node_modules/http-errors/README.md +0 -169
- gaia/eval/webapp/node_modules/http-errors/index.js +0 -289
- gaia/eval/webapp/node_modules/http-errors/package.json +0 -50
- gaia/eval/webapp/node_modules/iconv-lite/Changelog.md +0 -162
- gaia/eval/webapp/node_modules/iconv-lite/LICENSE +0 -21
- gaia/eval/webapp/node_modules/iconv-lite/README.md +0 -156
- gaia/eval/webapp/node_modules/iconv-lite/encodings/dbcs-codec.js +0 -555
- gaia/eval/webapp/node_modules/iconv-lite/encodings/dbcs-data.js +0 -176
- gaia/eval/webapp/node_modules/iconv-lite/encodings/index.js +0 -22
- gaia/eval/webapp/node_modules/iconv-lite/encodings/internal.js +0 -188
- gaia/eval/webapp/node_modules/iconv-lite/encodings/sbcs-codec.js +0 -72
- gaia/eval/webapp/node_modules/iconv-lite/encodings/sbcs-data-generated.js +0 -451
- gaia/eval/webapp/node_modules/iconv-lite/encodings/sbcs-data.js +0 -174
- gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/big5-added.json +0 -122
- gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/cp936.json +0 -264
- gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/cp949.json +0 -273
- gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/cp950.json +0 -177
- gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/eucjp.json +0 -182
- gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/gb18030-ranges.json +0 -1
- gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/gbk-added.json +0 -55
- gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/shiftjis.json +0 -125
- gaia/eval/webapp/node_modules/iconv-lite/encodings/utf16.js +0 -177
- gaia/eval/webapp/node_modules/iconv-lite/encodings/utf7.js +0 -290
- gaia/eval/webapp/node_modules/iconv-lite/lib/bom-handling.js +0 -52
- gaia/eval/webapp/node_modules/iconv-lite/lib/extend-node.js +0 -217
- gaia/eval/webapp/node_modules/iconv-lite/lib/index.d.ts +0 -24
- gaia/eval/webapp/node_modules/iconv-lite/lib/index.js +0 -153
- gaia/eval/webapp/node_modules/iconv-lite/lib/streams.js +0 -121
- gaia/eval/webapp/node_modules/iconv-lite/package.json +0 -46
- gaia/eval/webapp/node_modules/inherits/LICENSE +0 -16
- gaia/eval/webapp/node_modules/inherits/README.md +0 -42
- gaia/eval/webapp/node_modules/inherits/inherits.js +0 -9
- gaia/eval/webapp/node_modules/inherits/inherits_browser.js +0 -27
- gaia/eval/webapp/node_modules/inherits/package.json +0 -29
- gaia/eval/webapp/node_modules/ipaddr.js/LICENSE +0 -19
- gaia/eval/webapp/node_modules/ipaddr.js/README.md +0 -233
- gaia/eval/webapp/node_modules/ipaddr.js/ipaddr.min.js +0 -1
- gaia/eval/webapp/node_modules/ipaddr.js/lib/ipaddr.js +0 -673
- gaia/eval/webapp/node_modules/ipaddr.js/lib/ipaddr.js.d.ts +0 -68
- gaia/eval/webapp/node_modules/ipaddr.js/package.json +0 -35
- gaia/eval/webapp/node_modules/math-intrinsics/.eslintrc +0 -16
- gaia/eval/webapp/node_modules/math-intrinsics/.github/FUNDING.yml +0 -12
- gaia/eval/webapp/node_modules/math-intrinsics/CHANGELOG.md +0 -24
- gaia/eval/webapp/node_modules/math-intrinsics/LICENSE +0 -21
- gaia/eval/webapp/node_modules/math-intrinsics/README.md +0 -50
- gaia/eval/webapp/node_modules/math-intrinsics/abs.d.ts +0 -1
- gaia/eval/webapp/node_modules/math-intrinsics/abs.js +0 -4
- gaia/eval/webapp/node_modules/math-intrinsics/constants/maxArrayLength.d.ts +0 -3
- gaia/eval/webapp/node_modules/math-intrinsics/constants/maxArrayLength.js +0 -4
- gaia/eval/webapp/node_modules/math-intrinsics/constants/maxSafeInteger.d.ts +0 -3
- gaia/eval/webapp/node_modules/math-intrinsics/constants/maxSafeInteger.js +0 -5
- gaia/eval/webapp/node_modules/math-intrinsics/constants/maxValue.d.ts +0 -3
- gaia/eval/webapp/node_modules/math-intrinsics/constants/maxValue.js +0 -5
- gaia/eval/webapp/node_modules/math-intrinsics/floor.d.ts +0 -1
- gaia/eval/webapp/node_modules/math-intrinsics/floor.js +0 -4
- gaia/eval/webapp/node_modules/math-intrinsics/isFinite.d.ts +0 -3
- gaia/eval/webapp/node_modules/math-intrinsics/isFinite.js +0 -12
- gaia/eval/webapp/node_modules/math-intrinsics/isInteger.d.ts +0 -3
- gaia/eval/webapp/node_modules/math-intrinsics/isInteger.js +0 -16
- gaia/eval/webapp/node_modules/math-intrinsics/isNaN.d.ts +0 -1
- gaia/eval/webapp/node_modules/math-intrinsics/isNaN.js +0 -6
- gaia/eval/webapp/node_modules/math-intrinsics/isNegativeZero.d.ts +0 -3
- gaia/eval/webapp/node_modules/math-intrinsics/isNegativeZero.js +0 -6
- gaia/eval/webapp/node_modules/math-intrinsics/max.d.ts +0 -1
- gaia/eval/webapp/node_modules/math-intrinsics/max.js +0 -4
- gaia/eval/webapp/node_modules/math-intrinsics/min.d.ts +0 -1
- gaia/eval/webapp/node_modules/math-intrinsics/min.js +0 -4
- gaia/eval/webapp/node_modules/math-intrinsics/mod.d.ts +0 -3
- gaia/eval/webapp/node_modules/math-intrinsics/mod.js +0 -9
- gaia/eval/webapp/node_modules/math-intrinsics/package.json +0 -86
- gaia/eval/webapp/node_modules/math-intrinsics/pow.d.ts +0 -1
- gaia/eval/webapp/node_modules/math-intrinsics/pow.js +0 -4
- gaia/eval/webapp/node_modules/math-intrinsics/round.d.ts +0 -1
- gaia/eval/webapp/node_modules/math-intrinsics/round.js +0 -4
- gaia/eval/webapp/node_modules/math-intrinsics/sign.d.ts +0 -3
- gaia/eval/webapp/node_modules/math-intrinsics/sign.js +0 -11
- gaia/eval/webapp/node_modules/math-intrinsics/test/index.js +0 -192
- gaia/eval/webapp/node_modules/math-intrinsics/tsconfig.json +0 -3
- gaia/eval/webapp/node_modules/media-typer/HISTORY.md +0 -22
- gaia/eval/webapp/node_modules/media-typer/LICENSE +0 -22
- gaia/eval/webapp/node_modules/media-typer/README.md +0 -81
- gaia/eval/webapp/node_modules/media-typer/index.js +0 -270
- gaia/eval/webapp/node_modules/media-typer/package.json +0 -26
- gaia/eval/webapp/node_modules/merge-descriptors/HISTORY.md +0 -21
- gaia/eval/webapp/node_modules/merge-descriptors/LICENSE +0 -23
- gaia/eval/webapp/node_modules/merge-descriptors/README.md +0 -49
- gaia/eval/webapp/node_modules/merge-descriptors/index.js +0 -60
- gaia/eval/webapp/node_modules/merge-descriptors/package.json +0 -39
- gaia/eval/webapp/node_modules/methods/HISTORY.md +0 -29
- gaia/eval/webapp/node_modules/methods/LICENSE +0 -24
- gaia/eval/webapp/node_modules/methods/README.md +0 -51
- gaia/eval/webapp/node_modules/methods/index.js +0 -69
- gaia/eval/webapp/node_modules/methods/package.json +0 -36
- gaia/eval/webapp/node_modules/mime/.npmignore +0 -0
- gaia/eval/webapp/node_modules/mime/CHANGELOG.md +0 -164
- gaia/eval/webapp/node_modules/mime/LICENSE +0 -21
- gaia/eval/webapp/node_modules/mime/README.md +0 -90
- gaia/eval/webapp/node_modules/mime/cli.js +0 -8
- gaia/eval/webapp/node_modules/mime/mime.js +0 -108
- gaia/eval/webapp/node_modules/mime/package.json +0 -44
- gaia/eval/webapp/node_modules/mime/src/build.js +0 -53
- gaia/eval/webapp/node_modules/mime/src/test.js +0 -60
- gaia/eval/webapp/node_modules/mime/types.json +0 -1
- gaia/eval/webapp/node_modules/mime-db/HISTORY.md +0 -507
- gaia/eval/webapp/node_modules/mime-db/LICENSE +0 -23
- gaia/eval/webapp/node_modules/mime-db/README.md +0 -100
- gaia/eval/webapp/node_modules/mime-db/db.json +0 -8519
- gaia/eval/webapp/node_modules/mime-db/index.js +0 -12
- gaia/eval/webapp/node_modules/mime-db/package.json +0 -60
- gaia/eval/webapp/node_modules/mime-types/HISTORY.md +0 -397
- gaia/eval/webapp/node_modules/mime-types/LICENSE +0 -23
- gaia/eval/webapp/node_modules/mime-types/README.md +0 -113
- gaia/eval/webapp/node_modules/mime-types/index.js +0 -188
- gaia/eval/webapp/node_modules/mime-types/package.json +0 -44
- gaia/eval/webapp/node_modules/ms/index.js +0 -152
- gaia/eval/webapp/node_modules/ms/license.md +0 -21
- gaia/eval/webapp/node_modules/ms/package.json +0 -37
- gaia/eval/webapp/node_modules/ms/readme.md +0 -51
- gaia/eval/webapp/node_modules/negotiator/HISTORY.md +0 -108
- gaia/eval/webapp/node_modules/negotiator/LICENSE +0 -24
- gaia/eval/webapp/node_modules/negotiator/README.md +0 -203
- gaia/eval/webapp/node_modules/negotiator/index.js +0 -82
- gaia/eval/webapp/node_modules/negotiator/lib/charset.js +0 -169
- gaia/eval/webapp/node_modules/negotiator/lib/encoding.js +0 -184
- gaia/eval/webapp/node_modules/negotiator/lib/language.js +0 -179
- gaia/eval/webapp/node_modules/negotiator/lib/mediaType.js +0 -294
- gaia/eval/webapp/node_modules/negotiator/package.json +0 -42
- gaia/eval/webapp/node_modules/object-inspect/.eslintrc +0 -53
- gaia/eval/webapp/node_modules/object-inspect/.github/FUNDING.yml +0 -12
- gaia/eval/webapp/node_modules/object-inspect/.nycrc +0 -13
- gaia/eval/webapp/node_modules/object-inspect/CHANGELOG.md +0 -424
- gaia/eval/webapp/node_modules/object-inspect/LICENSE +0 -21
- gaia/eval/webapp/node_modules/object-inspect/example/all.js +0 -23
- gaia/eval/webapp/node_modules/object-inspect/example/circular.js +0 -6
- gaia/eval/webapp/node_modules/object-inspect/example/fn.js +0 -5
- gaia/eval/webapp/node_modules/object-inspect/example/inspect.js +0 -10
- gaia/eval/webapp/node_modules/object-inspect/index.js +0 -544
- gaia/eval/webapp/node_modules/object-inspect/package-support.json +0 -20
- gaia/eval/webapp/node_modules/object-inspect/package.json +0 -105
- gaia/eval/webapp/node_modules/object-inspect/readme.markdown +0 -84
- gaia/eval/webapp/node_modules/object-inspect/test/bigint.js +0 -58
- gaia/eval/webapp/node_modules/object-inspect/test/browser/dom.js +0 -15
- gaia/eval/webapp/node_modules/object-inspect/test/circular.js +0 -16
- gaia/eval/webapp/node_modules/object-inspect/test/deep.js +0 -12
- gaia/eval/webapp/node_modules/object-inspect/test/element.js +0 -53
- gaia/eval/webapp/node_modules/object-inspect/test/err.js +0 -48
- gaia/eval/webapp/node_modules/object-inspect/test/fakes.js +0 -29
- gaia/eval/webapp/node_modules/object-inspect/test/fn.js +0 -76
- gaia/eval/webapp/node_modules/object-inspect/test/global.js +0 -17
- gaia/eval/webapp/node_modules/object-inspect/test/has.js +0 -15
- gaia/eval/webapp/node_modules/object-inspect/test/holes.js +0 -15
- gaia/eval/webapp/node_modules/object-inspect/test/indent-option.js +0 -271
- gaia/eval/webapp/node_modules/object-inspect/test/inspect.js +0 -139
- gaia/eval/webapp/node_modules/object-inspect/test/lowbyte.js +0 -12
- gaia/eval/webapp/node_modules/object-inspect/test/number.js +0 -58
- gaia/eval/webapp/node_modules/object-inspect/test/quoteStyle.js +0 -26
- gaia/eval/webapp/node_modules/object-inspect/test/toStringTag.js +0 -40
- gaia/eval/webapp/node_modules/object-inspect/test/undef.js +0 -12
- gaia/eval/webapp/node_modules/object-inspect/test/values.js +0 -261
- gaia/eval/webapp/node_modules/object-inspect/test-core-js.js +0 -26
- gaia/eval/webapp/node_modules/object-inspect/util.inspect.js +0 -1
- gaia/eval/webapp/node_modules/on-finished/HISTORY.md +0 -98
- gaia/eval/webapp/node_modules/on-finished/LICENSE +0 -23
- gaia/eval/webapp/node_modules/on-finished/README.md +0 -162
- gaia/eval/webapp/node_modules/on-finished/index.js +0 -234
- gaia/eval/webapp/node_modules/on-finished/package.json +0 -39
- gaia/eval/webapp/node_modules/parseurl/HISTORY.md +0 -58
- gaia/eval/webapp/node_modules/parseurl/LICENSE +0 -24
- gaia/eval/webapp/node_modules/parseurl/README.md +0 -133
- gaia/eval/webapp/node_modules/parseurl/index.js +0 -158
- gaia/eval/webapp/node_modules/parseurl/package.json +0 -40
- gaia/eval/webapp/node_modules/path/.npmignore +0 -1
- gaia/eval/webapp/node_modules/path/LICENSE +0 -18
- gaia/eval/webapp/node_modules/path/README.md +0 -15
- gaia/eval/webapp/node_modules/path/package.json +0 -24
- gaia/eval/webapp/node_modules/path/path.js +0 -628
- gaia/eval/webapp/node_modules/path-to-regexp/LICENSE +0 -21
- gaia/eval/webapp/node_modules/path-to-regexp/Readme.md +0 -35
- gaia/eval/webapp/node_modules/path-to-regexp/index.js +0 -156
- gaia/eval/webapp/node_modules/path-to-regexp/package.json +0 -30
- gaia/eval/webapp/node_modules/process/.eslintrc +0 -21
- gaia/eval/webapp/node_modules/process/LICENSE +0 -22
- gaia/eval/webapp/node_modules/process/README.md +0 -26
- gaia/eval/webapp/node_modules/process/browser.js +0 -184
- gaia/eval/webapp/node_modules/process/index.js +0 -2
- gaia/eval/webapp/node_modules/process/package.json +0 -27
- gaia/eval/webapp/node_modules/process/test.js +0 -199
- gaia/eval/webapp/node_modules/proxy-addr/HISTORY.md +0 -161
- gaia/eval/webapp/node_modules/proxy-addr/LICENSE +0 -22
- gaia/eval/webapp/node_modules/proxy-addr/README.md +0 -139
- gaia/eval/webapp/node_modules/proxy-addr/index.js +0 -327
- gaia/eval/webapp/node_modules/proxy-addr/package.json +0 -47
- gaia/eval/webapp/node_modules/qs/.editorconfig +0 -46
- gaia/eval/webapp/node_modules/qs/.eslintrc +0 -38
- gaia/eval/webapp/node_modules/qs/.github/FUNDING.yml +0 -12
- gaia/eval/webapp/node_modules/qs/.nycrc +0 -13
- gaia/eval/webapp/node_modules/qs/CHANGELOG.md +0 -600
- gaia/eval/webapp/node_modules/qs/LICENSE.md +0 -29
- gaia/eval/webapp/node_modules/qs/README.md +0 -709
- gaia/eval/webapp/node_modules/qs/dist/qs.js +0 -90
- gaia/eval/webapp/node_modules/qs/lib/formats.js +0 -23
- gaia/eval/webapp/node_modules/qs/lib/index.js +0 -11
- gaia/eval/webapp/node_modules/qs/lib/parse.js +0 -296
- gaia/eval/webapp/node_modules/qs/lib/stringify.js +0 -351
- gaia/eval/webapp/node_modules/qs/lib/utils.js +0 -265
- gaia/eval/webapp/node_modules/qs/package.json +0 -91
- gaia/eval/webapp/node_modules/qs/test/empty-keys-cases.js +0 -267
- gaia/eval/webapp/node_modules/qs/test/parse.js +0 -1170
- gaia/eval/webapp/node_modules/qs/test/stringify.js +0 -1298
- gaia/eval/webapp/node_modules/qs/test/utils.js +0 -136
- gaia/eval/webapp/node_modules/range-parser/HISTORY.md +0 -56
- gaia/eval/webapp/node_modules/range-parser/LICENSE +0 -23
- gaia/eval/webapp/node_modules/range-parser/README.md +0 -84
- gaia/eval/webapp/node_modules/range-parser/index.js +0 -162
- gaia/eval/webapp/node_modules/range-parser/package.json +0 -44
- gaia/eval/webapp/node_modules/raw-body/HISTORY.md +0 -308
- gaia/eval/webapp/node_modules/raw-body/LICENSE +0 -22
- gaia/eval/webapp/node_modules/raw-body/README.md +0 -223
- gaia/eval/webapp/node_modules/raw-body/SECURITY.md +0 -24
- gaia/eval/webapp/node_modules/raw-body/index.d.ts +0 -87
- gaia/eval/webapp/node_modules/raw-body/index.js +0 -336
- gaia/eval/webapp/node_modules/raw-body/package.json +0 -49
- gaia/eval/webapp/node_modules/safe-buffer/LICENSE +0 -21
- gaia/eval/webapp/node_modules/safe-buffer/README.md +0 -584
- gaia/eval/webapp/node_modules/safe-buffer/index.d.ts +0 -187
- gaia/eval/webapp/node_modules/safe-buffer/index.js +0 -65
- gaia/eval/webapp/node_modules/safe-buffer/package.json +0 -51
- gaia/eval/webapp/node_modules/safer-buffer/LICENSE +0 -21
- gaia/eval/webapp/node_modules/safer-buffer/Porting-Buffer.md +0 -268
- gaia/eval/webapp/node_modules/safer-buffer/Readme.md +0 -156
- gaia/eval/webapp/node_modules/safer-buffer/dangerous.js +0 -58
- gaia/eval/webapp/node_modules/safer-buffer/package.json +0 -34
- gaia/eval/webapp/node_modules/safer-buffer/safer.js +0 -77
- gaia/eval/webapp/node_modules/safer-buffer/tests.js +0 -406
- gaia/eval/webapp/node_modules/send/HISTORY.md +0 -526
- gaia/eval/webapp/node_modules/send/LICENSE +0 -23
- gaia/eval/webapp/node_modules/send/README.md +0 -327
- gaia/eval/webapp/node_modules/send/SECURITY.md +0 -24
- gaia/eval/webapp/node_modules/send/index.js +0 -1142
- gaia/eval/webapp/node_modules/send/node_modules/encodeurl/HISTORY.md +0 -14
- gaia/eval/webapp/node_modules/send/node_modules/encodeurl/LICENSE +0 -22
- gaia/eval/webapp/node_modules/send/node_modules/encodeurl/README.md +0 -128
- gaia/eval/webapp/node_modules/send/node_modules/encodeurl/index.js +0 -60
- gaia/eval/webapp/node_modules/send/node_modules/encodeurl/package.json +0 -40
- gaia/eval/webapp/node_modules/send/node_modules/ms/index.js +0 -162
- gaia/eval/webapp/node_modules/send/node_modules/ms/license.md +0 -21
- gaia/eval/webapp/node_modules/send/node_modules/ms/package.json +0 -38
- gaia/eval/webapp/node_modules/send/node_modules/ms/readme.md +0 -59
- gaia/eval/webapp/node_modules/send/package.json +0 -62
- gaia/eval/webapp/node_modules/serve-static/HISTORY.md +0 -487
- gaia/eval/webapp/node_modules/serve-static/LICENSE +0 -25
- gaia/eval/webapp/node_modules/serve-static/README.md +0 -257
- gaia/eval/webapp/node_modules/serve-static/index.js +0 -209
- gaia/eval/webapp/node_modules/serve-static/package.json +0 -42
- gaia/eval/webapp/node_modules/setprototypeof/LICENSE +0 -13
- gaia/eval/webapp/node_modules/setprototypeof/README.md +0 -31
- gaia/eval/webapp/node_modules/setprototypeof/index.d.ts +0 -2
- gaia/eval/webapp/node_modules/setprototypeof/index.js +0 -17
- gaia/eval/webapp/node_modules/setprototypeof/package.json +0 -38
- gaia/eval/webapp/node_modules/setprototypeof/test/index.js +0 -24
- gaia/eval/webapp/node_modules/side-channel/.editorconfig +0 -9
- gaia/eval/webapp/node_modules/side-channel/.eslintrc +0 -12
- gaia/eval/webapp/node_modules/side-channel/.github/FUNDING.yml +0 -12
- gaia/eval/webapp/node_modules/side-channel/.nycrc +0 -13
- gaia/eval/webapp/node_modules/side-channel/CHANGELOG.md +0 -110
- gaia/eval/webapp/node_modules/side-channel/LICENSE +0 -21
- gaia/eval/webapp/node_modules/side-channel/README.md +0 -61
- gaia/eval/webapp/node_modules/side-channel/index.d.ts +0 -14
- gaia/eval/webapp/node_modules/side-channel/index.js +0 -43
- gaia/eval/webapp/node_modules/side-channel/package.json +0 -85
- gaia/eval/webapp/node_modules/side-channel/test/index.js +0 -104
- gaia/eval/webapp/node_modules/side-channel/tsconfig.json +0 -9
- gaia/eval/webapp/node_modules/side-channel-list/.editorconfig +0 -9
- gaia/eval/webapp/node_modules/side-channel-list/.eslintrc +0 -11
- gaia/eval/webapp/node_modules/side-channel-list/.github/FUNDING.yml +0 -12
- gaia/eval/webapp/node_modules/side-channel-list/.nycrc +0 -13
- gaia/eval/webapp/node_modules/side-channel-list/CHANGELOG.md +0 -15
- gaia/eval/webapp/node_modules/side-channel-list/LICENSE +0 -21
- gaia/eval/webapp/node_modules/side-channel-list/README.md +0 -62
- gaia/eval/webapp/node_modules/side-channel-list/index.d.ts +0 -13
- gaia/eval/webapp/node_modules/side-channel-list/index.js +0 -113
- gaia/eval/webapp/node_modules/side-channel-list/list.d.ts +0 -14
- gaia/eval/webapp/node_modules/side-channel-list/package.json +0 -77
- gaia/eval/webapp/node_modules/side-channel-list/test/index.js +0 -104
- gaia/eval/webapp/node_modules/side-channel-list/tsconfig.json +0 -9
- gaia/eval/webapp/node_modules/side-channel-map/.editorconfig +0 -9
- gaia/eval/webapp/node_modules/side-channel-map/.eslintrc +0 -11
- gaia/eval/webapp/node_modules/side-channel-map/.github/FUNDING.yml +0 -12
- gaia/eval/webapp/node_modules/side-channel-map/.nycrc +0 -13
- gaia/eval/webapp/node_modules/side-channel-map/CHANGELOG.md +0 -22
- gaia/eval/webapp/node_modules/side-channel-map/LICENSE +0 -21
- gaia/eval/webapp/node_modules/side-channel-map/README.md +0 -62
- gaia/eval/webapp/node_modules/side-channel-map/index.d.ts +0 -15
- gaia/eval/webapp/node_modules/side-channel-map/index.js +0 -68
- gaia/eval/webapp/node_modules/side-channel-map/package.json +0 -80
- gaia/eval/webapp/node_modules/side-channel-map/test/index.js +0 -114
- gaia/eval/webapp/node_modules/side-channel-map/tsconfig.json +0 -9
- gaia/eval/webapp/node_modules/side-channel-weakmap/.editorconfig +0 -9
- gaia/eval/webapp/node_modules/side-channel-weakmap/.eslintrc +0 -12
- gaia/eval/webapp/node_modules/side-channel-weakmap/.github/FUNDING.yml +0 -12
- gaia/eval/webapp/node_modules/side-channel-weakmap/.nycrc +0 -13
- gaia/eval/webapp/node_modules/side-channel-weakmap/CHANGELOG.md +0 -28
- gaia/eval/webapp/node_modules/side-channel-weakmap/LICENSE +0 -21
- gaia/eval/webapp/node_modules/side-channel-weakmap/README.md +0 -62
- gaia/eval/webapp/node_modules/side-channel-weakmap/index.d.ts +0 -15
- gaia/eval/webapp/node_modules/side-channel-weakmap/index.js +0 -84
- gaia/eval/webapp/node_modules/side-channel-weakmap/package.json +0 -87
- gaia/eval/webapp/node_modules/side-channel-weakmap/test/index.js +0 -114
- gaia/eval/webapp/node_modules/side-channel-weakmap/tsconfig.json +0 -9
- gaia/eval/webapp/node_modules/statuses/HISTORY.md +0 -82
- gaia/eval/webapp/node_modules/statuses/LICENSE +0 -23
- gaia/eval/webapp/node_modules/statuses/README.md +0 -136
- gaia/eval/webapp/node_modules/statuses/codes.json +0 -65
- gaia/eval/webapp/node_modules/statuses/index.js +0 -146
- gaia/eval/webapp/node_modules/statuses/package.json +0 -49
- gaia/eval/webapp/node_modules/toidentifier/HISTORY.md +0 -9
- gaia/eval/webapp/node_modules/toidentifier/LICENSE +0 -21
- gaia/eval/webapp/node_modules/toidentifier/README.md +0 -61
- gaia/eval/webapp/node_modules/toidentifier/index.js +0 -32
- gaia/eval/webapp/node_modules/toidentifier/package.json +0 -38
- gaia/eval/webapp/node_modules/type-is/HISTORY.md +0 -259
- gaia/eval/webapp/node_modules/type-is/LICENSE +0 -23
- gaia/eval/webapp/node_modules/type-is/README.md +0 -170
- gaia/eval/webapp/node_modules/type-is/index.js +0 -266
- gaia/eval/webapp/node_modules/type-is/package.json +0 -45
- gaia/eval/webapp/node_modules/unpipe/HISTORY.md +0 -4
- gaia/eval/webapp/node_modules/unpipe/LICENSE +0 -22
- gaia/eval/webapp/node_modules/unpipe/README.md +0 -43
- gaia/eval/webapp/node_modules/unpipe/index.js +0 -69
- gaia/eval/webapp/node_modules/unpipe/package.json +0 -27
- gaia/eval/webapp/node_modules/util/LICENSE +0 -18
- gaia/eval/webapp/node_modules/util/README.md +0 -15
- gaia/eval/webapp/node_modules/util/node_modules/inherits/LICENSE +0 -16
- gaia/eval/webapp/node_modules/util/node_modules/inherits/README.md +0 -42
- gaia/eval/webapp/node_modules/util/node_modules/inherits/inherits.js +0 -7
- gaia/eval/webapp/node_modules/util/node_modules/inherits/inherits_browser.js +0 -23
- gaia/eval/webapp/node_modules/util/node_modules/inherits/package.json +0 -29
- gaia/eval/webapp/node_modules/util/package.json +0 -35
- gaia/eval/webapp/node_modules/util/support/isBuffer.js +0 -3
- gaia/eval/webapp/node_modules/util/support/isBufferBrowser.js +0 -6
- gaia/eval/webapp/node_modules/util/util.js +0 -586
- gaia/eval/webapp/node_modules/utils-merge/.npmignore +0 -9
- gaia/eval/webapp/node_modules/utils-merge/LICENSE +0 -20
- gaia/eval/webapp/node_modules/utils-merge/README.md +0 -34
- gaia/eval/webapp/node_modules/utils-merge/index.js +0 -23
- gaia/eval/webapp/node_modules/utils-merge/package.json +0 -40
- gaia/eval/webapp/node_modules/vary/HISTORY.md +0 -39
- gaia/eval/webapp/node_modules/vary/LICENSE +0 -22
- gaia/eval/webapp/node_modules/vary/README.md +0 -101
- gaia/eval/webapp/node_modules/vary/index.js +0 -149
- gaia/eval/webapp/node_modules/vary/package.json +0 -43
- {amd_gaia-0.14.1.dist-info → amd_gaia-0.14.3.dist-info}/WHEEL +0 -0
- {amd_gaia-0.14.1.dist-info → amd_gaia-0.14.3.dist-info}/licenses/LICENSE.md +0 -0
- {amd_gaia-0.14.1.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())
|