amd-gaia 0.14.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (800) hide show
  1. amd_gaia-0.14.1.dist-info/METADATA +768 -0
  2. amd_gaia-0.14.1.dist-info/RECORD +800 -0
  3. amd_gaia-0.14.1.dist-info/WHEEL +5 -0
  4. amd_gaia-0.14.1.dist-info/entry_points.txt +5 -0
  5. amd_gaia-0.14.1.dist-info/licenses/LICENSE.md +21 -0
  6. amd_gaia-0.14.1.dist-info/top_level.txt +1 -0
  7. gaia/__init__.py +2 -0
  8. gaia/agents/__init__.py +19 -0
  9. gaia/agents/base/__init__.py +9 -0
  10. gaia/agents/base/agent.py +2072 -0
  11. gaia/agents/base/api_agent.py +120 -0
  12. gaia/agents/base/console.py +1457 -0
  13. gaia/agents/base/mcp_agent.py +86 -0
  14. gaia/agents/base/tools.py +83 -0
  15. gaia/agents/blender/agent.py +556 -0
  16. gaia/agents/blender/agent_simple.py +135 -0
  17. gaia/agents/blender/app.py +211 -0
  18. gaia/agents/blender/app_simple.py +41 -0
  19. gaia/agents/blender/core/__init__.py +16 -0
  20. gaia/agents/blender/core/materials.py +506 -0
  21. gaia/agents/blender/core/objects.py +316 -0
  22. gaia/agents/blender/core/rendering.py +225 -0
  23. gaia/agents/blender/core/scene.py +220 -0
  24. gaia/agents/blender/core/view.py +146 -0
  25. gaia/agents/chat/__init__.py +9 -0
  26. gaia/agents/chat/agent.py +975 -0
  27. gaia/agents/chat/app.py +1058 -0
  28. gaia/agents/chat/session.py +508 -0
  29. gaia/agents/chat/tools/__init__.py +15 -0
  30. gaia/agents/chat/tools/file_tools.py +96 -0
  31. gaia/agents/chat/tools/rag_tools.py +1729 -0
  32. gaia/agents/chat/tools/shell_tools.py +436 -0
  33. gaia/agents/code/__init__.py +7 -0
  34. gaia/agents/code/agent.py +547 -0
  35. gaia/agents/code/app.py +266 -0
  36. gaia/agents/code/models.py +135 -0
  37. gaia/agents/code/orchestration/__init__.py +24 -0
  38. gaia/agents/code/orchestration/checklist_executor.py +1739 -0
  39. gaia/agents/code/orchestration/checklist_generator.py +709 -0
  40. gaia/agents/code/orchestration/factories/__init__.py +9 -0
  41. gaia/agents/code/orchestration/factories/base.py +63 -0
  42. gaia/agents/code/orchestration/factories/nextjs_factory.py +118 -0
  43. gaia/agents/code/orchestration/factories/python_factory.py +106 -0
  44. gaia/agents/code/orchestration/orchestrator.py +610 -0
  45. gaia/agents/code/orchestration/project_analyzer.py +391 -0
  46. gaia/agents/code/orchestration/steps/__init__.py +67 -0
  47. gaia/agents/code/orchestration/steps/base.py +188 -0
  48. gaia/agents/code/orchestration/steps/error_handler.py +314 -0
  49. gaia/agents/code/orchestration/steps/nextjs.py +828 -0
  50. gaia/agents/code/orchestration/steps/python.py +307 -0
  51. gaia/agents/code/orchestration/template_catalog.py +463 -0
  52. gaia/agents/code/orchestration/workflows/__init__.py +14 -0
  53. gaia/agents/code/orchestration/workflows/base.py +80 -0
  54. gaia/agents/code/orchestration/workflows/nextjs.py +186 -0
  55. gaia/agents/code/orchestration/workflows/python.py +94 -0
  56. gaia/agents/code/prompts/__init__.py +11 -0
  57. gaia/agents/code/prompts/base_prompt.py +77 -0
  58. gaia/agents/code/prompts/code_patterns.py +1925 -0
  59. gaia/agents/code/prompts/nextjs_prompt.py +40 -0
  60. gaia/agents/code/prompts/python_prompt.py +109 -0
  61. gaia/agents/code/schema_inference.py +365 -0
  62. gaia/agents/code/system_prompt.py +41 -0
  63. gaia/agents/code/tools/__init__.py +42 -0
  64. gaia/agents/code/tools/cli_tools.py +1138 -0
  65. gaia/agents/code/tools/code_formatting.py +319 -0
  66. gaia/agents/code/tools/code_tools.py +769 -0
  67. gaia/agents/code/tools/error_fixing.py +1347 -0
  68. gaia/agents/code/tools/external_tools.py +180 -0
  69. gaia/agents/code/tools/file_io.py +845 -0
  70. gaia/agents/code/tools/prisma_tools.py +190 -0
  71. gaia/agents/code/tools/project_management.py +1016 -0
  72. gaia/agents/code/tools/testing.py +321 -0
  73. gaia/agents/code/tools/typescript_tools.py +122 -0
  74. gaia/agents/code/tools/validation_parsing.py +461 -0
  75. gaia/agents/code/tools/validation_tools.py +803 -0
  76. gaia/agents/code/tools/web_dev_tools.py +1744 -0
  77. gaia/agents/code/validators/__init__.py +16 -0
  78. gaia/agents/code/validators/antipattern_checker.py +241 -0
  79. gaia/agents/code/validators/ast_analyzer.py +197 -0
  80. gaia/agents/code/validators/requirements_validator.py +145 -0
  81. gaia/agents/code/validators/syntax_validator.py +171 -0
  82. gaia/agents/docker/__init__.py +7 -0
  83. gaia/agents/docker/agent.py +642 -0
  84. gaia/agents/jira/__init__.py +11 -0
  85. gaia/agents/jira/agent.py +894 -0
  86. gaia/agents/jira/jql_templates.py +299 -0
  87. gaia/agents/routing/__init__.py +7 -0
  88. gaia/agents/routing/agent.py +512 -0
  89. gaia/agents/routing/system_prompt.py +75 -0
  90. gaia/api/__init__.py +23 -0
  91. gaia/api/agent_registry.py +238 -0
  92. gaia/api/app.py +305 -0
  93. gaia/api/openai_server.py +575 -0
  94. gaia/api/schemas.py +186 -0
  95. gaia/api/sse_handler.py +370 -0
  96. gaia/apps/__init__.py +4 -0
  97. gaia/apps/llm/__init__.py +6 -0
  98. gaia/apps/llm/app.py +169 -0
  99. gaia/apps/summarize/app.py +633 -0
  100. gaia/apps/summarize/html_viewer.py +133 -0
  101. gaia/apps/summarize/pdf_formatter.py +284 -0
  102. gaia/audio/__init__.py +2 -0
  103. gaia/audio/audio_client.py +439 -0
  104. gaia/audio/audio_recorder.py +269 -0
  105. gaia/audio/kokoro_tts.py +599 -0
  106. gaia/audio/whisper_asr.py +432 -0
  107. gaia/chat/__init__.py +16 -0
  108. gaia/chat/app.py +430 -0
  109. gaia/chat/prompts.py +522 -0
  110. gaia/chat/sdk.py +1200 -0
  111. gaia/cli.py +5621 -0
  112. gaia/eval/batch_experiment.py +2332 -0
  113. gaia/eval/claude.py +542 -0
  114. gaia/eval/config.py +37 -0
  115. gaia/eval/email_generator.py +512 -0
  116. gaia/eval/eval.py +3179 -0
  117. gaia/eval/groundtruth.py +1130 -0
  118. gaia/eval/transcript_generator.py +582 -0
  119. gaia/eval/webapp/README.md +168 -0
  120. gaia/eval/webapp/node_modules/.bin/mime +16 -0
  121. gaia/eval/webapp/node_modules/.bin/mime.cmd +17 -0
  122. gaia/eval/webapp/node_modules/.bin/mime.ps1 +28 -0
  123. gaia/eval/webapp/node_modules/.package-lock.json +865 -0
  124. gaia/eval/webapp/node_modules/accepts/HISTORY.md +243 -0
  125. gaia/eval/webapp/node_modules/accepts/LICENSE +23 -0
  126. gaia/eval/webapp/node_modules/accepts/README.md +140 -0
  127. gaia/eval/webapp/node_modules/accepts/index.js +238 -0
  128. gaia/eval/webapp/node_modules/accepts/package.json +47 -0
  129. gaia/eval/webapp/node_modules/array-flatten/LICENSE +21 -0
  130. gaia/eval/webapp/node_modules/array-flatten/README.md +43 -0
  131. gaia/eval/webapp/node_modules/array-flatten/array-flatten.js +64 -0
  132. gaia/eval/webapp/node_modules/array-flatten/package.json +39 -0
  133. gaia/eval/webapp/node_modules/body-parser/HISTORY.md +672 -0
  134. gaia/eval/webapp/node_modules/body-parser/LICENSE +23 -0
  135. gaia/eval/webapp/node_modules/body-parser/README.md +476 -0
  136. gaia/eval/webapp/node_modules/body-parser/SECURITY.md +25 -0
  137. gaia/eval/webapp/node_modules/body-parser/index.js +156 -0
  138. gaia/eval/webapp/node_modules/body-parser/lib/read.js +205 -0
  139. gaia/eval/webapp/node_modules/body-parser/lib/types/json.js +247 -0
  140. gaia/eval/webapp/node_modules/body-parser/lib/types/raw.js +101 -0
  141. gaia/eval/webapp/node_modules/body-parser/lib/types/text.js +121 -0
  142. gaia/eval/webapp/node_modules/body-parser/lib/types/urlencoded.js +307 -0
  143. gaia/eval/webapp/node_modules/body-parser/package.json +56 -0
  144. gaia/eval/webapp/node_modules/bytes/History.md +97 -0
  145. gaia/eval/webapp/node_modules/bytes/LICENSE +23 -0
  146. gaia/eval/webapp/node_modules/bytes/Readme.md +152 -0
  147. gaia/eval/webapp/node_modules/bytes/index.js +170 -0
  148. gaia/eval/webapp/node_modules/bytes/package.json +42 -0
  149. gaia/eval/webapp/node_modules/call-bind-apply-helpers/.eslintrc +17 -0
  150. gaia/eval/webapp/node_modules/call-bind-apply-helpers/.github/FUNDING.yml +12 -0
  151. gaia/eval/webapp/node_modules/call-bind-apply-helpers/.nycrc +9 -0
  152. gaia/eval/webapp/node_modules/call-bind-apply-helpers/CHANGELOG.md +30 -0
  153. gaia/eval/webapp/node_modules/call-bind-apply-helpers/LICENSE +21 -0
  154. gaia/eval/webapp/node_modules/call-bind-apply-helpers/README.md +62 -0
  155. gaia/eval/webapp/node_modules/call-bind-apply-helpers/actualApply.d.ts +1 -0
  156. gaia/eval/webapp/node_modules/call-bind-apply-helpers/actualApply.js +10 -0
  157. gaia/eval/webapp/node_modules/call-bind-apply-helpers/applyBind.d.ts +19 -0
  158. gaia/eval/webapp/node_modules/call-bind-apply-helpers/applyBind.js +10 -0
  159. gaia/eval/webapp/node_modules/call-bind-apply-helpers/functionApply.d.ts +1 -0
  160. gaia/eval/webapp/node_modules/call-bind-apply-helpers/functionApply.js +4 -0
  161. gaia/eval/webapp/node_modules/call-bind-apply-helpers/functionCall.d.ts +1 -0
  162. gaia/eval/webapp/node_modules/call-bind-apply-helpers/functionCall.js +4 -0
  163. gaia/eval/webapp/node_modules/call-bind-apply-helpers/index.d.ts +64 -0
  164. gaia/eval/webapp/node_modules/call-bind-apply-helpers/index.js +15 -0
  165. gaia/eval/webapp/node_modules/call-bind-apply-helpers/package.json +85 -0
  166. gaia/eval/webapp/node_modules/call-bind-apply-helpers/reflectApply.d.ts +3 -0
  167. gaia/eval/webapp/node_modules/call-bind-apply-helpers/reflectApply.js +4 -0
  168. gaia/eval/webapp/node_modules/call-bind-apply-helpers/test/index.js +63 -0
  169. gaia/eval/webapp/node_modules/call-bind-apply-helpers/tsconfig.json +9 -0
  170. gaia/eval/webapp/node_modules/call-bound/.eslintrc +13 -0
  171. gaia/eval/webapp/node_modules/call-bound/.github/FUNDING.yml +12 -0
  172. gaia/eval/webapp/node_modules/call-bound/.nycrc +9 -0
  173. gaia/eval/webapp/node_modules/call-bound/CHANGELOG.md +42 -0
  174. gaia/eval/webapp/node_modules/call-bound/LICENSE +21 -0
  175. gaia/eval/webapp/node_modules/call-bound/README.md +53 -0
  176. gaia/eval/webapp/node_modules/call-bound/index.d.ts +94 -0
  177. gaia/eval/webapp/node_modules/call-bound/index.js +19 -0
  178. gaia/eval/webapp/node_modules/call-bound/package.json +99 -0
  179. gaia/eval/webapp/node_modules/call-bound/test/index.js +61 -0
  180. gaia/eval/webapp/node_modules/call-bound/tsconfig.json +10 -0
  181. gaia/eval/webapp/node_modules/content-disposition/HISTORY.md +60 -0
  182. gaia/eval/webapp/node_modules/content-disposition/LICENSE +22 -0
  183. gaia/eval/webapp/node_modules/content-disposition/README.md +142 -0
  184. gaia/eval/webapp/node_modules/content-disposition/index.js +458 -0
  185. gaia/eval/webapp/node_modules/content-disposition/package.json +44 -0
  186. gaia/eval/webapp/node_modules/content-type/HISTORY.md +29 -0
  187. gaia/eval/webapp/node_modules/content-type/LICENSE +22 -0
  188. gaia/eval/webapp/node_modules/content-type/README.md +94 -0
  189. gaia/eval/webapp/node_modules/content-type/index.js +225 -0
  190. gaia/eval/webapp/node_modules/content-type/package.json +42 -0
  191. gaia/eval/webapp/node_modules/cookie/LICENSE +24 -0
  192. gaia/eval/webapp/node_modules/cookie/README.md +317 -0
  193. gaia/eval/webapp/node_modules/cookie/SECURITY.md +25 -0
  194. gaia/eval/webapp/node_modules/cookie/index.js +334 -0
  195. gaia/eval/webapp/node_modules/cookie/package.json +44 -0
  196. gaia/eval/webapp/node_modules/cookie-signature/.npmignore +4 -0
  197. gaia/eval/webapp/node_modules/cookie-signature/History.md +38 -0
  198. gaia/eval/webapp/node_modules/cookie-signature/Readme.md +42 -0
  199. gaia/eval/webapp/node_modules/cookie-signature/index.js +51 -0
  200. gaia/eval/webapp/node_modules/cookie-signature/package.json +18 -0
  201. gaia/eval/webapp/node_modules/debug/.coveralls.yml +1 -0
  202. gaia/eval/webapp/node_modules/debug/.eslintrc +11 -0
  203. gaia/eval/webapp/node_modules/debug/.npmignore +9 -0
  204. gaia/eval/webapp/node_modules/debug/.travis.yml +14 -0
  205. gaia/eval/webapp/node_modules/debug/CHANGELOG.md +362 -0
  206. gaia/eval/webapp/node_modules/debug/LICENSE +19 -0
  207. gaia/eval/webapp/node_modules/debug/Makefile +50 -0
  208. gaia/eval/webapp/node_modules/debug/README.md +312 -0
  209. gaia/eval/webapp/node_modules/debug/component.json +19 -0
  210. gaia/eval/webapp/node_modules/debug/karma.conf.js +70 -0
  211. gaia/eval/webapp/node_modules/debug/node.js +1 -0
  212. gaia/eval/webapp/node_modules/debug/package.json +49 -0
  213. gaia/eval/webapp/node_modules/debug/src/browser.js +185 -0
  214. gaia/eval/webapp/node_modules/debug/src/debug.js +202 -0
  215. gaia/eval/webapp/node_modules/debug/src/index.js +10 -0
  216. gaia/eval/webapp/node_modules/debug/src/inspector-log.js +15 -0
  217. gaia/eval/webapp/node_modules/debug/src/node.js +248 -0
  218. gaia/eval/webapp/node_modules/depd/History.md +103 -0
  219. gaia/eval/webapp/node_modules/depd/LICENSE +22 -0
  220. gaia/eval/webapp/node_modules/depd/Readme.md +280 -0
  221. gaia/eval/webapp/node_modules/depd/index.js +538 -0
  222. gaia/eval/webapp/node_modules/depd/lib/browser/index.js +77 -0
  223. gaia/eval/webapp/node_modules/depd/package.json +45 -0
  224. gaia/eval/webapp/node_modules/destroy/LICENSE +23 -0
  225. gaia/eval/webapp/node_modules/destroy/README.md +63 -0
  226. gaia/eval/webapp/node_modules/destroy/index.js +209 -0
  227. gaia/eval/webapp/node_modules/destroy/package.json +48 -0
  228. gaia/eval/webapp/node_modules/dunder-proto/.eslintrc +5 -0
  229. gaia/eval/webapp/node_modules/dunder-proto/.github/FUNDING.yml +12 -0
  230. gaia/eval/webapp/node_modules/dunder-proto/.nycrc +13 -0
  231. gaia/eval/webapp/node_modules/dunder-proto/CHANGELOG.md +24 -0
  232. gaia/eval/webapp/node_modules/dunder-proto/LICENSE +21 -0
  233. gaia/eval/webapp/node_modules/dunder-proto/README.md +54 -0
  234. gaia/eval/webapp/node_modules/dunder-proto/get.d.ts +5 -0
  235. gaia/eval/webapp/node_modules/dunder-proto/get.js +30 -0
  236. gaia/eval/webapp/node_modules/dunder-proto/package.json +76 -0
  237. gaia/eval/webapp/node_modules/dunder-proto/set.d.ts +5 -0
  238. gaia/eval/webapp/node_modules/dunder-proto/set.js +35 -0
  239. gaia/eval/webapp/node_modules/dunder-proto/test/get.js +34 -0
  240. gaia/eval/webapp/node_modules/dunder-proto/test/index.js +4 -0
  241. gaia/eval/webapp/node_modules/dunder-proto/test/set.js +50 -0
  242. gaia/eval/webapp/node_modules/dunder-proto/tsconfig.json +9 -0
  243. gaia/eval/webapp/node_modules/ee-first/LICENSE +22 -0
  244. gaia/eval/webapp/node_modules/ee-first/README.md +80 -0
  245. gaia/eval/webapp/node_modules/ee-first/index.js +95 -0
  246. gaia/eval/webapp/node_modules/ee-first/package.json +29 -0
  247. gaia/eval/webapp/node_modules/encodeurl/LICENSE +22 -0
  248. gaia/eval/webapp/node_modules/encodeurl/README.md +109 -0
  249. gaia/eval/webapp/node_modules/encodeurl/index.js +60 -0
  250. gaia/eval/webapp/node_modules/encodeurl/package.json +40 -0
  251. gaia/eval/webapp/node_modules/es-define-property/.eslintrc +13 -0
  252. gaia/eval/webapp/node_modules/es-define-property/.github/FUNDING.yml +12 -0
  253. gaia/eval/webapp/node_modules/es-define-property/.nycrc +9 -0
  254. gaia/eval/webapp/node_modules/es-define-property/CHANGELOG.md +29 -0
  255. gaia/eval/webapp/node_modules/es-define-property/LICENSE +21 -0
  256. gaia/eval/webapp/node_modules/es-define-property/README.md +49 -0
  257. gaia/eval/webapp/node_modules/es-define-property/index.d.ts +3 -0
  258. gaia/eval/webapp/node_modules/es-define-property/index.js +14 -0
  259. gaia/eval/webapp/node_modules/es-define-property/package.json +81 -0
  260. gaia/eval/webapp/node_modules/es-define-property/test/index.js +56 -0
  261. gaia/eval/webapp/node_modules/es-define-property/tsconfig.json +10 -0
  262. gaia/eval/webapp/node_modules/es-errors/.eslintrc +5 -0
  263. gaia/eval/webapp/node_modules/es-errors/.github/FUNDING.yml +12 -0
  264. gaia/eval/webapp/node_modules/es-errors/CHANGELOG.md +40 -0
  265. gaia/eval/webapp/node_modules/es-errors/LICENSE +21 -0
  266. gaia/eval/webapp/node_modules/es-errors/README.md +55 -0
  267. gaia/eval/webapp/node_modules/es-errors/eval.d.ts +3 -0
  268. gaia/eval/webapp/node_modules/es-errors/eval.js +4 -0
  269. gaia/eval/webapp/node_modules/es-errors/index.d.ts +3 -0
  270. gaia/eval/webapp/node_modules/es-errors/index.js +4 -0
  271. gaia/eval/webapp/node_modules/es-errors/package.json +80 -0
  272. gaia/eval/webapp/node_modules/es-errors/range.d.ts +3 -0
  273. gaia/eval/webapp/node_modules/es-errors/range.js +4 -0
  274. gaia/eval/webapp/node_modules/es-errors/ref.d.ts +3 -0
  275. gaia/eval/webapp/node_modules/es-errors/ref.js +4 -0
  276. gaia/eval/webapp/node_modules/es-errors/syntax.d.ts +3 -0
  277. gaia/eval/webapp/node_modules/es-errors/syntax.js +4 -0
  278. gaia/eval/webapp/node_modules/es-errors/test/index.js +19 -0
  279. gaia/eval/webapp/node_modules/es-errors/tsconfig.json +49 -0
  280. gaia/eval/webapp/node_modules/es-errors/type.d.ts +3 -0
  281. gaia/eval/webapp/node_modules/es-errors/type.js +4 -0
  282. gaia/eval/webapp/node_modules/es-errors/uri.d.ts +3 -0
  283. gaia/eval/webapp/node_modules/es-errors/uri.js +4 -0
  284. gaia/eval/webapp/node_modules/es-object-atoms/.eslintrc +16 -0
  285. gaia/eval/webapp/node_modules/es-object-atoms/.github/FUNDING.yml +12 -0
  286. gaia/eval/webapp/node_modules/es-object-atoms/CHANGELOG.md +37 -0
  287. gaia/eval/webapp/node_modules/es-object-atoms/LICENSE +21 -0
  288. gaia/eval/webapp/node_modules/es-object-atoms/README.md +63 -0
  289. gaia/eval/webapp/node_modules/es-object-atoms/RequireObjectCoercible.d.ts +3 -0
  290. gaia/eval/webapp/node_modules/es-object-atoms/RequireObjectCoercible.js +11 -0
  291. gaia/eval/webapp/node_modules/es-object-atoms/ToObject.d.ts +7 -0
  292. gaia/eval/webapp/node_modules/es-object-atoms/ToObject.js +10 -0
  293. gaia/eval/webapp/node_modules/es-object-atoms/index.d.ts +3 -0
  294. gaia/eval/webapp/node_modules/es-object-atoms/index.js +4 -0
  295. gaia/eval/webapp/node_modules/es-object-atoms/isObject.d.ts +3 -0
  296. gaia/eval/webapp/node_modules/es-object-atoms/isObject.js +6 -0
  297. gaia/eval/webapp/node_modules/es-object-atoms/package.json +80 -0
  298. gaia/eval/webapp/node_modules/es-object-atoms/test/index.js +38 -0
  299. gaia/eval/webapp/node_modules/es-object-atoms/tsconfig.json +6 -0
  300. gaia/eval/webapp/node_modules/escape-html/LICENSE +24 -0
  301. gaia/eval/webapp/node_modules/escape-html/Readme.md +43 -0
  302. gaia/eval/webapp/node_modules/escape-html/index.js +78 -0
  303. gaia/eval/webapp/node_modules/escape-html/package.json +24 -0
  304. gaia/eval/webapp/node_modules/etag/HISTORY.md +83 -0
  305. gaia/eval/webapp/node_modules/etag/LICENSE +22 -0
  306. gaia/eval/webapp/node_modules/etag/README.md +159 -0
  307. gaia/eval/webapp/node_modules/etag/index.js +131 -0
  308. gaia/eval/webapp/node_modules/etag/package.json +47 -0
  309. gaia/eval/webapp/node_modules/express/History.md +3656 -0
  310. gaia/eval/webapp/node_modules/express/LICENSE +24 -0
  311. gaia/eval/webapp/node_modules/express/Readme.md +260 -0
  312. gaia/eval/webapp/node_modules/express/index.js +11 -0
  313. gaia/eval/webapp/node_modules/express/lib/application.js +661 -0
  314. gaia/eval/webapp/node_modules/express/lib/express.js +116 -0
  315. gaia/eval/webapp/node_modules/express/lib/middleware/init.js +43 -0
  316. gaia/eval/webapp/node_modules/express/lib/middleware/query.js +47 -0
  317. gaia/eval/webapp/node_modules/express/lib/request.js +525 -0
  318. gaia/eval/webapp/node_modules/express/lib/response.js +1179 -0
  319. gaia/eval/webapp/node_modules/express/lib/router/index.js +673 -0
  320. gaia/eval/webapp/node_modules/express/lib/router/layer.js +181 -0
  321. gaia/eval/webapp/node_modules/express/lib/router/route.js +230 -0
  322. gaia/eval/webapp/node_modules/express/lib/utils.js +303 -0
  323. gaia/eval/webapp/node_modules/express/lib/view.js +182 -0
  324. gaia/eval/webapp/node_modules/express/package.json +102 -0
  325. gaia/eval/webapp/node_modules/finalhandler/HISTORY.md +210 -0
  326. gaia/eval/webapp/node_modules/finalhandler/LICENSE +22 -0
  327. gaia/eval/webapp/node_modules/finalhandler/README.md +147 -0
  328. gaia/eval/webapp/node_modules/finalhandler/SECURITY.md +25 -0
  329. gaia/eval/webapp/node_modules/finalhandler/index.js +341 -0
  330. gaia/eval/webapp/node_modules/finalhandler/package.json +47 -0
  331. gaia/eval/webapp/node_modules/forwarded/HISTORY.md +21 -0
  332. gaia/eval/webapp/node_modules/forwarded/LICENSE +22 -0
  333. gaia/eval/webapp/node_modules/forwarded/README.md +57 -0
  334. gaia/eval/webapp/node_modules/forwarded/index.js +90 -0
  335. gaia/eval/webapp/node_modules/forwarded/package.json +45 -0
  336. gaia/eval/webapp/node_modules/fresh/HISTORY.md +70 -0
  337. gaia/eval/webapp/node_modules/fresh/LICENSE +23 -0
  338. gaia/eval/webapp/node_modules/fresh/README.md +119 -0
  339. gaia/eval/webapp/node_modules/fresh/index.js +137 -0
  340. gaia/eval/webapp/node_modules/fresh/package.json +46 -0
  341. gaia/eval/webapp/node_modules/fs/README.md +9 -0
  342. gaia/eval/webapp/node_modules/fs/package.json +20 -0
  343. gaia/eval/webapp/node_modules/function-bind/.eslintrc +21 -0
  344. gaia/eval/webapp/node_modules/function-bind/.github/FUNDING.yml +12 -0
  345. gaia/eval/webapp/node_modules/function-bind/.github/SECURITY.md +3 -0
  346. gaia/eval/webapp/node_modules/function-bind/.nycrc +13 -0
  347. gaia/eval/webapp/node_modules/function-bind/CHANGELOG.md +136 -0
  348. gaia/eval/webapp/node_modules/function-bind/LICENSE +20 -0
  349. gaia/eval/webapp/node_modules/function-bind/README.md +46 -0
  350. gaia/eval/webapp/node_modules/function-bind/implementation.js +84 -0
  351. gaia/eval/webapp/node_modules/function-bind/index.js +5 -0
  352. gaia/eval/webapp/node_modules/function-bind/package.json +87 -0
  353. gaia/eval/webapp/node_modules/function-bind/test/.eslintrc +9 -0
  354. gaia/eval/webapp/node_modules/function-bind/test/index.js +252 -0
  355. gaia/eval/webapp/node_modules/get-intrinsic/.eslintrc +42 -0
  356. gaia/eval/webapp/node_modules/get-intrinsic/.github/FUNDING.yml +12 -0
  357. gaia/eval/webapp/node_modules/get-intrinsic/.nycrc +9 -0
  358. gaia/eval/webapp/node_modules/get-intrinsic/CHANGELOG.md +186 -0
  359. gaia/eval/webapp/node_modules/get-intrinsic/LICENSE +21 -0
  360. gaia/eval/webapp/node_modules/get-intrinsic/README.md +71 -0
  361. gaia/eval/webapp/node_modules/get-intrinsic/index.js +378 -0
  362. gaia/eval/webapp/node_modules/get-intrinsic/package.json +97 -0
  363. gaia/eval/webapp/node_modules/get-intrinsic/test/GetIntrinsic.js +274 -0
  364. gaia/eval/webapp/node_modules/get-proto/.eslintrc +10 -0
  365. gaia/eval/webapp/node_modules/get-proto/.github/FUNDING.yml +12 -0
  366. gaia/eval/webapp/node_modules/get-proto/.nycrc +9 -0
  367. gaia/eval/webapp/node_modules/get-proto/CHANGELOG.md +21 -0
  368. gaia/eval/webapp/node_modules/get-proto/LICENSE +21 -0
  369. gaia/eval/webapp/node_modules/get-proto/Object.getPrototypeOf.d.ts +5 -0
  370. gaia/eval/webapp/node_modules/get-proto/Object.getPrototypeOf.js +6 -0
  371. gaia/eval/webapp/node_modules/get-proto/README.md +50 -0
  372. gaia/eval/webapp/node_modules/get-proto/Reflect.getPrototypeOf.d.ts +3 -0
  373. gaia/eval/webapp/node_modules/get-proto/Reflect.getPrototypeOf.js +4 -0
  374. gaia/eval/webapp/node_modules/get-proto/index.d.ts +5 -0
  375. gaia/eval/webapp/node_modules/get-proto/index.js +27 -0
  376. gaia/eval/webapp/node_modules/get-proto/package.json +81 -0
  377. gaia/eval/webapp/node_modules/get-proto/test/index.js +68 -0
  378. gaia/eval/webapp/node_modules/get-proto/tsconfig.json +9 -0
  379. gaia/eval/webapp/node_modules/gopd/.eslintrc +16 -0
  380. gaia/eval/webapp/node_modules/gopd/.github/FUNDING.yml +12 -0
  381. gaia/eval/webapp/node_modules/gopd/CHANGELOG.md +45 -0
  382. gaia/eval/webapp/node_modules/gopd/LICENSE +21 -0
  383. gaia/eval/webapp/node_modules/gopd/README.md +40 -0
  384. gaia/eval/webapp/node_modules/gopd/gOPD.d.ts +1 -0
  385. gaia/eval/webapp/node_modules/gopd/gOPD.js +4 -0
  386. gaia/eval/webapp/node_modules/gopd/index.d.ts +5 -0
  387. gaia/eval/webapp/node_modules/gopd/index.js +15 -0
  388. gaia/eval/webapp/node_modules/gopd/package.json +77 -0
  389. gaia/eval/webapp/node_modules/gopd/test/index.js +36 -0
  390. gaia/eval/webapp/node_modules/gopd/tsconfig.json +9 -0
  391. gaia/eval/webapp/node_modules/has-symbols/.eslintrc +11 -0
  392. gaia/eval/webapp/node_modules/has-symbols/.github/FUNDING.yml +12 -0
  393. gaia/eval/webapp/node_modules/has-symbols/.nycrc +9 -0
  394. gaia/eval/webapp/node_modules/has-symbols/CHANGELOG.md +91 -0
  395. gaia/eval/webapp/node_modules/has-symbols/LICENSE +21 -0
  396. gaia/eval/webapp/node_modules/has-symbols/README.md +46 -0
  397. gaia/eval/webapp/node_modules/has-symbols/index.d.ts +3 -0
  398. gaia/eval/webapp/node_modules/has-symbols/index.js +14 -0
  399. gaia/eval/webapp/node_modules/has-symbols/package.json +111 -0
  400. gaia/eval/webapp/node_modules/has-symbols/shams.d.ts +3 -0
  401. gaia/eval/webapp/node_modules/has-symbols/shams.js +45 -0
  402. gaia/eval/webapp/node_modules/has-symbols/test/index.js +22 -0
  403. gaia/eval/webapp/node_modules/has-symbols/test/shams/core-js.js +29 -0
  404. gaia/eval/webapp/node_modules/has-symbols/test/shams/get-own-property-symbols.js +29 -0
  405. gaia/eval/webapp/node_modules/has-symbols/test/tests.js +58 -0
  406. gaia/eval/webapp/node_modules/has-symbols/tsconfig.json +10 -0
  407. gaia/eval/webapp/node_modules/hasown/.eslintrc +5 -0
  408. gaia/eval/webapp/node_modules/hasown/.github/FUNDING.yml +12 -0
  409. gaia/eval/webapp/node_modules/hasown/.nycrc +13 -0
  410. gaia/eval/webapp/node_modules/hasown/CHANGELOG.md +40 -0
  411. gaia/eval/webapp/node_modules/hasown/LICENSE +21 -0
  412. gaia/eval/webapp/node_modules/hasown/README.md +40 -0
  413. gaia/eval/webapp/node_modules/hasown/index.d.ts +3 -0
  414. gaia/eval/webapp/node_modules/hasown/index.js +8 -0
  415. gaia/eval/webapp/node_modules/hasown/package.json +92 -0
  416. gaia/eval/webapp/node_modules/hasown/tsconfig.json +6 -0
  417. gaia/eval/webapp/node_modules/http-errors/HISTORY.md +180 -0
  418. gaia/eval/webapp/node_modules/http-errors/LICENSE +23 -0
  419. gaia/eval/webapp/node_modules/http-errors/README.md +169 -0
  420. gaia/eval/webapp/node_modules/http-errors/index.js +289 -0
  421. gaia/eval/webapp/node_modules/http-errors/package.json +50 -0
  422. gaia/eval/webapp/node_modules/iconv-lite/Changelog.md +162 -0
  423. gaia/eval/webapp/node_modules/iconv-lite/LICENSE +21 -0
  424. gaia/eval/webapp/node_modules/iconv-lite/README.md +156 -0
  425. gaia/eval/webapp/node_modules/iconv-lite/encodings/dbcs-codec.js +555 -0
  426. gaia/eval/webapp/node_modules/iconv-lite/encodings/dbcs-data.js +176 -0
  427. gaia/eval/webapp/node_modules/iconv-lite/encodings/index.js +22 -0
  428. gaia/eval/webapp/node_modules/iconv-lite/encodings/internal.js +188 -0
  429. gaia/eval/webapp/node_modules/iconv-lite/encodings/sbcs-codec.js +72 -0
  430. gaia/eval/webapp/node_modules/iconv-lite/encodings/sbcs-data-generated.js +451 -0
  431. gaia/eval/webapp/node_modules/iconv-lite/encodings/sbcs-data.js +174 -0
  432. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/big5-added.json +122 -0
  433. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/cp936.json +264 -0
  434. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/cp949.json +273 -0
  435. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/cp950.json +177 -0
  436. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/eucjp.json +182 -0
  437. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/gb18030-ranges.json +1 -0
  438. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/gbk-added.json +55 -0
  439. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/shiftjis.json +125 -0
  440. gaia/eval/webapp/node_modules/iconv-lite/encodings/utf16.js +177 -0
  441. gaia/eval/webapp/node_modules/iconv-lite/encodings/utf7.js +290 -0
  442. gaia/eval/webapp/node_modules/iconv-lite/lib/bom-handling.js +52 -0
  443. gaia/eval/webapp/node_modules/iconv-lite/lib/extend-node.js +217 -0
  444. gaia/eval/webapp/node_modules/iconv-lite/lib/index.d.ts +24 -0
  445. gaia/eval/webapp/node_modules/iconv-lite/lib/index.js +153 -0
  446. gaia/eval/webapp/node_modules/iconv-lite/lib/streams.js +121 -0
  447. gaia/eval/webapp/node_modules/iconv-lite/package.json +46 -0
  448. gaia/eval/webapp/node_modules/inherits/LICENSE +16 -0
  449. gaia/eval/webapp/node_modules/inherits/README.md +42 -0
  450. gaia/eval/webapp/node_modules/inherits/inherits.js +9 -0
  451. gaia/eval/webapp/node_modules/inherits/inherits_browser.js +27 -0
  452. gaia/eval/webapp/node_modules/inherits/package.json +29 -0
  453. gaia/eval/webapp/node_modules/ipaddr.js/LICENSE +19 -0
  454. gaia/eval/webapp/node_modules/ipaddr.js/README.md +233 -0
  455. gaia/eval/webapp/node_modules/ipaddr.js/ipaddr.min.js +1 -0
  456. gaia/eval/webapp/node_modules/ipaddr.js/lib/ipaddr.js +673 -0
  457. gaia/eval/webapp/node_modules/ipaddr.js/lib/ipaddr.js.d.ts +68 -0
  458. gaia/eval/webapp/node_modules/ipaddr.js/package.json +35 -0
  459. gaia/eval/webapp/node_modules/math-intrinsics/.eslintrc +16 -0
  460. gaia/eval/webapp/node_modules/math-intrinsics/.github/FUNDING.yml +12 -0
  461. gaia/eval/webapp/node_modules/math-intrinsics/CHANGELOG.md +24 -0
  462. gaia/eval/webapp/node_modules/math-intrinsics/LICENSE +21 -0
  463. gaia/eval/webapp/node_modules/math-intrinsics/README.md +50 -0
  464. gaia/eval/webapp/node_modules/math-intrinsics/abs.d.ts +1 -0
  465. gaia/eval/webapp/node_modules/math-intrinsics/abs.js +4 -0
  466. gaia/eval/webapp/node_modules/math-intrinsics/constants/maxArrayLength.d.ts +3 -0
  467. gaia/eval/webapp/node_modules/math-intrinsics/constants/maxArrayLength.js +4 -0
  468. gaia/eval/webapp/node_modules/math-intrinsics/constants/maxSafeInteger.d.ts +3 -0
  469. gaia/eval/webapp/node_modules/math-intrinsics/constants/maxSafeInteger.js +5 -0
  470. gaia/eval/webapp/node_modules/math-intrinsics/constants/maxValue.d.ts +3 -0
  471. gaia/eval/webapp/node_modules/math-intrinsics/constants/maxValue.js +5 -0
  472. gaia/eval/webapp/node_modules/math-intrinsics/floor.d.ts +1 -0
  473. gaia/eval/webapp/node_modules/math-intrinsics/floor.js +4 -0
  474. gaia/eval/webapp/node_modules/math-intrinsics/isFinite.d.ts +3 -0
  475. gaia/eval/webapp/node_modules/math-intrinsics/isFinite.js +12 -0
  476. gaia/eval/webapp/node_modules/math-intrinsics/isInteger.d.ts +3 -0
  477. gaia/eval/webapp/node_modules/math-intrinsics/isInteger.js +16 -0
  478. gaia/eval/webapp/node_modules/math-intrinsics/isNaN.d.ts +1 -0
  479. gaia/eval/webapp/node_modules/math-intrinsics/isNaN.js +6 -0
  480. gaia/eval/webapp/node_modules/math-intrinsics/isNegativeZero.d.ts +3 -0
  481. gaia/eval/webapp/node_modules/math-intrinsics/isNegativeZero.js +6 -0
  482. gaia/eval/webapp/node_modules/math-intrinsics/max.d.ts +1 -0
  483. gaia/eval/webapp/node_modules/math-intrinsics/max.js +4 -0
  484. gaia/eval/webapp/node_modules/math-intrinsics/min.d.ts +1 -0
  485. gaia/eval/webapp/node_modules/math-intrinsics/min.js +4 -0
  486. gaia/eval/webapp/node_modules/math-intrinsics/mod.d.ts +3 -0
  487. gaia/eval/webapp/node_modules/math-intrinsics/mod.js +9 -0
  488. gaia/eval/webapp/node_modules/math-intrinsics/package.json +86 -0
  489. gaia/eval/webapp/node_modules/math-intrinsics/pow.d.ts +1 -0
  490. gaia/eval/webapp/node_modules/math-intrinsics/pow.js +4 -0
  491. gaia/eval/webapp/node_modules/math-intrinsics/round.d.ts +1 -0
  492. gaia/eval/webapp/node_modules/math-intrinsics/round.js +4 -0
  493. gaia/eval/webapp/node_modules/math-intrinsics/sign.d.ts +3 -0
  494. gaia/eval/webapp/node_modules/math-intrinsics/sign.js +11 -0
  495. gaia/eval/webapp/node_modules/math-intrinsics/test/index.js +192 -0
  496. gaia/eval/webapp/node_modules/math-intrinsics/tsconfig.json +3 -0
  497. gaia/eval/webapp/node_modules/media-typer/HISTORY.md +22 -0
  498. gaia/eval/webapp/node_modules/media-typer/LICENSE +22 -0
  499. gaia/eval/webapp/node_modules/media-typer/README.md +81 -0
  500. gaia/eval/webapp/node_modules/media-typer/index.js +270 -0
  501. gaia/eval/webapp/node_modules/media-typer/package.json +26 -0
  502. gaia/eval/webapp/node_modules/merge-descriptors/HISTORY.md +21 -0
  503. gaia/eval/webapp/node_modules/merge-descriptors/LICENSE +23 -0
  504. gaia/eval/webapp/node_modules/merge-descriptors/README.md +49 -0
  505. gaia/eval/webapp/node_modules/merge-descriptors/index.js +60 -0
  506. gaia/eval/webapp/node_modules/merge-descriptors/package.json +39 -0
  507. gaia/eval/webapp/node_modules/methods/HISTORY.md +29 -0
  508. gaia/eval/webapp/node_modules/methods/LICENSE +24 -0
  509. gaia/eval/webapp/node_modules/methods/README.md +51 -0
  510. gaia/eval/webapp/node_modules/methods/index.js +69 -0
  511. gaia/eval/webapp/node_modules/methods/package.json +36 -0
  512. gaia/eval/webapp/node_modules/mime/.npmignore +0 -0
  513. gaia/eval/webapp/node_modules/mime/CHANGELOG.md +164 -0
  514. gaia/eval/webapp/node_modules/mime/LICENSE +21 -0
  515. gaia/eval/webapp/node_modules/mime/README.md +90 -0
  516. gaia/eval/webapp/node_modules/mime/cli.js +8 -0
  517. gaia/eval/webapp/node_modules/mime/mime.js +108 -0
  518. gaia/eval/webapp/node_modules/mime/package.json +44 -0
  519. gaia/eval/webapp/node_modules/mime/src/build.js +53 -0
  520. gaia/eval/webapp/node_modules/mime/src/test.js +60 -0
  521. gaia/eval/webapp/node_modules/mime/types.json +1 -0
  522. gaia/eval/webapp/node_modules/mime-db/HISTORY.md +507 -0
  523. gaia/eval/webapp/node_modules/mime-db/LICENSE +23 -0
  524. gaia/eval/webapp/node_modules/mime-db/README.md +100 -0
  525. gaia/eval/webapp/node_modules/mime-db/db.json +8519 -0
  526. gaia/eval/webapp/node_modules/mime-db/index.js +12 -0
  527. gaia/eval/webapp/node_modules/mime-db/package.json +60 -0
  528. gaia/eval/webapp/node_modules/mime-types/HISTORY.md +397 -0
  529. gaia/eval/webapp/node_modules/mime-types/LICENSE +23 -0
  530. gaia/eval/webapp/node_modules/mime-types/README.md +113 -0
  531. gaia/eval/webapp/node_modules/mime-types/index.js +188 -0
  532. gaia/eval/webapp/node_modules/mime-types/package.json +44 -0
  533. gaia/eval/webapp/node_modules/ms/index.js +152 -0
  534. gaia/eval/webapp/node_modules/ms/license.md +21 -0
  535. gaia/eval/webapp/node_modules/ms/package.json +37 -0
  536. gaia/eval/webapp/node_modules/ms/readme.md +51 -0
  537. gaia/eval/webapp/node_modules/negotiator/HISTORY.md +108 -0
  538. gaia/eval/webapp/node_modules/negotiator/LICENSE +24 -0
  539. gaia/eval/webapp/node_modules/negotiator/README.md +203 -0
  540. gaia/eval/webapp/node_modules/negotiator/index.js +82 -0
  541. gaia/eval/webapp/node_modules/negotiator/lib/charset.js +169 -0
  542. gaia/eval/webapp/node_modules/negotiator/lib/encoding.js +184 -0
  543. gaia/eval/webapp/node_modules/negotiator/lib/language.js +179 -0
  544. gaia/eval/webapp/node_modules/negotiator/lib/mediaType.js +294 -0
  545. gaia/eval/webapp/node_modules/negotiator/package.json +42 -0
  546. gaia/eval/webapp/node_modules/object-inspect/.eslintrc +53 -0
  547. gaia/eval/webapp/node_modules/object-inspect/.github/FUNDING.yml +12 -0
  548. gaia/eval/webapp/node_modules/object-inspect/.nycrc +13 -0
  549. gaia/eval/webapp/node_modules/object-inspect/CHANGELOG.md +424 -0
  550. gaia/eval/webapp/node_modules/object-inspect/LICENSE +21 -0
  551. gaia/eval/webapp/node_modules/object-inspect/example/all.js +23 -0
  552. gaia/eval/webapp/node_modules/object-inspect/example/circular.js +6 -0
  553. gaia/eval/webapp/node_modules/object-inspect/example/fn.js +5 -0
  554. gaia/eval/webapp/node_modules/object-inspect/example/inspect.js +10 -0
  555. gaia/eval/webapp/node_modules/object-inspect/index.js +544 -0
  556. gaia/eval/webapp/node_modules/object-inspect/package-support.json +20 -0
  557. gaia/eval/webapp/node_modules/object-inspect/package.json +105 -0
  558. gaia/eval/webapp/node_modules/object-inspect/readme.markdown +84 -0
  559. gaia/eval/webapp/node_modules/object-inspect/test/bigint.js +58 -0
  560. gaia/eval/webapp/node_modules/object-inspect/test/browser/dom.js +15 -0
  561. gaia/eval/webapp/node_modules/object-inspect/test/circular.js +16 -0
  562. gaia/eval/webapp/node_modules/object-inspect/test/deep.js +12 -0
  563. gaia/eval/webapp/node_modules/object-inspect/test/element.js +53 -0
  564. gaia/eval/webapp/node_modules/object-inspect/test/err.js +48 -0
  565. gaia/eval/webapp/node_modules/object-inspect/test/fakes.js +29 -0
  566. gaia/eval/webapp/node_modules/object-inspect/test/fn.js +76 -0
  567. gaia/eval/webapp/node_modules/object-inspect/test/global.js +17 -0
  568. gaia/eval/webapp/node_modules/object-inspect/test/has.js +15 -0
  569. gaia/eval/webapp/node_modules/object-inspect/test/holes.js +15 -0
  570. gaia/eval/webapp/node_modules/object-inspect/test/indent-option.js +271 -0
  571. gaia/eval/webapp/node_modules/object-inspect/test/inspect.js +139 -0
  572. gaia/eval/webapp/node_modules/object-inspect/test/lowbyte.js +12 -0
  573. gaia/eval/webapp/node_modules/object-inspect/test/number.js +58 -0
  574. gaia/eval/webapp/node_modules/object-inspect/test/quoteStyle.js +26 -0
  575. gaia/eval/webapp/node_modules/object-inspect/test/toStringTag.js +40 -0
  576. gaia/eval/webapp/node_modules/object-inspect/test/undef.js +12 -0
  577. gaia/eval/webapp/node_modules/object-inspect/test/values.js +261 -0
  578. gaia/eval/webapp/node_modules/object-inspect/test-core-js.js +26 -0
  579. gaia/eval/webapp/node_modules/object-inspect/util.inspect.js +1 -0
  580. gaia/eval/webapp/node_modules/on-finished/HISTORY.md +98 -0
  581. gaia/eval/webapp/node_modules/on-finished/LICENSE +23 -0
  582. gaia/eval/webapp/node_modules/on-finished/README.md +162 -0
  583. gaia/eval/webapp/node_modules/on-finished/index.js +234 -0
  584. gaia/eval/webapp/node_modules/on-finished/package.json +39 -0
  585. gaia/eval/webapp/node_modules/parseurl/HISTORY.md +58 -0
  586. gaia/eval/webapp/node_modules/parseurl/LICENSE +24 -0
  587. gaia/eval/webapp/node_modules/parseurl/README.md +133 -0
  588. gaia/eval/webapp/node_modules/parseurl/index.js +158 -0
  589. gaia/eval/webapp/node_modules/parseurl/package.json +40 -0
  590. gaia/eval/webapp/node_modules/path/.npmignore +1 -0
  591. gaia/eval/webapp/node_modules/path/LICENSE +18 -0
  592. gaia/eval/webapp/node_modules/path/README.md +15 -0
  593. gaia/eval/webapp/node_modules/path/package.json +24 -0
  594. gaia/eval/webapp/node_modules/path/path.js +628 -0
  595. gaia/eval/webapp/node_modules/path-to-regexp/LICENSE +21 -0
  596. gaia/eval/webapp/node_modules/path-to-regexp/Readme.md +35 -0
  597. gaia/eval/webapp/node_modules/path-to-regexp/index.js +156 -0
  598. gaia/eval/webapp/node_modules/path-to-regexp/package.json +30 -0
  599. gaia/eval/webapp/node_modules/process/.eslintrc +21 -0
  600. gaia/eval/webapp/node_modules/process/LICENSE +22 -0
  601. gaia/eval/webapp/node_modules/process/README.md +26 -0
  602. gaia/eval/webapp/node_modules/process/browser.js +184 -0
  603. gaia/eval/webapp/node_modules/process/index.js +2 -0
  604. gaia/eval/webapp/node_modules/process/package.json +27 -0
  605. gaia/eval/webapp/node_modules/process/test.js +199 -0
  606. gaia/eval/webapp/node_modules/proxy-addr/HISTORY.md +161 -0
  607. gaia/eval/webapp/node_modules/proxy-addr/LICENSE +22 -0
  608. gaia/eval/webapp/node_modules/proxy-addr/README.md +139 -0
  609. gaia/eval/webapp/node_modules/proxy-addr/index.js +327 -0
  610. gaia/eval/webapp/node_modules/proxy-addr/package.json +47 -0
  611. gaia/eval/webapp/node_modules/qs/.editorconfig +46 -0
  612. gaia/eval/webapp/node_modules/qs/.eslintrc +38 -0
  613. gaia/eval/webapp/node_modules/qs/.github/FUNDING.yml +12 -0
  614. gaia/eval/webapp/node_modules/qs/.nycrc +13 -0
  615. gaia/eval/webapp/node_modules/qs/CHANGELOG.md +600 -0
  616. gaia/eval/webapp/node_modules/qs/LICENSE.md +29 -0
  617. gaia/eval/webapp/node_modules/qs/README.md +709 -0
  618. gaia/eval/webapp/node_modules/qs/dist/qs.js +90 -0
  619. gaia/eval/webapp/node_modules/qs/lib/formats.js +23 -0
  620. gaia/eval/webapp/node_modules/qs/lib/index.js +11 -0
  621. gaia/eval/webapp/node_modules/qs/lib/parse.js +296 -0
  622. gaia/eval/webapp/node_modules/qs/lib/stringify.js +351 -0
  623. gaia/eval/webapp/node_modules/qs/lib/utils.js +265 -0
  624. gaia/eval/webapp/node_modules/qs/package.json +91 -0
  625. gaia/eval/webapp/node_modules/qs/test/empty-keys-cases.js +267 -0
  626. gaia/eval/webapp/node_modules/qs/test/parse.js +1170 -0
  627. gaia/eval/webapp/node_modules/qs/test/stringify.js +1298 -0
  628. gaia/eval/webapp/node_modules/qs/test/utils.js +136 -0
  629. gaia/eval/webapp/node_modules/range-parser/HISTORY.md +56 -0
  630. gaia/eval/webapp/node_modules/range-parser/LICENSE +23 -0
  631. gaia/eval/webapp/node_modules/range-parser/README.md +84 -0
  632. gaia/eval/webapp/node_modules/range-parser/index.js +162 -0
  633. gaia/eval/webapp/node_modules/range-parser/package.json +44 -0
  634. gaia/eval/webapp/node_modules/raw-body/HISTORY.md +308 -0
  635. gaia/eval/webapp/node_modules/raw-body/LICENSE +22 -0
  636. gaia/eval/webapp/node_modules/raw-body/README.md +223 -0
  637. gaia/eval/webapp/node_modules/raw-body/SECURITY.md +24 -0
  638. gaia/eval/webapp/node_modules/raw-body/index.d.ts +87 -0
  639. gaia/eval/webapp/node_modules/raw-body/index.js +336 -0
  640. gaia/eval/webapp/node_modules/raw-body/package.json +49 -0
  641. gaia/eval/webapp/node_modules/safe-buffer/LICENSE +21 -0
  642. gaia/eval/webapp/node_modules/safe-buffer/README.md +584 -0
  643. gaia/eval/webapp/node_modules/safe-buffer/index.d.ts +187 -0
  644. gaia/eval/webapp/node_modules/safe-buffer/index.js +65 -0
  645. gaia/eval/webapp/node_modules/safe-buffer/package.json +51 -0
  646. gaia/eval/webapp/node_modules/safer-buffer/LICENSE +21 -0
  647. gaia/eval/webapp/node_modules/safer-buffer/Porting-Buffer.md +268 -0
  648. gaia/eval/webapp/node_modules/safer-buffer/Readme.md +156 -0
  649. gaia/eval/webapp/node_modules/safer-buffer/dangerous.js +58 -0
  650. gaia/eval/webapp/node_modules/safer-buffer/package.json +34 -0
  651. gaia/eval/webapp/node_modules/safer-buffer/safer.js +77 -0
  652. gaia/eval/webapp/node_modules/safer-buffer/tests.js +406 -0
  653. gaia/eval/webapp/node_modules/send/HISTORY.md +526 -0
  654. gaia/eval/webapp/node_modules/send/LICENSE +23 -0
  655. gaia/eval/webapp/node_modules/send/README.md +327 -0
  656. gaia/eval/webapp/node_modules/send/SECURITY.md +24 -0
  657. gaia/eval/webapp/node_modules/send/index.js +1142 -0
  658. gaia/eval/webapp/node_modules/send/node_modules/encodeurl/HISTORY.md +14 -0
  659. gaia/eval/webapp/node_modules/send/node_modules/encodeurl/LICENSE +22 -0
  660. gaia/eval/webapp/node_modules/send/node_modules/encodeurl/README.md +128 -0
  661. gaia/eval/webapp/node_modules/send/node_modules/encodeurl/index.js +60 -0
  662. gaia/eval/webapp/node_modules/send/node_modules/encodeurl/package.json +40 -0
  663. gaia/eval/webapp/node_modules/send/node_modules/ms/index.js +162 -0
  664. gaia/eval/webapp/node_modules/send/node_modules/ms/license.md +21 -0
  665. gaia/eval/webapp/node_modules/send/node_modules/ms/package.json +38 -0
  666. gaia/eval/webapp/node_modules/send/node_modules/ms/readme.md +59 -0
  667. gaia/eval/webapp/node_modules/send/package.json +62 -0
  668. gaia/eval/webapp/node_modules/serve-static/HISTORY.md +487 -0
  669. gaia/eval/webapp/node_modules/serve-static/LICENSE +25 -0
  670. gaia/eval/webapp/node_modules/serve-static/README.md +257 -0
  671. gaia/eval/webapp/node_modules/serve-static/index.js +209 -0
  672. gaia/eval/webapp/node_modules/serve-static/package.json +42 -0
  673. gaia/eval/webapp/node_modules/setprototypeof/LICENSE +13 -0
  674. gaia/eval/webapp/node_modules/setprototypeof/README.md +31 -0
  675. gaia/eval/webapp/node_modules/setprototypeof/index.d.ts +2 -0
  676. gaia/eval/webapp/node_modules/setprototypeof/index.js +17 -0
  677. gaia/eval/webapp/node_modules/setprototypeof/package.json +38 -0
  678. gaia/eval/webapp/node_modules/setprototypeof/test/index.js +24 -0
  679. gaia/eval/webapp/node_modules/side-channel/.editorconfig +9 -0
  680. gaia/eval/webapp/node_modules/side-channel/.eslintrc +12 -0
  681. gaia/eval/webapp/node_modules/side-channel/.github/FUNDING.yml +12 -0
  682. gaia/eval/webapp/node_modules/side-channel/.nycrc +13 -0
  683. gaia/eval/webapp/node_modules/side-channel/CHANGELOG.md +110 -0
  684. gaia/eval/webapp/node_modules/side-channel/LICENSE +21 -0
  685. gaia/eval/webapp/node_modules/side-channel/README.md +61 -0
  686. gaia/eval/webapp/node_modules/side-channel/index.d.ts +14 -0
  687. gaia/eval/webapp/node_modules/side-channel/index.js +43 -0
  688. gaia/eval/webapp/node_modules/side-channel/package.json +85 -0
  689. gaia/eval/webapp/node_modules/side-channel/test/index.js +104 -0
  690. gaia/eval/webapp/node_modules/side-channel/tsconfig.json +9 -0
  691. gaia/eval/webapp/node_modules/side-channel-list/.editorconfig +9 -0
  692. gaia/eval/webapp/node_modules/side-channel-list/.eslintrc +11 -0
  693. gaia/eval/webapp/node_modules/side-channel-list/.github/FUNDING.yml +12 -0
  694. gaia/eval/webapp/node_modules/side-channel-list/.nycrc +13 -0
  695. gaia/eval/webapp/node_modules/side-channel-list/CHANGELOG.md +15 -0
  696. gaia/eval/webapp/node_modules/side-channel-list/LICENSE +21 -0
  697. gaia/eval/webapp/node_modules/side-channel-list/README.md +62 -0
  698. gaia/eval/webapp/node_modules/side-channel-list/index.d.ts +13 -0
  699. gaia/eval/webapp/node_modules/side-channel-list/index.js +113 -0
  700. gaia/eval/webapp/node_modules/side-channel-list/list.d.ts +14 -0
  701. gaia/eval/webapp/node_modules/side-channel-list/package.json +77 -0
  702. gaia/eval/webapp/node_modules/side-channel-list/test/index.js +104 -0
  703. gaia/eval/webapp/node_modules/side-channel-list/tsconfig.json +9 -0
  704. gaia/eval/webapp/node_modules/side-channel-map/.editorconfig +9 -0
  705. gaia/eval/webapp/node_modules/side-channel-map/.eslintrc +11 -0
  706. gaia/eval/webapp/node_modules/side-channel-map/.github/FUNDING.yml +12 -0
  707. gaia/eval/webapp/node_modules/side-channel-map/.nycrc +13 -0
  708. gaia/eval/webapp/node_modules/side-channel-map/CHANGELOG.md +22 -0
  709. gaia/eval/webapp/node_modules/side-channel-map/LICENSE +21 -0
  710. gaia/eval/webapp/node_modules/side-channel-map/README.md +62 -0
  711. gaia/eval/webapp/node_modules/side-channel-map/index.d.ts +15 -0
  712. gaia/eval/webapp/node_modules/side-channel-map/index.js +68 -0
  713. gaia/eval/webapp/node_modules/side-channel-map/package.json +80 -0
  714. gaia/eval/webapp/node_modules/side-channel-map/test/index.js +114 -0
  715. gaia/eval/webapp/node_modules/side-channel-map/tsconfig.json +9 -0
  716. gaia/eval/webapp/node_modules/side-channel-weakmap/.editorconfig +9 -0
  717. gaia/eval/webapp/node_modules/side-channel-weakmap/.eslintrc +12 -0
  718. gaia/eval/webapp/node_modules/side-channel-weakmap/.github/FUNDING.yml +12 -0
  719. gaia/eval/webapp/node_modules/side-channel-weakmap/.nycrc +13 -0
  720. gaia/eval/webapp/node_modules/side-channel-weakmap/CHANGELOG.md +28 -0
  721. gaia/eval/webapp/node_modules/side-channel-weakmap/LICENSE +21 -0
  722. gaia/eval/webapp/node_modules/side-channel-weakmap/README.md +62 -0
  723. gaia/eval/webapp/node_modules/side-channel-weakmap/index.d.ts +15 -0
  724. gaia/eval/webapp/node_modules/side-channel-weakmap/index.js +84 -0
  725. gaia/eval/webapp/node_modules/side-channel-weakmap/package.json +87 -0
  726. gaia/eval/webapp/node_modules/side-channel-weakmap/test/index.js +114 -0
  727. gaia/eval/webapp/node_modules/side-channel-weakmap/tsconfig.json +9 -0
  728. gaia/eval/webapp/node_modules/statuses/HISTORY.md +82 -0
  729. gaia/eval/webapp/node_modules/statuses/LICENSE +23 -0
  730. gaia/eval/webapp/node_modules/statuses/README.md +136 -0
  731. gaia/eval/webapp/node_modules/statuses/codes.json +65 -0
  732. gaia/eval/webapp/node_modules/statuses/index.js +146 -0
  733. gaia/eval/webapp/node_modules/statuses/package.json +49 -0
  734. gaia/eval/webapp/node_modules/toidentifier/HISTORY.md +9 -0
  735. gaia/eval/webapp/node_modules/toidentifier/LICENSE +21 -0
  736. gaia/eval/webapp/node_modules/toidentifier/README.md +61 -0
  737. gaia/eval/webapp/node_modules/toidentifier/index.js +32 -0
  738. gaia/eval/webapp/node_modules/toidentifier/package.json +38 -0
  739. gaia/eval/webapp/node_modules/type-is/HISTORY.md +259 -0
  740. gaia/eval/webapp/node_modules/type-is/LICENSE +23 -0
  741. gaia/eval/webapp/node_modules/type-is/README.md +170 -0
  742. gaia/eval/webapp/node_modules/type-is/index.js +266 -0
  743. gaia/eval/webapp/node_modules/type-is/package.json +45 -0
  744. gaia/eval/webapp/node_modules/unpipe/HISTORY.md +4 -0
  745. gaia/eval/webapp/node_modules/unpipe/LICENSE +22 -0
  746. gaia/eval/webapp/node_modules/unpipe/README.md +43 -0
  747. gaia/eval/webapp/node_modules/unpipe/index.js +69 -0
  748. gaia/eval/webapp/node_modules/unpipe/package.json +27 -0
  749. gaia/eval/webapp/node_modules/util/LICENSE +18 -0
  750. gaia/eval/webapp/node_modules/util/README.md +15 -0
  751. gaia/eval/webapp/node_modules/util/node_modules/inherits/LICENSE +16 -0
  752. gaia/eval/webapp/node_modules/util/node_modules/inherits/README.md +42 -0
  753. gaia/eval/webapp/node_modules/util/node_modules/inherits/inherits.js +7 -0
  754. gaia/eval/webapp/node_modules/util/node_modules/inherits/inherits_browser.js +23 -0
  755. gaia/eval/webapp/node_modules/util/node_modules/inherits/package.json +29 -0
  756. gaia/eval/webapp/node_modules/util/package.json +35 -0
  757. gaia/eval/webapp/node_modules/util/support/isBuffer.js +3 -0
  758. gaia/eval/webapp/node_modules/util/support/isBufferBrowser.js +6 -0
  759. gaia/eval/webapp/node_modules/util/util.js +586 -0
  760. gaia/eval/webapp/node_modules/utils-merge/.npmignore +9 -0
  761. gaia/eval/webapp/node_modules/utils-merge/LICENSE +20 -0
  762. gaia/eval/webapp/node_modules/utils-merge/README.md +34 -0
  763. gaia/eval/webapp/node_modules/utils-merge/index.js +23 -0
  764. gaia/eval/webapp/node_modules/utils-merge/package.json +40 -0
  765. gaia/eval/webapp/node_modules/vary/HISTORY.md +39 -0
  766. gaia/eval/webapp/node_modules/vary/LICENSE +22 -0
  767. gaia/eval/webapp/node_modules/vary/README.md +101 -0
  768. gaia/eval/webapp/node_modules/vary/index.js +149 -0
  769. gaia/eval/webapp/node_modules/vary/package.json +43 -0
  770. gaia/eval/webapp/package-lock.json +875 -0
  771. gaia/eval/webapp/package.json +21 -0
  772. gaia/eval/webapp/public/app.js +3403 -0
  773. gaia/eval/webapp/public/index.html +88 -0
  774. gaia/eval/webapp/public/styles.css +3661 -0
  775. gaia/eval/webapp/server.js +416 -0
  776. gaia/eval/webapp/test-setup.js +73 -0
  777. gaia/llm/__init__.py +2 -0
  778. gaia/llm/lemonade_client.py +3083 -0
  779. gaia/llm/lemonade_manager.py +269 -0
  780. gaia/llm/llm_client.py +729 -0
  781. gaia/llm/vlm_client.py +307 -0
  782. gaia/logger.py +189 -0
  783. gaia/mcp/agent_mcp_server.py +245 -0
  784. gaia/mcp/blender_mcp_client.py +138 -0
  785. gaia/mcp/blender_mcp_server.py +648 -0
  786. gaia/mcp/context7_cache.py +332 -0
  787. gaia/mcp/external_services.py +518 -0
  788. gaia/mcp/mcp_bridge.py +550 -0
  789. gaia/mcp/servers/__init__.py +6 -0
  790. gaia/mcp/servers/docker_mcp.py +83 -0
  791. gaia/rag/__init__.py +10 -0
  792. gaia/rag/app.py +293 -0
  793. gaia/rag/demo.py +304 -0
  794. gaia/rag/pdf_utils.py +235 -0
  795. gaia/rag/sdk.py +2194 -0
  796. gaia/security.py +163 -0
  797. gaia/talk/app.py +289 -0
  798. gaia/talk/sdk.py +538 -0
  799. gaia/util.py +46 -0
  800. gaia/version.py +100 -0
@@ -0,0 +1,1138 @@
1
+ # Copyright(C) 2024-2025 Advanced Micro Devices, Inc. All rights reserved.
2
+ # SPDX-License-Identifier: MIT
3
+ """
4
+ CLI Tools Mixin for Code Agent.
5
+
6
+ Provides universal CLI command execution with background process management,
7
+ error detection, and graceful shutdown capabilities.
8
+ """
9
+
10
+ import logging
11
+ import os
12
+ import platform
13
+ import re
14
+ import signal
15
+ import socket
16
+ import subprocess
17
+ import tempfile
18
+ import time
19
+ from dataclasses import dataclass
20
+ from pathlib import Path
21
+ from threading import Thread
22
+ from typing import Any, Dict, List, Optional
23
+
24
+ import psutil
25
+
26
+ logger = logging.getLogger(__name__)
27
+
28
+ # CLI configuration constants
29
+ DEFAULT_PORT_RANGE_START = 3000
30
+ DEFAULT_PORT_RANGE_END = 9999
31
+ DEFAULT_COMMAND_TIMEOUT_SECS = 120
32
+ MAX_OUTPUT_CHARS = 10_000
33
+ MAX_ERROR_OUTPUT_CHARS = 2000
34
+
35
+
36
+ @dataclass
37
+ class ProcessInfo:
38
+ """Information about a managed background process."""
39
+
40
+ pid: int
41
+ command: str
42
+ working_dir: str
43
+ log_file: str
44
+ start_time: float
45
+ port: Optional[int] = None
46
+ errors: List[Dict[str, Any]] = None
47
+ warnings: List[str] = None
48
+
49
+ def __post_init__(self):
50
+ if self.errors is None:
51
+ self.errors = []
52
+ if self.warnings is None:
53
+ self.warnings = []
54
+
55
+
56
+ # Error patterns to detect common startup issues
57
+ ERROR_PATTERNS = {
58
+ "port_conflict": [
59
+ r"Port (\d+) is (?:already )?in use",
60
+ r"EADDRINUSE.*:(\d+)",
61
+ r"address already in use.*:(\d+)",
62
+ r"bind\(\) failed.*Address already in use",
63
+ r"listen EADDRINUSE:.*:(\d+)",
64
+ ],
65
+ "missing_deps": [
66
+ r"Cannot find module ['\"]([^'\"]+)['\"]",
67
+ r"Module not found: Error: Can't resolve ['\"]([^'\"]+)['\"]",
68
+ r"Error: Cannot find package ['\"]([^'\"]+)['\"]",
69
+ r"ModuleNotFoundError: No module named ['\"]([^'\"]+)['\"]",
70
+ r"ImportError: No module named ['\"]([^'\"]+)['\"]",
71
+ r"command not found: (npm|node|yarn|pnpm|python|pip)",
72
+ ],
73
+ "compilation": [
74
+ r"SyntaxError:",
75
+ r"TypeError:",
76
+ r"ReferenceError:",
77
+ r"(\d+) error(?:s)?",
78
+ r"Failed to compile",
79
+ r"Build failed",
80
+ r"ERROR in \./",
81
+ r"TS\d+:", # TypeScript errors
82
+ r"Compilation failed",
83
+ ],
84
+ "permissions": [
85
+ r"EACCES: permission denied",
86
+ r"Permission denied",
87
+ r"Access is denied",
88
+ r"Operation not permitted",
89
+ r"EPERM:",
90
+ ],
91
+ "resources": [
92
+ r"JavaScript heap out of memory",
93
+ r"ENOMEM",
94
+ r"Cannot allocate memory",
95
+ r"Out of memory",
96
+ ],
97
+ "network": [
98
+ r"ECONNREFUSED",
99
+ r"fetch failed",
100
+ r"Network error",
101
+ r"ETIMEDOUT",
102
+ r"ENOTFOUND",
103
+ ],
104
+ }
105
+
106
+
107
+ def find_process_on_port(port: int) -> Optional[int]:
108
+ """
109
+ Find the PID of the process using a specific port.
110
+
111
+ Args:
112
+ port: Port number to check
113
+
114
+ Returns:
115
+ PID of the process using the port, or None if port is free
116
+ """
117
+ try:
118
+ for proc in psutil.process_iter(["pid", "name"]):
119
+ try:
120
+ connections = proc.net_connections()
121
+ for conn in connections:
122
+ if conn.laddr.port == port:
123
+ return proc.pid
124
+ except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
125
+ continue
126
+ except Exception as e:
127
+ logger.warning(f"Error checking port {port}: {e}")
128
+ return None
129
+
130
+
131
+ def kill_process_on_port(port: int) -> bool:
132
+ """
133
+ Kill any process using the specified port.
134
+
135
+ Args:
136
+ port: Port number to free
137
+
138
+ Returns:
139
+ True if a process was killed, False otherwise
140
+ """
141
+ pid = find_process_on_port(port)
142
+ if pid:
143
+ try:
144
+ proc = psutil.Process(pid)
145
+ proc.kill()
146
+ logger.info(f"Killed process {proc.name()} (PID: {pid}) using port {port}")
147
+ return True
148
+ except (psutil.NoSuchProcess, psutil.AccessDenied) as e:
149
+ logger.warning(f"Failed to kill process on port {port}: {e}")
150
+ return False
151
+
152
+
153
+ def is_port_available(port: int, host: str = "localhost") -> bool:
154
+ """
155
+ Check if a port is available for use.
156
+
157
+ Args:
158
+ port: Port number to check
159
+ host: Host address (default: localhost)
160
+
161
+ Returns:
162
+ True if port is available, False if in use
163
+ """
164
+ try:
165
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
166
+ sock.bind((host, port))
167
+ return True
168
+ except OSError:
169
+ return False
170
+
171
+
172
+ def find_available_port(
173
+ start: int = DEFAULT_PORT_RANGE_START, end: int = DEFAULT_PORT_RANGE_END
174
+ ) -> int:
175
+ """
176
+ Find the next available port in a range.
177
+
178
+ Args:
179
+ start: Starting port number
180
+ end: Ending port number
181
+
182
+ Returns:
183
+ Next available port number
184
+
185
+ Raises:
186
+ RuntimeError: If no available ports found
187
+ """
188
+ for port in range(start, end + 1):
189
+ if is_port_available(port):
190
+ return port
191
+ raise RuntimeError(f"No available ports found in range {start}-{end}")
192
+
193
+
194
+ class CLIToolsMixin:
195
+ """
196
+ Mixin providing unrestricted CLI command execution with process management.
197
+
198
+ Designed for trusted developer tools - no security restrictions.
199
+ Provides background process support with error detection and graceful shutdown.
200
+ """
201
+
202
+ def __init__(self, *args, **kwargs):
203
+ """Initialize CLI tools with process tracking."""
204
+ super().__init__(*args, **kwargs)
205
+
206
+ self._ensure_cli_tools_initialized()
207
+
208
+ def _ensure_cli_tools_initialized(self) -> None:
209
+ """Ensure platform flags and process registries exist."""
210
+ if getattr(self, "_cli_tools_initialized", False):
211
+ return
212
+
213
+ existing_platform = getattr(self, "platform", None)
214
+ if isinstance(existing_platform, str):
215
+ normalized_platform = existing_platform.lower()
216
+ else:
217
+ normalized_platform = platform.system().lower()
218
+
219
+ self.platform = normalized_platform
220
+ self.is_windows = normalized_platform == "windows"
221
+
222
+ if not hasattr(self, "background_processes"):
223
+ self.background_processes = {} # type: Dict[int, ProcessInfo]
224
+ if not hasattr(self, "port_registry"):
225
+ self.port_registry = {} # type: Dict[int, int]
226
+
227
+ self._cli_tools_initialized = True
228
+
229
+ def register_cli_tools(self) -> None:
230
+ """Register CLI command execution tools."""
231
+ self._ensure_cli_tools_initialized()
232
+ from gaia.agents.base.tools import tool
233
+
234
+ @tool(
235
+ name="run_cli_command",
236
+ description="Execute any CLI command (npm, python, docker, gh, etc.) with optional background execution for servers. "
237
+ "Automatically detects startup errors and manages process lifecycle.",
238
+ parameters={
239
+ "command": {
240
+ "type": "str",
241
+ "description": "The command to execute (e.g., 'npm run dev', 'python app.py', 'docker ps')",
242
+ "required": True,
243
+ },
244
+ "working_dir": {
245
+ "type": "str",
246
+ "description": "Directory to execute command in (default: current directory)",
247
+ "required": False,
248
+ },
249
+ "background": {
250
+ "type": "bool",
251
+ "description": "Run as background process (for dev servers, long-running processes)",
252
+ "required": False,
253
+ },
254
+ "timeout": {
255
+ "type": "int",
256
+ "description": "Timeout in seconds for foreground commands (default: 120)",
257
+ "required": False,
258
+ },
259
+ "startup_timeout": {
260
+ "type": "int",
261
+ "description": "Timeout for startup error detection in background mode (default: 5)",
262
+ "required": False,
263
+ },
264
+ "expected_port": {
265
+ "type": "int",
266
+ "description": "Port the process should bind to (for verification)",
267
+ "required": False,
268
+ },
269
+ "auto_respond": {
270
+ "type": "str",
271
+ "description": "String to auto-respond to interactive prompts (default: 'y\\n')",
272
+ "required": False,
273
+ },
274
+ },
275
+ )
276
+ def run_cli_command(
277
+ command: str,
278
+ working_dir: str = None,
279
+ background: bool = False,
280
+ timeout: Optional[int] = None,
281
+ startup_timeout: int = 5,
282
+ expected_port: Optional[int] = None,
283
+ auto_respond: str = "y\n",
284
+ ) -> Dict[str, Any]:
285
+ """
286
+ Execute any CLI command without restrictions.
287
+
288
+ Args:
289
+ command: Command to execute
290
+ working_dir: Directory to run command in (default: current directory)
291
+ background: Run as background process
292
+ timeout: Timeout for foreground commands (default: 120s)
293
+ startup_timeout: Timeout for error detection (default: 5s)
294
+ expected_port: Port process should bind to
295
+ auto_respond: Response for interactive prompts
296
+
297
+ Returns:
298
+ Dict with execution status, output, and errors
299
+ """
300
+ try:
301
+ # Use workspace_root if available, else current directory
302
+ if working_dir is None:
303
+ if hasattr(self, "workspace_root") and self.workspace_root:
304
+ working_dir = self.workspace_root
305
+ else:
306
+ working_dir = "."
307
+
308
+ # Resolve working directory
309
+ work_path = Path(working_dir).resolve()
310
+ if not work_path.exists():
311
+ return {
312
+ "status": "error",
313
+ "success": False,
314
+ "error": f"Working directory not found: {working_dir}",
315
+ "has_errors": True,
316
+ }
317
+
318
+ if not work_path.is_dir():
319
+ return {
320
+ "status": "error",
321
+ "success": False,
322
+ "error": f"Path is not a directory: {working_dir}",
323
+ "has_errors": True,
324
+ }
325
+
326
+ # Set default timeout for foreground commands
327
+ if timeout is None and not background:
328
+ timeout = DEFAULT_COMMAND_TIMEOUT_SECS
329
+
330
+ # Detect port from command if not specified
331
+ if expected_port is None:
332
+ expected_port = self._detect_port_from_command(command)
333
+
334
+ # Check for port conflicts before starting
335
+ if expected_port and not is_port_available(expected_port):
336
+ existing_pid = find_process_on_port(expected_port)
337
+ return {
338
+ "status": "error",
339
+ "success": False,
340
+ "error": f"Port {expected_port} is already in use",
341
+ "port": expected_port,
342
+ "blocking_pid": existing_pid,
343
+ "has_errors": True,
344
+ }
345
+
346
+ if background:
347
+ return self._run_background_command(
348
+ command=command,
349
+ work_path=work_path,
350
+ startup_timeout=startup_timeout,
351
+ expected_port=expected_port,
352
+ auto_respond=auto_respond,
353
+ )
354
+ else:
355
+ return self._run_foreground_command(
356
+ command=command,
357
+ work_path=work_path,
358
+ timeout=timeout,
359
+ auto_respond=auto_respond,
360
+ )
361
+
362
+ except Exception as e:
363
+ logger.error(f"Error executing CLI command: {e}")
364
+ return {
365
+ "status": "error",
366
+ "success": False,
367
+ "error": str(e),
368
+ "has_errors": True,
369
+ }
370
+
371
+ @tool(
372
+ name="stop_process",
373
+ description="Stop a background process gracefully (SIGINT/Ctrl+C), with optional force kill",
374
+ parameters={
375
+ "pid": {
376
+ "type": "int",
377
+ "description": "Process ID to stop",
378
+ "required": True,
379
+ },
380
+ "force": {
381
+ "type": "bool",
382
+ "description": "Force kill immediately without graceful shutdown",
383
+ "required": False,
384
+ },
385
+ },
386
+ )
387
+ def stop_process(pid: int, force: bool = False) -> Dict[str, Any]:
388
+ """
389
+ Stop a background process with graceful shutdown.
390
+
391
+ Args:
392
+ pid: Process ID to stop
393
+ force: Skip graceful shutdown and force kill
394
+
395
+ Returns:
396
+ Dict with stop status and method used
397
+ """
398
+ return self._stop_process(pid, force)
399
+
400
+ @tool(
401
+ name="list_processes",
402
+ description="List all managed background processes",
403
+ parameters={},
404
+ )
405
+ def list_processes() -> Dict[str, Any]:
406
+ """
407
+ List all managed background processes.
408
+
409
+ Returns:
410
+ Dict with list of running processes and their info
411
+ """
412
+ return self._list_processes()
413
+
414
+ @tool(
415
+ name="get_process_logs",
416
+ description="Get output logs from a background process",
417
+ parameters={
418
+ "pid": {
419
+ "type": "int",
420
+ "description": "Process ID to get logs for",
421
+ "required": True,
422
+ },
423
+ "lines": {
424
+ "type": "int",
425
+ "description": "Number of lines to return (default: 50)",
426
+ "required": False,
427
+ },
428
+ },
429
+ )
430
+ def get_process_logs(pid: int, lines: int = 50) -> Dict[str, Any]:
431
+ """
432
+ Get output logs from a background process.
433
+
434
+ Args:
435
+ pid: Process ID
436
+ lines: Number of lines to return
437
+
438
+ Returns:
439
+ Dict with log output
440
+ """
441
+ return self._get_process_logs(pid, lines)
442
+
443
+ @tool(
444
+ name="cleanup_all_processes",
445
+ description="Stop all managed background processes gracefully",
446
+ parameters={},
447
+ )
448
+ def cleanup_all_processes() -> Dict[str, Any]:
449
+ """
450
+ Stop all managed background processes.
451
+
452
+ Returns:
453
+ Dict with cleanup status
454
+ """
455
+ return self._cleanup_all_processes()
456
+
457
+ def _detect_port_from_command(self, command: str) -> Optional[int]:
458
+ """
459
+ Detect port number from common command patterns.
460
+
461
+ Args:
462
+ command: Command string
463
+
464
+ Returns:
465
+ Detected port number or None
466
+ """
467
+ # Common port patterns
468
+ patterns = [
469
+ r"PORT[=\s]+(\d+)", # PORT=3000
470
+ r"--port[=\s]+(\d+)", # --port 3000
471
+ r"-p\s+(\d+)", # -p 3000
472
+ r":(\d+)", # localhost:3000
473
+ ]
474
+
475
+ for pattern in patterns:
476
+ match = re.search(pattern, command, re.IGNORECASE)
477
+ if match:
478
+ return int(match.group(1))
479
+
480
+ # Default ports for common commands
481
+ if "npm run dev" in command or "next dev" in command:
482
+ return 3000
483
+ if "vite" in command.lower():
484
+ return 5173
485
+ if "flask run" in command:
486
+ return 5000
487
+ if "uvicorn" in command:
488
+ return 8000
489
+
490
+ return None
491
+
492
+ def _run_foreground_command(
493
+ self,
494
+ command: str,
495
+ work_path: Path,
496
+ timeout: int,
497
+ auto_respond: str,
498
+ ) -> Dict[str, Any]:
499
+ """
500
+ Execute a command in foreground mode.
501
+
502
+ Args:
503
+ command: Command to execute
504
+ work_path: Working directory
505
+ timeout: Command timeout
506
+ auto_respond: Auto-response for interactive prompts
507
+
508
+ Returns:
509
+ Dict with command output and status
510
+ """
511
+ try:
512
+ # Log to debug instead of info
513
+ logger.debug(f"Executing foreground command: {command}")
514
+
515
+ # Check if console is available for preview
516
+ console = getattr(self, "console", None)
517
+
518
+ if console:
519
+ console.start_file_preview(command, max_lines=15, title_prefix="💻")
520
+ elif getattr(self, "console", None):
521
+ self.console.print_command_executing(command)
522
+ else:
523
+ print(f"\nExecuting Command: {command}")
524
+
525
+ # Run command with real-time streaming
526
+ # Use stdin=PIPE to prevent inheriting terminal stdin (which can cause
527
+ # hangs waiting for input), while still allowing auto_respond to work
528
+ process = subprocess.Popen(
529
+ command,
530
+ cwd=str(work_path),
531
+ shell=True,
532
+ stdin=subprocess.PIPE,
533
+ stdout=subprocess.PIPE,
534
+ stderr=subprocess.PIPE,
535
+ text=True,
536
+ encoding="utf-8",
537
+ bufsize=1,
538
+ )
539
+
540
+ # Send auto_respond and close stdin to prevent command from waiting
541
+ if process.stdin:
542
+ try:
543
+ if auto_respond:
544
+ process.stdin.write(auto_respond)
545
+ process.stdin.close()
546
+ except Exception as e:
547
+ logger.debug(f"Error writing to stdin: {e}")
548
+
549
+ stdout_lines = []
550
+ stderr_lines = []
551
+
552
+ # Function to read and print streams
553
+ def read_stream(stream, output_list, is_stderr=False):
554
+ for line in iter(stream.readline, ""):
555
+ output_list.append(line)
556
+ if console:
557
+ console.update_file_preview(line)
558
+ else:
559
+ if is_stderr:
560
+ # Print stderr in red if it's not just info/warning
561
+ print(f"{line.rstrip()}", flush=True)
562
+ else:
563
+ print(line.rstrip(), flush=True)
564
+ stream.close()
565
+
566
+ # Start threads to read streams
567
+ stdout_thread = Thread(
568
+ target=read_stream, args=(process.stdout, stdout_lines, False)
569
+ )
570
+ stderr_thread = Thread(
571
+ target=read_stream, args=(process.stderr, stderr_lines, True)
572
+ )
573
+
574
+ stdout_thread.start()
575
+ stderr_thread.start()
576
+
577
+ # Wait for command to finish
578
+ try:
579
+ process.wait(timeout=timeout)
580
+ except subprocess.TimeoutExpired:
581
+ process.kill()
582
+ stdout_thread.join()
583
+ stderr_thread.join()
584
+ raise subprocess.TimeoutExpired(
585
+ process.args,
586
+ timeout,
587
+ output="".join(stdout_lines),
588
+ stderr="".join(stderr_lines),
589
+ )
590
+
591
+ stdout_thread.join()
592
+ stderr_thread.join()
593
+
594
+ # Stop preview
595
+ if console:
596
+ console.stop_file_preview()
597
+
598
+ # Collect full output
599
+ stdout = "".join(stdout_lines)
600
+ stderr = "".join(stderr_lines)
601
+ returncode = process.returncode
602
+
603
+ # Print status
604
+ if not console:
605
+ if returncode == 0:
606
+ print("✓ Command successful\n")
607
+ else:
608
+ print(f"✗ Command failed (exit code {returncode})\n")
609
+
610
+ # Scan for errors
611
+ errors = self._scan_output_for_errors(stdout + stderr)
612
+
613
+ truncated = False
614
+ max_output = MAX_OUTPUT_CHARS
615
+
616
+ if len(stdout) > max_output:
617
+ stdout = stdout[:max_output] + "\n...output truncated (stdout)..."
618
+ truncated = True
619
+
620
+ if len(stderr) > max_output:
621
+ stderr = stderr[:max_output] + "\n...output truncated (stderr)..."
622
+ truncated = True
623
+
624
+ return {
625
+ "status": "error" if returncode != 0 else "success",
626
+ "success": returncode == 0,
627
+ "command": command,
628
+ "stdout": stdout,
629
+ "stderr": stderr,
630
+ "return_code": returncode,
631
+ "has_errors": returncode != 0 or len(errors) > 0,
632
+ "error": stderr if returncode != 0 else None,
633
+ "errors": errors,
634
+ "output_truncated": truncated,
635
+ "working_dir": str(work_path),
636
+ }
637
+
638
+ except subprocess.TimeoutExpired as e:
639
+ # Ensure preview is stopped on timeout
640
+ if getattr(self, "console", None):
641
+ self.console.stop_file_preview()
642
+
643
+ # Handle both string and bytes output (text=True returns strings)
644
+ stdout_str = ""
645
+ if e.stdout:
646
+ stdout_str = (
647
+ e.stdout
648
+ if isinstance(e.stdout, str)
649
+ else e.stdout.decode("utf-8", errors="replace")
650
+ )
651
+
652
+ stderr_str = ""
653
+ if e.stderr:
654
+ stderr_str = (
655
+ e.stderr
656
+ if isinstance(e.stderr, str)
657
+ else e.stderr.decode("utf-8", errors="replace")
658
+ )
659
+
660
+ return {
661
+ "status": "error",
662
+ "success": False,
663
+ "error": f"Command timed out after {timeout} seconds",
664
+ "command": command,
665
+ "stdout": stdout_str,
666
+ "stderr": stderr_str,
667
+ "has_errors": True,
668
+ "timed_out": True,
669
+ "timeout": timeout,
670
+ }
671
+
672
+ except Exception as e:
673
+ # Ensure preview is stopped on error
674
+ if getattr(self, "console", None):
675
+ self.console.stop_file_preview()
676
+
677
+ return {
678
+ "status": "error",
679
+ "success": False,
680
+ "error": str(e),
681
+ "command": command,
682
+ "has_errors": True,
683
+ }
684
+
685
+ def _run_background_command(
686
+ self,
687
+ command: str,
688
+ work_path: Path,
689
+ startup_timeout: int,
690
+ expected_port: Optional[int],
691
+ auto_respond: str,
692
+ ) -> Dict[str, Any]:
693
+ """
694
+ Execute a command in background mode with error detection.
695
+
696
+ Args:
697
+ command: Command to execute
698
+ work_path: Working directory
699
+ startup_timeout: Time to monitor for errors
700
+ expected_port: Expected port for the process
701
+ auto_respond: Auto-response for interactive prompts
702
+
703
+ Returns:
704
+ Dict with process info or error details
705
+ """
706
+ self._ensure_cli_tools_initialized()
707
+ try:
708
+ logger.info(f"Starting background command: {command}")
709
+
710
+ # Create log file
711
+ log_file = tempfile.NamedTemporaryFile(
712
+ mode="w",
713
+ suffix=".log",
714
+ prefix="gaia_cli_",
715
+ delete=False,
716
+ encoding="utf-8",
717
+ )
718
+
719
+ # Start process
720
+ if self.is_windows:
721
+ # Windows: CREATE_NEW_PROCESS_GROUP for Ctrl+C support
722
+ process = subprocess.Popen(
723
+ command,
724
+ cwd=str(work_path),
725
+ shell=True,
726
+ stdout=log_file,
727
+ stderr=subprocess.STDOUT,
728
+ stdin=subprocess.PIPE if auto_respond else subprocess.DEVNULL,
729
+ creationflags=subprocess.CREATE_NEW_PROCESS_GROUP,
730
+ )
731
+ else:
732
+ # Unix: start_new_session for signal isolation
733
+ process = subprocess.Popen(
734
+ command,
735
+ cwd=str(work_path),
736
+ shell=True,
737
+ stdout=log_file,
738
+ stderr=subprocess.STDOUT,
739
+ stdin=subprocess.PIPE if auto_respond else subprocess.DEVNULL,
740
+ start_new_session=True,
741
+ )
742
+
743
+ log_file.close()
744
+
745
+ # Auto-respond to prompts in background thread
746
+ if auto_respond:
747
+
748
+ def send_input():
749
+ try:
750
+ time.sleep(0.5) # Small delay for process to start
751
+ if process.stdin:
752
+ process.stdin.write(auto_respond.encode())
753
+ process.stdin.flush()
754
+ process.stdin.close()
755
+ except Exception as e:
756
+ logger.debug(f"Auto-respond thread error: {e}")
757
+
758
+ Thread(target=send_input, daemon=True).start()
759
+
760
+ # Monitor for startup errors
761
+ start_time = time.time()
762
+ errors_detected = []
763
+ output_buffer = []
764
+
765
+ logger.info(
766
+ f"Monitoring process {process.pid} for {startup_timeout} seconds..."
767
+ )
768
+
769
+ while time.time() - start_time < startup_timeout:
770
+ # Check if process died
771
+ if process.poll() is not None:
772
+ errors_detected.append(
773
+ {
774
+ "type": "process_died",
775
+ "message": f"Process exited with code {process.returncode}",
776
+ }
777
+ )
778
+ break
779
+
780
+ # Read recent output
781
+ try:
782
+ with open(log_file.name, "r", encoding="utf-8") as f:
783
+ new_output = f.read()
784
+ if new_output and new_output != "".join(output_buffer):
785
+ output_buffer.append(new_output)
786
+ # Scan for errors
787
+ errors = self._scan_output_for_errors(new_output)
788
+ errors_detected.extend(errors)
789
+
790
+ # Stop if critical errors found
791
+ if any(
792
+ e["type"]
793
+ in ["port_conflict", "missing_deps", "permissions"]
794
+ for e in errors
795
+ ):
796
+ break
797
+
798
+ except Exception as e:
799
+ logger.debug(f"Error reading log file: {e}")
800
+
801
+ time.sleep(0.1)
802
+
803
+ # Check if process is still alive
804
+ is_alive = process.poll() is None
805
+
806
+ # If errors detected or process died, stop it
807
+ if errors_detected or not is_alive:
808
+ if is_alive:
809
+ self._terminate_process(process.pid)
810
+
811
+ # Read final output
812
+ try:
813
+ with open(log_file.name, "r", encoding="utf-8") as f:
814
+ final_output = f.read()
815
+ except Exception:
816
+ final_output = "".join(output_buffer)
817
+
818
+ return {
819
+ "success": False,
820
+ "command": command,
821
+ "output": final_output[-MAX_ERROR_OUTPUT_CHARS:],
822
+ "errors": errors_detected,
823
+ "has_errors": True,
824
+ "log_file": log_file.name,
825
+ }
826
+
827
+ # Check port is bound if expected
828
+ if expected_port:
829
+ port_ready = False
830
+ for _ in range(10): # Check for 1 second
831
+ if not is_port_available(expected_port):
832
+ port_ready = True
833
+ self.port_registry[expected_port] = process.pid
834
+ break
835
+ time.sleep(0.1)
836
+
837
+ if not port_ready:
838
+ self._terminate_process(process.pid)
839
+ return {
840
+ "success": False,
841
+ "error": f"Process started but port {expected_port} not bound",
842
+ "has_errors": True,
843
+ }
844
+
845
+ # Process started successfully!
846
+ process_info = ProcessInfo(
847
+ pid=process.pid,
848
+ command=command,
849
+ working_dir=str(work_path),
850
+ log_file=log_file.name,
851
+ start_time=time.time(),
852
+ port=expected_port,
853
+ )
854
+
855
+ self.background_processes[process.pid] = process_info
856
+
857
+ logger.info(f"Background process started successfully: PID {process.pid}")
858
+
859
+ return {
860
+ "success": True,
861
+ "pid": process.pid,
862
+ "command": command,
863
+ "port": expected_port,
864
+ "log_file": log_file.name,
865
+ "background": True,
866
+ "message": f"Process started with PID {process.pid}"
867
+ + (f" on port {expected_port}" if expected_port else ""),
868
+ }
869
+
870
+ except Exception as e:
871
+ logger.error(f"Error starting background command: {e}")
872
+ return {
873
+ "success": False,
874
+ "error": str(e),
875
+ "has_errors": True,
876
+ }
877
+
878
+ def _scan_output_for_errors(self, output: str) -> List[Dict[str, Any]]:
879
+ """
880
+ Scan output for known error patterns.
881
+
882
+ Args:
883
+ output: Command output to scan
884
+
885
+ Returns:
886
+ List of detected errors
887
+ """
888
+ detected_errors = []
889
+
890
+ for error_type, patterns in ERROR_PATTERNS.items():
891
+ for pattern in patterns:
892
+ matches = re.finditer(pattern, output, re.IGNORECASE | re.MULTILINE)
893
+ for match in matches:
894
+ error_info = {
895
+ "type": error_type,
896
+ "message": match.group(0),
897
+ }
898
+
899
+ # Extract specific details
900
+ if error_type == "port_conflict" and len(match.groups()) > 0:
901
+ error_info["port"] = int(match.group(1))
902
+ elif error_type == "missing_deps" and len(match.groups()) > 0:
903
+ error_info["module"] = match.group(1)
904
+
905
+ detected_errors.append(error_info)
906
+
907
+ return detected_errors
908
+
909
+ def _stop_process(self, pid: int, force: bool = False) -> Dict[str, Any]:
910
+ """
911
+ Stop a background process gracefully.
912
+
913
+ Args:
914
+ pid: Process ID
915
+ force: Skip graceful shutdown
916
+
917
+ Returns:
918
+ Dict with stop status
919
+ """
920
+ self._ensure_cli_tools_initialized()
921
+ if pid not in self.background_processes:
922
+ return {
923
+ "success": False,
924
+ "error": f"Process {pid} not found in managed processes",
925
+ }
926
+
927
+ try:
928
+ # Get process info
929
+ proc_info = self.background_processes[pid]
930
+
931
+ # Try to terminate
932
+ method = "forced" if force else "graceful"
933
+ self._terminate_process(pid, force=force)
934
+
935
+ # Remove from tracking
936
+ del self.background_processes[pid]
937
+
938
+ # Remove port registry
939
+ if proc_info.port and proc_info.port in self.port_registry:
940
+ del self.port_registry[proc_info.port]
941
+
942
+ logger.info(f"Stopped process {pid} ({method})")
943
+
944
+ return {
945
+ "success": True,
946
+ "pid": pid,
947
+ "method": method,
948
+ "message": f"Process {pid} stopped successfully",
949
+ }
950
+
951
+ except Exception as e:
952
+ logger.error(f"Error stopping process {pid}: {e}")
953
+ return {
954
+ "success": False,
955
+ "error": str(e),
956
+ }
957
+
958
+ def _terminate_process(self, pid: int, force: bool = False):
959
+ """
960
+ Terminate a process using platform-specific methods.
961
+
962
+ Args:
963
+ pid: Process ID to terminate
964
+ force: Skip graceful termination
965
+ """
966
+ self._ensure_cli_tools_initialized()
967
+ try:
968
+ proc = psutil.Process(pid)
969
+
970
+ if self.is_windows:
971
+ if force:
972
+ # Force kill with taskkill
973
+ os.system(f"taskkill /F /T /PID {pid}")
974
+ else:
975
+ # Try graceful termination first
976
+ try:
977
+ # pylint: disable=no-member
978
+ proc.send_signal(signal.CTRL_C_EVENT)
979
+ proc.wait(timeout=5)
980
+ except (psutil.TimeoutExpired, psutil.NoSuchProcess):
981
+ # Fallback to taskkill
982
+ os.system(f"taskkill /F /T /PID {pid}")
983
+ else:
984
+ # Unix/Linux/macOS
985
+ if not force:
986
+ # Send SIGINT (Ctrl+C)
987
+ try:
988
+ os.kill(pid, signal.SIGINT)
989
+ proc.wait(timeout=5)
990
+ return # Success!
991
+ except (psutil.TimeoutExpired, ProcessLookupError):
992
+ pass # Continue to SIGTERM
993
+
994
+ # Send SIGTERM (Unix only - killpg not available on Windows)
995
+ if hasattr(os, "killpg"):
996
+ try:
997
+ os.killpg(os.getpgid(pid), signal.SIGTERM)
998
+ proc.wait(timeout=2)
999
+ return # Success!
1000
+ except (OSError, ProcessLookupError, psutil.TimeoutExpired):
1001
+ pass # Continue to SIGKILL
1002
+
1003
+ # Force kill with SIGKILL (Unix) or terminate (Windows)
1004
+ if hasattr(os, "killpg") and hasattr(signal, "SIGKILL"):
1005
+ try:
1006
+ # pylint: disable=no-member
1007
+ os.killpg(os.getpgid(pid), signal.SIGTERM)
1008
+ proc.wait(timeout=2)
1009
+ return # Success!
1010
+ except (OSError, ProcessLookupError, psutil.TimeoutExpired):
1011
+ pass # Continue to SIGKILL
1012
+
1013
+ # Force kill with SIGKILL
1014
+ try:
1015
+ # pylint: disable=no-member
1016
+ os.killpg(os.getpgid(pid), signal.SIGKILL)
1017
+ except (OSError, ProcessLookupError):
1018
+ # Fallback to individual kill
1019
+ try:
1020
+ proc.kill()
1021
+ except psutil.NoSuchProcess:
1022
+ pass # Already dead
1023
+
1024
+ except psutil.NoSuchProcess:
1025
+ logger.debug(f"Process {pid} already terminated")
1026
+ except Exception as e:
1027
+ logger.warning(f"Error terminating process {pid}: {e}")
1028
+
1029
+ def _list_processes(self) -> Dict[str, Any]:
1030
+ """
1031
+ List all managed background processes.
1032
+
1033
+ Returns:
1034
+ Dict with process list
1035
+ """
1036
+ self._ensure_cli_tools_initialized()
1037
+ processes = []
1038
+
1039
+ for pid, info in self.background_processes.items():
1040
+ # Check if process is still running
1041
+ try:
1042
+ proc = psutil.Process(pid)
1043
+ is_running = proc.is_running()
1044
+ except psutil.NoSuchProcess:
1045
+ is_running = False
1046
+
1047
+ processes.append(
1048
+ {
1049
+ "pid": pid,
1050
+ "command": info.command,
1051
+ "working_dir": info.working_dir,
1052
+ "port": info.port,
1053
+ "running": is_running,
1054
+ "runtime_seconds": time.time() - info.start_time,
1055
+ "log_file": info.log_file,
1056
+ }
1057
+ )
1058
+
1059
+ return {
1060
+ "success": True,
1061
+ "count": len(processes),
1062
+ "processes": processes,
1063
+ }
1064
+
1065
+ def _get_process_logs(self, pid: int, lines: int = 50) -> Dict[str, Any]:
1066
+ """
1067
+ Get output logs from a background process.
1068
+
1069
+ Args:
1070
+ pid: Process ID
1071
+ lines: Number of lines to return
1072
+
1073
+ Returns:
1074
+ Dict with log output
1075
+ """
1076
+ self._ensure_cli_tools_initialized()
1077
+ if pid not in self.background_processes:
1078
+ return {
1079
+ "success": False,
1080
+ "error": f"Process {pid} not found",
1081
+ }
1082
+
1083
+ proc_info = self.background_processes[pid]
1084
+
1085
+ try:
1086
+ with open(proc_info.log_file, "r", encoding="utf-8") as f:
1087
+ all_lines = f.readlines()
1088
+ recent_lines = (
1089
+ all_lines[-lines:] if len(all_lines) > lines else all_lines
1090
+ )
1091
+
1092
+ return {
1093
+ "success": True,
1094
+ "pid": pid,
1095
+ "lines": len(recent_lines),
1096
+ "output": "".join(recent_lines),
1097
+ "log_file": proc_info.log_file,
1098
+ }
1099
+
1100
+ except Exception as e:
1101
+ return {
1102
+ "success": False,
1103
+ "error": str(e),
1104
+ }
1105
+
1106
+ def _cleanup_all_processes(self) -> Dict[str, Any]:
1107
+ """
1108
+ Stop all managed background processes.
1109
+
1110
+ Returns:
1111
+ Dict with cleanup status
1112
+ """
1113
+ self._ensure_cli_tools_initialized()
1114
+ pids = list(self.background_processes.keys())
1115
+ stopped = []
1116
+ failed = []
1117
+
1118
+ for pid in pids:
1119
+ result = self._stop_process(pid, force=False)
1120
+ if result.get("success"):
1121
+ stopped.append(pid)
1122
+ else:
1123
+ failed.append(pid)
1124
+
1125
+ return {
1126
+ "success": len(failed) == 0,
1127
+ "stopped": stopped,
1128
+ "failed": failed,
1129
+ "message": f"Stopped {len(stopped)} processes, {len(failed)} failures",
1130
+ }
1131
+
1132
+ def __del__(self):
1133
+ """Cleanup all processes on deletion."""
1134
+ if hasattr(self, "background_processes"):
1135
+ try:
1136
+ self._cleanup_all_processes()
1137
+ except Exception as e:
1138
+ logger.debug(f"Error cleaning up processes in __del__: {e}")