cmdbox 0.6.0.4__py3-none-any.whl → 0.6.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.

Potentially problematic release.


This version of cmdbox might be problematic. Click here for more details.

Files changed (220) hide show
  1. cmdbox/app/app.py +2 -2
  2. cmdbox/app/auth/signin.py +144 -28
  3. cmdbox/app/common.py +40 -3
  4. cmdbox/app/edge.py +1 -1
  5. cmdbox/app/edge_tool.py +1 -1
  6. cmdbox/app/features/cli/agent_base.py +1 -335
  7. cmdbox/app/features/cli/cmdbox_audit_search.py +0 -2
  8. cmdbox/app/features/cli/cmdbox_audit_write.py +9 -0
  9. cmdbox/app/features/cli/cmdbox_cmd_list.py +1 -1
  10. cmdbox/app/features/cli/cmdbox_cmd_load.py +1 -1
  11. cmdbox/app/features/cli/cmdbox_mcp_proxy.py +90 -0
  12. cmdbox/app/features/cli/cmdbox_web_gencert.py +25 -2
  13. cmdbox/app/features/cli/cmdbox_web_start.py +4 -1
  14. cmdbox/app/features/web/cmdbox_web_signin.py +1 -1
  15. cmdbox/app/mcp.py +375 -0
  16. cmdbox/app/options.py +2 -0
  17. cmdbox/app/web.py +34 -6
  18. cmdbox/autoload.py +10 -0
  19. cmdbox/extensions/user_list.yml +25 -1
  20. cmdbox/licenses/{LICENSE.Deprecated.1.2.18(MIT License).txt → LICENSE_PyJWT_2_10_1_MIT_License.txt} +2 -2
  21. cmdbox/licenses/LICENSE_exceptiongroup_1_3_0_MIT_License.txt +73 -0
  22. cmdbox/licenses/LICENSE_fastmcp_2_9_2_Apache_Software_License.txt +201 -0
  23. cmdbox/licenses/{LICENSE.graphviz.0.20.3(MIT License).txt → LICENSE_graphviz_0_21_UNKNOWN.txt} +1 -1
  24. cmdbox/licenses/LICENSE_jaraco_functools_4_2_1_UNKNOWN.txt +18 -0
  25. cmdbox/licenses/{LICENSE.numpy.2.2.5(BSD License).txt → LICENSE_numpy_2_3_1_BSD_License.txt} +8 -8
  26. cmdbox/licenses/LICENSE_openapi-pydantic_0_5_1_MIT_License.txt +40 -0
  27. cmdbox/licenses/LICENSE_propcache_0_3_2_Apache_Software_License.txt +202 -0
  28. cmdbox/licenses/LICENSE_proto-plus_1_26_1_Apache_Software_License.txt +202 -0
  29. cmdbox/licenses/LICENSE_shellingham_1_5_4_ISC_License-ISCL.txt +13 -0
  30. cmdbox/licenses/LICENSE_sphinx-last-updated-by-git_0_3_8_BSD_License.txt +22 -0
  31. cmdbox/licenses/LICENSE_tenacity_8_5_0_Apache_Software_License.txt +202 -0
  32. cmdbox/licenses/LICENSE_tokenizers_0_21_2_Apache_Software_License.txt +1 -0
  33. cmdbox/licenses/LICENSE_typer_0_16_0_MIT_License.txt +21 -0
  34. cmdbox/licenses/LICENSE_typing-inspection_0_4_1_UNKNOWN.txt +21 -0
  35. cmdbox/licenses/LICENSE_yarl_1_20_1_Apache_Software_License.txt +202 -0
  36. cmdbox/licenses/LICENSE_zipp_3_23_0_UNKNOWN.txt +18 -0
  37. cmdbox/licenses/files.txt +176 -166
  38. cmdbox/logconf_mcp.yml +43 -0
  39. cmdbox/version.py +2 -2
  40. cmdbox/web/agent.html +1 -33
  41. cmdbox/web/assets/cmdbox/audit.js +1 -1
  42. cmdbox/web/assets/cmdbox/common.js +47 -4
  43. cmdbox/web/assets/cmdbox/svgicon.js +122 -0
  44. cmdbox/web/assets/cmdbox/users.js +4 -3
  45. cmdbox/web/audit.html +1 -35
  46. cmdbox/web/filer.html +1 -13
  47. cmdbox/web/gui.html +2 -50
  48. cmdbox/web/result.html +2 -46
  49. cmdbox/web/signin.html +1 -26
  50. cmdbox/web/users.html +1 -41
  51. {cmdbox-0.6.0.4.dist-info → cmdbox-0.6.1.dist-info}/METADATA +31 -6
  52. cmdbox-0.6.1.dist-info/RECORD +383 -0
  53. cmdbox/licenses/LICENSE.keyring.25.6.0(MIT License).txt +0 -17
  54. cmdbox/licenses/LICENSE.typing-inspection.0.4.0(MIT License).txt +0 -21
  55. cmdbox/licenses/LICENSE.wrapt.1.17.2(BSD License).txt +0 -24
  56. cmdbox/licenses/LICENSE.zipp.3.21.0(MIT License).txt +0 -17
  57. cmdbox-0.6.0.4.dist-info/RECORD +0 -368
  58. /cmdbox/licenses/{LICENSE.Authlib.1.5.2(BSD License).txt → LICENSE_Authlib_1_6_0_BSD_License.txt} +0 -0
  59. /cmdbox/licenses/{LICENSE.Jinja2.3.1.6(BSD License).txt → LICENSE_Jinja2_3_1_6_BSD_License.txt} +0 -0
  60. /cmdbox/licenses/{LICENSE.MarkupSafe.3.0.2(BSD License).txt → LICENSE_MarkupSafe_3_0_2_BSD_License.txt} +0 -0
  61. /cmdbox/licenses/{LICENSE.PyYAML.6.0.2(MIT License).txt → LICENSE_PyYAML_6_0_2_MIT_License.txt} +0 -0
  62. /cmdbox/licenses/{LICENSE.Pygments.2.19.1(BSD License).txt → LICENSE_Pygments_2_19_2_BSD_License.txt} +0 -0
  63. /cmdbox/licenses/{LICENSE.SQLAlchemy.2.0.40(MIT License).txt → LICENSE_SQLAlchemy_2_0_41_MIT.txt} +0 -0
  64. /cmdbox/licenses/{LICENSE.Sphinx.8.2.3(UNKNOWN).txt → LICENSE_Sphinx_8_2_3_UNKNOWN.txt} +0 -0
  65. /cmdbox/licenses/{LICENSE.aiohappyeyeballs.2.6.1(Python Software Foundation License).txt → LICENSE_aiohappyeyeballs_2_6_1_Python_Software_Foundation_License.txt} +0 -0
  66. /cmdbox/licenses/{LICENSE.aiohttp.3.11.18(Apache Software License).txt → LICENSE_aiohttp_3_12_13_Apache-2_0.txt} +0 -0
  67. /cmdbox/licenses/{LICENSE.aiosignal.1.3.2(Apache Software License).txt → LICENSE_aiosignal_1_3_2_Apache_Software_License.txt} +0 -0
  68. /cmdbox/licenses/{LICENSE.alabaster.1.0.0(BSD License).txt → LICENSE_alabaster_1_0_0_BSD_License.txt} +0 -0
  69. /cmdbox/licenses/{LICENSE.annotated-types.0.7.0(MIT License).txt → LICENSE_annotated-types_0_7_0_MIT_License.txt} +0 -0
  70. /cmdbox/licenses/{LICENSE.anyio.4.9.0(MIT License).txt → LICENSE_anyio_4_9_0_MIT_License.txt} +0 -0
  71. /cmdbox/licenses/{LICENSE.argcomplete.3.6.2(Apache Software License).txt → LICENSE_argcomplete_3_6_2_Apache_Software_License.txt} +0 -0
  72. /cmdbox/licenses/{LICENSE.async-timeout.5.0.1(Apache Software License).txt → LICENSE_async-timeout_5_0_1_Apache_Software_License.txt} +0 -0
  73. /cmdbox/licenses/{LICENSE.attrs.25.3.0(UNKNOWN).txt → LICENSE_attrs_25_3_0_UNKNOWN.txt} +0 -0
  74. /cmdbox/licenses/{LICENSE.babel.2.17.0(BSD License).txt → LICENSE_babel_2_17_0_BSD_License.txt} +0 -0
  75. /cmdbox/licenses/{LICENSE.backports.tarfile.1.2.0(MIT License).txt → LICENSE_backports_tarfile_1_2_0_MIT_License.txt} +0 -0
  76. /cmdbox/licenses/{LICENSE.cachetools.5.5.2(MIT License).txt → LICENSE_cachetools_5_5_2_MIT_License.txt} +0 -0
  77. /cmdbox/licenses/{LICENSE.certifi.2025.4.26(Mozilla Public License 2.0 (MPL 2.0)).txt → LICENSE_certifi_2025_6_15_Mozilla_Public_License_2_0-MPL_2_0.txt} +0 -0
  78. /cmdbox/licenses/{LICENSE.cffi.1.17.1(MIT License).txt → LICENSE_cffi_1_17_1_MIT_License.txt} +0 -0
  79. /cmdbox/licenses/{LICENSE.charset-normalizer.3.4.2(MIT License).txt → LICENSE_charset-normalizer_3_4_2_MIT_License.txt} +0 -0
  80. /cmdbox/licenses/{LICENSE.click.8.2.0(UNKNOWN).txt → LICENSE_click_8_2_1_UNKNOWN.txt} +0 -0
  81. /cmdbox/licenses/{LICENSE.jiter.0.9.0(MIT License).txt → LICENSE_cloudpickle_3_1_1_BSD_License.txt} +0 -0
  82. /cmdbox/licenses/{LICENSE.colorama.0.4.6(BSD License).txt → LICENSE_colorama_0_4_6_BSD_License.txt} +0 -0
  83. /cmdbox/licenses/{LICENSE.cryptography.44.0.3(Apache Software License; BSD License).txt → LICENSE_cryptography_45_0_4_Apache-2_0_OR_BSD-3-Clause.txt} +0 -0
  84. /cmdbox/licenses/{LICENSE.distro.1.9.0(Apache Software License).txt → LICENSE_distro_1_9_0_Apache_Software_License.txt} +0 -0
  85. /cmdbox/licenses/{LICENSE.docstring_parser.0.16(MIT License).txt → LICENSE_docstring_parser_0_16_MIT_License.txt} +0 -0
  86. /cmdbox/licenses/{LICENSE.docutils.0.21.2(BSD License; GNU General Public License (GPL); Public Domain; Python Software Foundation License).txt → LICENSE_docutils_0_21_2_BSD_License-GNU_General_Public_License-GPL-Public_Domain-Python_Software_Foundation_License.txt} +0 -0
  87. /cmdbox/licenses/{LICENSE.fastapi.0.115.12(MIT License).txt → LICENSE_fastapi_0_115_14_MIT_License.txt} +0 -0
  88. /cmdbox/licenses/{LICENSE.filelock.3.18.0(The Unlicense (Unlicense)).txt → LICENSE_filelock_3_18_0_The_Unlicense-Unlicense.txt} +0 -0
  89. /cmdbox/licenses/{LICENSE.frozenlist.1.6.0(Apache-2.0).txt → LICENSE_frozenlist_1_7_0_Apache-2_0.txt} +0 -0
  90. /cmdbox/licenses/{LICENSE.fsspec.2025.3.2(BSD License).txt → LICENSE_fsspec_2025_5_1_BSD_License.txt} +0 -0
  91. /cmdbox/licenses/{LICENSE.gevent.25.4.2(MIT).txt → LICENSE_gevent_25_5_1_MIT.txt} +0 -0
  92. /cmdbox/licenses/{LICENSE.google-adk.0.5.0(Apache Software License).txt → LICENSE_google-adk_1_5_0_Apache_Software_License.txt} +0 -0
  93. /cmdbox/licenses/{LICENSE.google-api-core.2.24.2(Apache Software License).txt → LICENSE_google-api-core_2_25_1_Apache_Software_License.txt} +0 -0
  94. /cmdbox/licenses/{LICENSE.google-api-python-client.2.169.0(Apache Software License).txt → LICENSE_google-api-python-client_2_174_0_Apache_Software_License.txt} +0 -0
  95. /cmdbox/licenses/{LICENSE.google-auth-httplib2.0.2.0(Apache Software License).txt → LICENSE_google-auth-httplib2_0_2_0_Apache_Software_License.txt} +0 -0
  96. /cmdbox/licenses/{LICENSE.google-auth.2.40.1(Apache Software License).txt → LICENSE_google-auth_2_40_3_Apache_Software_License.txt} +0 -0
  97. /cmdbox/licenses/{LICENSE.google-cloud-aiplatform.1.92.0(Apache 2.0).txt → LICENSE_google-cloud-aiplatform_1_100_0_Apache_2_0.txt} +0 -0
  98. /cmdbox/licenses/{LICENSE.google-cloud-bigquery.3.31.0(Apache Software License).txt → LICENSE_google-cloud-appengine-logging_1_6_2_Apache_Software_License.txt} +0 -0
  99. /cmdbox/licenses/{LICENSE.google-cloud-core.2.4.3(Apache Software License).txt → LICENSE_google-cloud-audit-log_0_3_2_Apache_Software_License.txt} +0 -0
  100. /cmdbox/licenses/{LICENSE.google-cloud-resource-manager.1.14.2(Apache Software License).txt → LICENSE_google-cloud-bigquery_3_34_0_Apache_Software_License.txt} +0 -0
  101. /cmdbox/licenses/{LICENSE.google-cloud-secret-manager.2.23.3(Apache Software License).txt → LICENSE_google-cloud-core_2_4_3_Apache_Software_License.txt} +0 -0
  102. /cmdbox/licenses/{LICENSE.google-cloud-speech.2.32.0(Apache Software License).txt → LICENSE_google-cloud-logging_3_12_1_Apache_Software_License.txt} +0 -0
  103. /cmdbox/licenses/{LICENSE.google-cloud-storage.2.19.0(Apache Software License).txt → LICENSE_google-cloud-resource-manager_1_14_2_Apache_Software_License.txt} +0 -0
  104. /cmdbox/licenses/{LICENSE.google-cloud-trace.1.16.1(Apache Software License).txt → LICENSE_google-cloud-secret-manager_2_24_0_Apache_Software_License.txt} +0 -0
  105. /cmdbox/licenses/{LICENSE.google-crc32c.1.7.1(Apache 2.0).txt → LICENSE_google-cloud-speech_2_33_0_Apache_Software_License.txt} +0 -0
  106. /cmdbox/licenses/{LICENSE.google-genai.1.14.0(Apache Software License).txt → LICENSE_google-cloud-storage_2_19_0_Apache_Software_License.txt} +0 -0
  107. /cmdbox/licenses/{LICENSE.google-resumable-media.2.7.2(Apache Software License).txt → LICENSE_google-cloud-trace_1_16_2_Apache_Software_License.txt} +0 -0
  108. /cmdbox/licenses/{LICENSE.googleapis-common-protos.1.70.0(Apache Software License).txt → LICENSE_google-crc32c_1_7_1_Apache_2_0.txt} +0 -0
  109. /cmdbox/licenses/{LICENSE.grpc-google-iam-v1.0.14.2(Apache Software License).txt → LICENSE_google-genai_1_23_0_Apache_Software_License.txt} +0 -0
  110. /cmdbox/licenses/{LICENSE.id.1.5.0(Apache Software License).txt → LICENSE_google-resumable-media_2_7_2_Apache_Software_License.txt} +0 -0
  111. /cmdbox/licenses/{LICENSE.importlib_metadata.8.6.1(Apache Software License).txt → LICENSE_googleapis-common-protos_1_70_0_Apache_Software_License.txt} +0 -0
  112. /cmdbox/licenses/{LICENSE.greenlet.3.2.2(MIT AND Python-2.0).txt → LICENSE_greenlet_3_2_3_MIT_AND_Python-2_0.txt} +0 -0
  113. /cmdbox/licenses/{LICENSE.propcache.0.3.1(Apache Software License).txt → LICENSE_grpc-google-iam-v1_0_14_2_Apache_Software_License.txt} +0 -0
  114. /cmdbox/licenses/{LICENSE.grpcio-status.1.71.0(Apache Software License).txt → LICENSE_grpcio-status_1_73_1_Apache_Software_License.txt} +0 -0
  115. /cmdbox/licenses/{LICENSE.grpcio.1.71.0(Apache Software License).txt → LICENSE_grpcio_1_73_1_Apache_Software_License.txt} +0 -0
  116. /cmdbox/licenses/{LICENSE.gunicorn.23.0.0(MIT License).txt → LICENSE_gunicorn_23_0_0_MIT_License.txt} +0 -0
  117. /cmdbox/licenses/{LICENSE.h11.0.16.0(MIT License).txt → LICENSE_h11_0_16_0_MIT_License.txt} +0 -0
  118. /cmdbox/licenses/{LICENSE.httpcore.1.0.9(BSD License).txt → LICENSE_httpcore_1_0_9_BSD_License.txt} +0 -0
  119. /cmdbox/licenses/{LICENSE.httplib2.0.22.0(MIT License).txt → LICENSE_httplib2_0_22_0_MIT_License.txt} +0 -0
  120. /cmdbox/licenses/{LICENSE.httptools.0.6.4(MIT License).txt → LICENSE_httptools_0_6_4_MIT_License.txt} +0 -0
  121. /cmdbox/licenses/{LICENSE.httpx-sse.0.4.0(MIT).txt → LICENSE_httpx-sse_0_4_1_MIT.txt} +0 -0
  122. /cmdbox/licenses/{LICENSE.httpx.0.28.1(BSD License).txt → LICENSE_httpx_0_28_1_BSD_License.txt} +0 -0
  123. /cmdbox/licenses/{LICENSE.huggingface-hub.0.31.1(Apache Software License).txt → LICENSE_huggingface-hub_0_33_1_Apache_Software_License.txt} +0 -0
  124. /cmdbox/licenses/{LICENSE.proto-plus.1.26.1(Apache Software License).txt → LICENSE_id_1_5_0_Apache_Software_License.txt} +0 -0
  125. /cmdbox/licenses/{LICENSE.idna.3.10(BSD License).txt → LICENSE_idna_3_10_BSD_License.txt} +0 -0
  126. /cmdbox/licenses/{LICENSE.imagesize.1.4.1(MIT License).txt → LICENSE_imagesize_1_4_1_MIT_License.txt} +0 -0
  127. /cmdbox/licenses/{LICENSE.yarl.1.20.0(Apache Software License).txt → LICENSE_importlib_metadata_8_7_0_Apache_Software_License.txt} +0 -0
  128. /cmdbox/licenses/{LICENSE.itsdangerous.2.2.0(BSD License).txt → LICENSE_itsdangerous_2_2_0_BSD_License.txt} +0 -0
  129. /cmdbox/licenses/{LICENSE.jaraco.classes.3.4.0(MIT License).txt → LICENSE_jaraco_classes_3_4_0_MIT_License.txt} +0 -0
  130. /cmdbox/licenses/{LICENSE.jaraco.context.6.0.1(MIT License).txt → LICENSE_jaraco_context_6_0_1_MIT_License.txt} +0 -0
  131. /cmdbox/licenses/{LICENSE.sphinxcontrib-applehelp.2.0.0(BSD License).txt → LICENSE_jiter_0_10_0_MIT_License.txt} +0 -0
  132. /cmdbox/licenses/{LICENSE.jsonschema-specifications.2025.4.1(UNKNOWN).txt → LICENSE_jsonschema-specifications_2025_4_1_UNKNOWN.txt} +0 -0
  133. /cmdbox/licenses/{LICENSE.jsonschema.4.23.0(MIT License).txt → LICENSE_jsonschema_4_24_0_UNKNOWN.txt} +0 -0
  134. /cmdbox/licenses/{LICENSE.jaraco.functools.4.1.0(MIT License).txt → LICENSE_keyring_25_6_0_MIT_License.txt} +0 -0
  135. /cmdbox/licenses/{LICENSE.litellm.1.69.0(MIT License).txt → LICENSE_litellm_1_73_6_MIT_License.txt} +0 -0
  136. /cmdbox/licenses/{LICENSE.markdown-it-py.3.0.0(MIT License).txt → LICENSE_markdown-it-py_3_0_0_MIT_License.txt} +0 -0
  137. /cmdbox/licenses/{LICENSE.mcp.1.8.0(MIT License).txt → LICENSE_mcp_1_9_4_MIT_License.txt} +0 -0
  138. /cmdbox/licenses/{LICENSE.mdurl.0.1.2(MIT License).txt → LICENSE_mdurl_0_1_2_MIT_License.txt} +0 -0
  139. /cmdbox/licenses/{LICENSE.more-itertools.10.7.0(MIT License).txt → LICENSE_more-itertools_10_7_0_MIT_License.txt} +0 -0
  140. /cmdbox/licenses/{LICENSE.multidict.6.4.3(Apache Software License).txt → LICENSE_multidict_6_6_2_Apache_License_2_0.txt} +0 -0
  141. /cmdbox/licenses/{LICENSE.nh3.0.2.21(MIT).txt → LICENSE_nh3_0_2_21_MIT.txt} +0 -0
  142. /cmdbox/licenses/{LICENSE.openai.1.75.0(Apache Software License).txt → LICENSE_openai_1_93_0_Apache_Software_License.txt} +0 -0
  143. /cmdbox/licenses/{LICENSE.opentelemetry-api.1.33.0(Apache Software License).txt → LICENSE_opentelemetry-api_1_34_1_Apache_Software_License.txt} +0 -0
  144. /cmdbox/licenses/{LICENSE.opentelemetry-exporter-gcp-trace.1.9.0(Apache Software License).txt → LICENSE_opentelemetry-exporter-gcp-trace_1_9_0_Apache_Software_License.txt} +0 -0
  145. /cmdbox/licenses/{LICENSE.opentelemetry-resourcedetector-gcp.1.9.0a0(Apache Software License).txt → LICENSE_opentelemetry-resourcedetector-gcp_1_9_0a0_Apache_Software_License.txt} +0 -0
  146. /cmdbox/licenses/{LICENSE.opentelemetry-sdk.1.33.0(Apache Software License).txt → LICENSE_opentelemetry-sdk_1_34_1_Apache_Software_License.txt} +0 -0
  147. /cmdbox/licenses/{LICENSE.opentelemetry-semantic-conventions.0.54b0(Apache Software License).txt → LICENSE_opentelemetry-semantic-conventions_0_55b1_Apache_Software_License.txt} +0 -0
  148. /cmdbox/licenses/{LICENSE.packaging.25.0(Apache Software License; BSD License).txt → LICENSE_packaging_25_0_Apache_Software_License-BSD_License.txt} +0 -0
  149. /cmdbox/licenses/{LICENSE.pillow.11.2.1(UNKNOWN).txt → LICENSE_pillow_11_2_1_UNKNOWN.txt} +0 -0
  150. /cmdbox/licenses/{LICENSE.pip.24.0(MIT License).txt → LICENSE_pip_24_0_MIT_License.txt} +0 -0
  151. /cmdbox/licenses/{LICENSE.plyer.2.1.0(MIT License).txt → LICENSE_plyer_2_1_0_MIT_License.txt} +0 -0
  152. /cmdbox/licenses/{LICENSE.prettytable.3.16.0(UNKNOWN).txt → LICENSE_prettytable_3_16_0_UNKNOWN.txt} +0 -0
  153. /cmdbox/licenses/{LICENSE.prompt_toolkit.3.0.51(BSD License).txt → LICENSE_prompt_toolkit_3_0_51_BSD_License.txt} +0 -0
  154. /cmdbox/licenses/{LICENSE.protobuf.5.29.4(3-Clause BSD License).txt → LICENSE_protobuf_6_31_1_3-Clause_BSD_License.txt} +0 -0
  155. /cmdbox/licenses/{LICENSE.psycopg-binary.3.2.7(GNU Lesser General Public License v3 (LGPLv3)).txt → LICENSE_psycopg-binary_3_2_9_GNU_Lesser_General_Public_License_v3-LGPLv3.txt} +0 -0
  156. /cmdbox/licenses/{LICENSE.psycopg.3.2.7(GNU Lesser General Public License v3 (LGPLv3)).txt → LICENSE_psycopg_3_2_9_GNU_Lesser_General_Public_License_v3-LGPLv3.txt} +0 -0
  157. /cmdbox/licenses/{LICENSE.pyasn1.0.6.1(BSD License).txt → LICENSE_pyasn1_0_6_1_BSD_License.txt} +0 -0
  158. /cmdbox/licenses/{LICENSE.pyasn1_modules.0.4.2(BSD License).txt → LICENSE_pyasn1_modules_0_4_2_BSD_License.txt} +0 -0
  159. /cmdbox/licenses/{LICENSE.pycparser.2.22(BSD License).txt → LICENSE_pycparser_2_22_BSD_License.txt} +0 -0
  160. /cmdbox/licenses/{LICENSE.pycryptodome.3.22.0(BSD License; Public Domain).txt → LICENSE_pycryptodome_3_23_0_BSD_License-Public_Domain.txt} +0 -0
  161. /cmdbox/licenses/{LICENSE.pydantic-settings.2.9.1(MIT License).txt → LICENSE_pydantic-settings_2_10_1_MIT_License.txt} +0 -0
  162. /cmdbox/licenses/{LICENSE.pydantic.2.11.4(MIT License).txt → LICENSE_pydantic_2_11_7_MIT_License.txt} +0 -0
  163. /cmdbox/licenses/{LICENSE.pydantic_core.2.33.2(MIT License).txt → LICENSE_pydantic_core_2_33_2_MIT_License.txt} +0 -0
  164. /cmdbox/licenses/{LICENSE.pyparsing.3.2.3(MIT License).txt → LICENSE_pyparsing_3_2_3_MIT_License.txt} +0 -0
  165. /cmdbox/licenses/{LICENSE.pystray.0.19.5(GNU Lesser General Public License v3 (LGPLv3)).txt → LICENSE_pystray_0_19_5_GNU_Lesser_General_Public_License_v3-LGPLv3.txt} +0 -0
  166. /cmdbox/licenses/{LICENSE.python-dateutil.2.9.0.post0(Apache Software License; BSD License).txt → LICENSE_python-dateutil_2_9_0_post0_Apache_Software_License-BSD_License.txt} +0 -0
  167. /cmdbox/licenses/{LICENSE.python-dotenv.1.1.0(BSD License).txt → LICENSE_python-dotenv_1_1_1_BSD_License.txt} +0 -0
  168. /cmdbox/licenses/{LICENSE.python-multipart.0.0.20(Apache Software License).txt → LICENSE_python-multipart_0_0_20_Apache_Software_License.txt} +0 -0
  169. /cmdbox/licenses/{LICENSE.pywin32-ctypes.0.2.3(BSD-3-Clause).txt → LICENSE_pywin32-ctypes_0_2_3_BSD-3-Clause.txt} +0 -0
  170. /cmdbox/licenses/{LICENSE.questionary.2.1.0(MIT License).txt → LICENSE_questionary_2_1_0_MIT_License.txt} +0 -0
  171. /cmdbox/licenses/{LICENSE.readme_renderer.44.0(Apache Software License).txt → LICENSE_readme_renderer_44_0_Apache_Software_License.txt} +0 -0
  172. /cmdbox/licenses/{LICENSE.redis.6.0.0(MIT License).txt → LICENSE_redis_6_2_0_MIT_License.txt} +0 -0
  173. /cmdbox/licenses/{LICENSE.referencing.0.36.2(UNKNOWN).txt → LICENSE_referencing_0_36_2_UNKNOWN.txt} +0 -0
  174. /cmdbox/licenses/{LICENSE.regex.2024.11.6(Apache Software License).txt → LICENSE_regex_2024_11_6_Apache_Software_License.txt} +0 -0
  175. /cmdbox/licenses/{LICENSE.requests-toolbelt.1.0.0(Apache Software License).txt → LICENSE_requests-toolbelt_1_0_0_Apache_Software_License.txt} +0 -0
  176. /cmdbox/licenses/{LICENSE.requests.2.32.3(Apache Software License).txt → LICENSE_requests_2_32_4_Apache_Software_License.txt} +0 -0
  177. /cmdbox/licenses/{LICENSE.rfc3986.2.0.0(Apache Software License).txt → LICENSE_rfc3986_2_0_0_Apache_Software_License.txt} +0 -0
  178. /cmdbox/licenses/{LICENSE.rich.14.0.0(MIT License).txt → LICENSE_rich_14_0_0_MIT_License.txt} +0 -0
  179. /cmdbox/licenses/{LICENSE.roman-numerals-py.3.1.0(CC0 1.0 Universal (CC0 1.0) Public Domain Dedication; Zero-Clause BSD (0BSD)).txt → LICENSE_roman-numerals-py_3_1_0_CC0_1_0_Universal-CC0_1_0-Public_Domain_Dedication-Zero-Clause_BSD-0BSD.txt} +0 -0
  180. /cmdbox/licenses/{LICENSE.rpds-py.0.24.0(MIT).txt → LICENSE_rpds-py_0_25_1_MIT.txt} +0 -0
  181. /cmdbox/licenses/{LICENSE.rsa.4.9.1(Apache Software License).txt → LICENSE_rsa_4_9_1_Apache_Software_License.txt} +0 -0
  182. /cmdbox/licenses/{LICENSE.setuptools.65.5.0(MIT License).txt → LICENSE_setuptools_65_5_0_MIT_License.txt} +0 -0
  183. /cmdbox/licenses/{LICENSE.shapely.2.1.0(BSD License).txt → LICENSE_shapely_2_1_1_BSD_License.txt} +0 -0
  184. /cmdbox/licenses/{LICENSE.six.1.17.0(MIT License).txt → LICENSE_six_1_17_0_MIT_License.txt} +0 -0
  185. /cmdbox/licenses/{LICENSE.sniffio.1.3.1(Apache Software License; MIT License).txt → LICENSE_sniffio_1_3_1_Apache_Software_License-MIT_License.txt} +0 -0
  186. /cmdbox/licenses/{LICENSE.snowballstemmer.3.0.1(BSD License).txt → LICENSE_snowballstemmer_3_0_1_BSD_License.txt} +0 -0
  187. /cmdbox/licenses/{LICENSE.sphinx-intl.2.3.1(BSD License).txt → LICENSE_sphinx-intl_2_3_1_BSD_License.txt} +0 -0
  188. /cmdbox/licenses/{LICENSE.sphinx-rtd-theme.3.0.2(MIT License).txt → LICENSE_sphinx-rtd-theme_3_0_2_MIT_License.txt} +0 -0
  189. /cmdbox/licenses/{LICENSE.sphinx-sitemap.2.6.0(MIT License).txt → LICENSE_sphinx-sitemap_2_7_2_UNKNOWN.txt} +0 -0
  190. /cmdbox/licenses/{LICENSE.sphinx_fontawesome.0.0.6(GNU General Public License v2 (GPLv2)).txt → LICENSE_sphinx_fontawesome_0_0_6_GNU_General_Public_License_v2-GPLv2.txt} +0 -0
  191. /cmdbox/licenses/{LICENSE.sphinxcontrib-devhelp.2.0.0(BSD License).txt → LICENSE_sphinxcontrib-applehelp_2_0_0_BSD_License.txt} +0 -0
  192. /cmdbox/licenses/{LICENSE.sphinxcontrib-htmlhelp.2.1.0(BSD License).txt → LICENSE_sphinxcontrib-devhelp_2_0_0_BSD_License.txt} +0 -0
  193. /cmdbox/licenses/{LICENSE.sphinxcontrib-jquery.4.1(BSD License).txt → LICENSE_sphinxcontrib-htmlhelp_2_1_0_BSD_License.txt} +0 -0
  194. /cmdbox/licenses/{LICENSE.sphinxcontrib-qthelp.2.0.0(BSD License).txt → LICENSE_sphinxcontrib-jquery_4_1_BSD_License.txt} +0 -0
  195. /cmdbox/licenses/{LICENSE.sphinxcontrib-jsmath.1.0.1(BSD License).txt → LICENSE_sphinxcontrib-jsmath_1_0_1_BSD_License.txt} +0 -0
  196. /cmdbox/licenses/{LICENSE.sphinxcontrib-serializinghtml.2.0.0(BSD License).txt → LICENSE_sphinxcontrib-qthelp_2_0_0_BSD_License.txt} +0 -0
  197. /cmdbox/licenses/{LICENSE.tokenizers.0.21.1(Apache Software License).txt → LICENSE_sphinxcontrib-serializinghtml_2_0_0_BSD_License.txt} +0 -0
  198. /cmdbox/licenses/{LICENSE.sse-starlette.2.3.4(BSD License).txt → LICENSE_sse-starlette_2_3_6_BSD_License.txt} +0 -0
  199. /cmdbox/licenses/{LICENSE.starlette.0.46.2(BSD License).txt → LICENSE_starlette_0_46_2_BSD_License.txt} +0 -0
  200. /cmdbox/licenses/{LICENSE.tabulate.0.9.0(MIT License).txt → LICENSE_tabulate_0_9_0_MIT_License.txt} +0 -0
  201. /cmdbox/licenses/{LICENSE.tiktoken.0.9.0(MIT License).txt → LICENSE_tiktoken_0_9_0_MIT_License-Copyright-c-2022_OpenAI-Shantanu_Jain-Permission_is_hereby_granted-free_of_charge-to_any_pers.txt} +0 -0
  202. /cmdbox/licenses/{LICENSE.tomli.2.2.1(MIT License).txt → LICENSE_tomli_2_2_1_MIT_License.txt} +0 -0
  203. /cmdbox/licenses/{LICENSE.tqdm.4.67.1(MIT License; Mozilla Public License 2.0 (MPL 2.0)).txt → LICENSE_tqdm_4_67_1_MIT_License-Mozilla_Public_License_2_0-MPL_2_0.txt} +0 -0
  204. /cmdbox/licenses/{LICENSE.twine.6.1.0(Apache Software License).txt → LICENSE_twine_6_1_0_Apache_Software_License.txt} +0 -0
  205. /cmdbox/licenses/{LICENSE.typing_extensions.4.13.2(UNKNOWN).txt → LICENSE_typing_extensions_4_14_0_UNKNOWN.txt} +0 -0
  206. /cmdbox/licenses/{LICENSE.tzdata.2025.2(Apache Software License).txt → LICENSE_tzdata_2025_2_Apache_Software_License.txt} +0 -0
  207. /cmdbox/licenses/{LICENSE.tzlocal.5.3.1(MIT License).txt → LICENSE_tzlocal_5_3_1_MIT_License.txt} +0 -0
  208. /cmdbox/licenses/{LICENSE.uritemplate.4.1.1(Apache Software License; BSD License).txt → LICENSE_uritemplate_4_2_0_BSD_3-Clause_OR_Apache-2_0.txt} +0 -0
  209. /cmdbox/licenses/{LICENSE.urllib3.2.4.0(UNKNOWN).txt → LICENSE_urllib3_2_5_0_UNKNOWN.txt} +0 -0
  210. /cmdbox/licenses/{LICENSE.uvicorn.0.34.2(BSD License).txt → LICENSE_uvicorn_0_35_0_BSD_License.txt} +0 -0
  211. /cmdbox/licenses/{LICENSE.watchfiles.1.0.5(MIT License).txt → LICENSE_watchfiles_1_1_0_MIT_License.txt} +0 -0
  212. /cmdbox/licenses/{LICENSE.wcwidth.0.2.13(MIT License).txt → LICENSE_wcwidth_0_2_13_MIT_License.txt} +0 -0
  213. /cmdbox/licenses/{LICENSE.websockets.15.0.1(BSD License).txt → LICENSE_websockets_15_0_1_BSD_License.txt} +0 -0
  214. /cmdbox/licenses/{LICENSE.wheel.0.45.1(MIT License).txt → LICENSE_wheel_0_45_1_MIT_License.txt} +0 -0
  215. /cmdbox/licenses/{LICENSE.zope.event.5.0(Zope Public License).txt → LICENSE_zope_event_5_1_Zope_Public_License.txt} +0 -0
  216. /cmdbox/licenses/{LICENSE.zope.interface.7.2(Zope Public License).txt → LICENSE_zope_interface_7_2_Zope_Public_License.txt} +0 -0
  217. {cmdbox-0.6.0.4.dist-info → cmdbox-0.6.1.dist-info}/LICENSE +0 -0
  218. {cmdbox-0.6.0.4.dist-info → cmdbox-0.6.1.dist-info}/WHEEL +0 -0
  219. {cmdbox-0.6.0.4.dist-info → cmdbox-0.6.1.dist-info}/entry_points.txt +0 -0
  220. {cmdbox-0.6.0.4.dist-info → cmdbox-0.6.1.dist-info}/top_level.txt +0 -0
@@ -1,16 +1,5 @@
1
- from cmdbox.app import common, feature
2
- from cmdbox.app.auth import signin
3
- from cmdbox.app.features.cli import cmdbox_cmd_list
1
+ from cmdbox.app import common, feature, mcp
4
2
  from cmdbox.app.options import Options
5
- from pathlib import Path
6
- from typing import Any, Callable, Dict, Tuple, List
7
- import argparse
8
- import asyncio
9
- import locale
10
- import logging
11
- import json
12
- import re
13
- import time
14
3
 
15
4
 
16
5
  class AgentBase(feature.ResultEdgeFeature):
@@ -96,326 +85,3 @@ class AgentBase(feature.ResultEdgeFeature):
96
85
  discription_ja="llmのモデルを使用するときのtemperatureを指定します。",
97
86
  discription_en="Specifies the temperature when using llm model."),
98
87
  ])
99
-
100
- def create_mcpserver(self, args:argparse.Namespace) -> Any:
101
- """
102
- mcpserverを作成します
103
-
104
- Args:
105
- args (argparse.Namespace): 引数
106
-
107
- Returns:
108
- Any: FastMCP
109
- """
110
- from fastmcp import FastMCP
111
- mcp = FastMCP(name=self.ver.__appid__)
112
- return mcp
113
-
114
- def create_session_service(self, args:argparse.Namespace) -> Any:
115
- """
116
- セッションサービスを作成します
117
-
118
- Args:
119
- args (argparse.Namespace): 引数
120
-
121
- Returns:
122
- BaseSessionService: セッションサービス
123
- """
124
- from google.adk.events import Event
125
- from google.adk.sessions import DatabaseSessionService, InMemorySessionService, session
126
- from typing_extensions import override
127
- if hasattr(args, 'agent_session_dburl') and args.agent_session_dburl is not None:
128
- class _DatabaseSessionService(DatabaseSessionService):
129
- @override
130
- async def append_event(self, session: session.Session, event: Event) -> Event:
131
- # 永続化されるセッションには <important> タグを含めない
132
- bk_parts = event.content.parts.copy()
133
- for part in event.content.parts:
134
- if not part.text: continue
135
- part.text = re.sub(r"<important>.*</important>", "", part.text)
136
- for part in bk_parts:
137
- if not part.text: continue
138
- part.text = part.text.replace("<important>", "").replace("</important>", "")
139
- ret = await super().append_event(session, event)
140
- ret.content.parts = bk_parts
141
- return ret
142
- dss = _DatabaseSessionService(db_url=args.agent_session_dburl)
143
- #dss.db_engine.echo = True
144
- return dss
145
- else:
146
- return InMemorySessionService()
147
-
148
- def create_agent(self, logger:logging.Logger, args:argparse.Namespace, tools:List[Callable]) -> Any:
149
- """
150
- エージェントを作成します
151
-
152
- Args:
153
- logger (logging.Logger): ロガー
154
- args (argparse.Namespace): 引数
155
- tools (List[Callable]): 関数
156
-
157
- Returns:
158
- Agent: エージェント
159
- """
160
- if logger.level == logging.DEBUG:
161
- logger.debug(f"create_agent processing..")
162
- language, _ = locale.getlocale()
163
- is_japan = language.find('Japan') >= 0 or language.find('ja_JP') >= 0
164
- description = f"{self.ver.__appid__}に登録されているコマンド提供"
165
- instruction = f"あなたはコマンドの意味を熟知しているエキスパートです。" + \
166
- f"ユーザーがコマンドを実行したいとき、あなたは以下の手順に従ってコマンドを確実に実行してください。\n" + \
167
- f"1. ユーザーのクエリからが実行したいコマンドを特定します。\n" + \
168
- f"2. コマンド実行に必要なパラメータのなかで、ユーザーのクエリから取得できないものは、コマンド定義にあるデフォルト値を指定して実行してください。\n" + \
169
- f"3. もしエラーが発生した場合は、ユーザーにコマンド名とパラメータとエラー内容を提示してください。\n"
170
-
171
- description = description if is_japan else \
172
- f"Command offer registered in {self.ver.__appid__}."
173
- instruction = instruction if is_japan else \
174
- f"You are the expert who knows what the commands mean." + \
175
- f"When a user wants to execute a command, you follow these steps to ensure that the command is executed.\n" + \
176
- f"1. Identify the command you want to execute from the user's query.\n" + \
177
- f"2. Any parameters required to execute the command that cannot be obtained from the user's query should be executed with the default values provided in the command definition.\n" + \
178
- f"3. If an error occurs, provide the user with the command name, parameters, and error description.\n"
179
-
180
- description = args.agent_description if args.agent_description else description
181
- instruction = args.agent_instruction if args.agent_instruction else instruction
182
- if logger.level == logging.DEBUG:
183
- logger.debug(f"google-adk loading..")
184
- from google.adk.agents import Agent
185
- if logger.level == logging.DEBUG:
186
- logger.debug(f"litellm loading..")
187
- from google.adk.models.lite_llm import LiteLlm
188
- # loggerの初期化
189
- common.reset_logger("LiteLLM Proxy")
190
- common.reset_logger("LiteLLM Router")
191
- common.reset_logger("LiteLLM")
192
- if args.llmprov == 'openai':
193
- if args.llmmodel is None: raise ValueError("llmmodel is required.")
194
- if args.llmapikey is None: raise ValueError("llmapikey is required.")
195
- agent = Agent(
196
- name=args.agent_name,
197
- model=LiteLlm(
198
- model=args.llmmodel,
199
- api_key=args.llmapikey,
200
- endpoint=args.llmendpoint,
201
- ),
202
- description=description,
203
- instruction=instruction,
204
- tools=tools,
205
- )
206
- elif args.llmprov == 'azureopenai':
207
- if args.llmmodel is None: raise ValueError("llmmodel is required.")
208
- if args.llmendpoint is None: raise ValueError("llmendpoint is required.")
209
- if args.llmapikey is None: raise ValueError("llmapikey is required.")
210
- if args.llmapiversion is None: raise ValueError("llmapiversion is required.")
211
- agent = Agent(
212
- name=args.agent_name,
213
- model=LiteLlm(
214
- model=args.llmmodel,
215
- api_key=args.llmapikey,
216
- endpoint=args.llmendpoint,
217
- api_version=args.llmapiversion,
218
- ),
219
- description=description,
220
- instruction=instruction,
221
- tools=tools,
222
- )
223
- elif args.llmprov == 'vertexai':
224
- if args.llmmodel is None: raise ValueError("llmmodel is required.")
225
- if args.llmlocation is None: raise ValueError("llmlocation is required.")
226
- if args.llmsvaccountfile is not None:
227
- with open(args.llmsvaccountfile, "r", encoding="utf-8") as f:
228
- vertex_credentials = json.load(f)
229
- elif args.llmprojectid is None: raise ValueError("llmprojectid is required.")
230
- agent = Agent(
231
- name=args.agent_name,
232
- model=LiteLlm(
233
- model=args.llmmodel,
234
- #vertex_project=args.llmprojectid,
235
- vertex_credentials=vertex_credentials,
236
- vertex_location=args.llmlocation,
237
- #seed=args.llmseed,
238
- #temperature=args.llmtemperature,
239
- ),
240
- description=description,
241
- instruction=instruction,
242
- tools=tools,
243
- )
244
- elif args.llmprov == 'ollama':
245
- if args.llmmodel is None: raise ValueError("llmmodel is required.")
246
- if args.llmendpoint is None: raise ValueError("llmendpoint is required.")
247
- agent = Agent(
248
- name=args.agent_name,
249
- model=LiteLlm(
250
- model=f"ollama/{args.llmmodel}",
251
- api_base=args.llmendpoint,
252
- temperature=args.llmtemperature,
253
- stream=True
254
- ),
255
- description=description,
256
- instruction=instruction,
257
- tools=tools,
258
- )
259
- else:
260
- raise ValueError("llmprov is required.")
261
- if logger.level == logging.DEBUG:
262
- logger.debug(f"create_agent complate.")
263
- return agent
264
-
265
- def create_runner(self, logger:logging.Logger, args:argparse.Namespace, session_service, agent) -> Any:
266
- """
267
- ランナーを作成します
268
-
269
- Args:
270
- logger (logging.Logger): ロガー
271
- args (argparse.Namespace): 引数
272
- session_service (BaseSessionService): セッションサービス
273
- agent (Agent): エージェント
274
-
275
- Returns:
276
- Runner: ランナー
277
- """
278
- from google.adk.runners import Runner
279
- return Runner(
280
- app_name=self.ver.__appid__,
281
- agent=agent,
282
- session_service=session_service,
283
- )
284
-
285
- def init_agent_runner(self, logger:logging.Logger, args:argparse.Namespace) -> Tuple[Any, Any]:
286
- """
287
- エージェントの初期化を行います
288
-
289
- Args:
290
- logger (logging.Logger): ロガー
291
- args (argparse.Namespace): 引数
292
-
293
- Returns:
294
- Tuple[Any, Any]: ランナーとFastMCP
295
- """
296
- if logger.level == logging.DEBUG:
297
- logger.debug(f"init_agent_runner processing..")
298
- # loggerの初期化
299
- common.reset_logger("httpx")
300
- common.reset_logger("google_adk.google.adk.sessions.database_session_service")
301
- common.reset_logger("mcp.server.streamable_http_manager")
302
- # モジュールインポート
303
- from fastmcp import FastMCP
304
- from google.adk.sessions import BaseSessionService
305
- mcp:FastMCP = self.create_mcpserver(args)
306
- session_service:BaseSessionService = self.create_session_service(args)
307
- options = Options.getInstance()
308
- tools:Callable[[logging.Logger, argparse.Namespace, float, Dict], Tuple[int, Dict[str, Any], Any]] = []
309
-
310
- def _ds(d:str) -> str:
311
- return f'"{d}"' if d is not None else 'None'
312
- def _t2s(o:Dict[str, Any], req=True) -> str:
313
- t, m, d, r = o["type"], o["multi"], o["default"], o["required"]
314
- if t == Options.T_BOOL: return ("List[bool]=[]" if m else f"bool={d}") if req else ("List[bool]" if m else f"bool")
315
- if t == Options.T_DATE: return ("List[str]=[]" if m else f"str={_ds(d)}") if req else ("List[str]" if m else f"str")
316
- if t == Options.T_DATETIME: return ("List[str]=[]" if m else f"str={_ds(d)}") if req else ("List[str]" if m else f"str")
317
- if t == Options.T_DICT: return ("List[dict]=[]" if m else f"dict={d}") if req else ("List[dict]" if m else f"dict")
318
- if t == Options.T_DIR or t == Options.T_FILE:
319
- if d is not None: d = str(d).replace('\\', '/')
320
- return ("List[str]=[]" if m else f"str={_ds(d)}") if req else ("List[str]" if m else f"str")
321
- if t == Options.T_FLOAT: return ("List[float]=[]" if m else f"float={d}") if req else ("List[float]" if m else f"float")
322
- if t == Options.T_INT: return ("List[int]=[]" if m else f"int={d}") if req else ("List[int]" if m else f"int")
323
- if t == Options.T_STR: return ("List[str]=[]" if m else f"str={_ds(d)}") if req else ("List[str]" if m else f"str")
324
- if t == Options.T_TEXT: return ("List[str]=[]" if m else f"str={_ds(d)}") if req else ("List[str]" if m else f"str")
325
- raise ValueError(f"Unknown type: {t} for option {o['opt']}")
326
- def _arg(o:Dict[str, Any], is_japan) -> str:
327
- t, d = o["type"], o["default"]
328
- s = f' {o["opt"]}:'
329
- if t == Options.T_DIR or t == Options.T_FILE:
330
- d = str(d).replace("\\", "/")
331
- s += f'Optional[{_t2s(o, False)}]={d}:'
332
- s += f'{o["discription_ja"] if is_japan else o["discription_en"]}'
333
- return s
334
- def _coercion(a:argparse.Namespace, key:str, dval) -> str:
335
- dval = f'opt["{key}"] if "{key}" in opt else ' + f'"{dval}"' if isinstance(dval, str) else dval
336
- aval = args.__dict__[key] if hasattr(args, key) and args.__dict__[key] else None
337
- aval = f'"{aval}"' if isinstance(aval, str) else aval
338
- ret = f'opt["{key}"] = {aval}' if aval is not None else f'opt["{key}"] = {dval}'
339
- return ret
340
- language, _ = locale.getlocale()
341
- is_japan = language.find('Japan') >= 0 or language.find('ja_JP') >= 0
342
- for mode in options.get_mode_keys():
343
- for cmd in options.get_cmd_keys(mode):
344
- if not options.get_cmd_attr(mode, cmd, 'use_agent'):
345
- continue
346
- discription = options.get_cmd_attr(mode, cmd, 'discription_ja' if is_japan else 'discription_en')
347
- choices = options.get_cmd_choices(mode, cmd, False)
348
- if len([opt for opt in choices if 'opt' in opt and opt['opt'] == 'signin_file']) <= 0:
349
- choices.append(dict(opt="signin_file", type=Options.T_FILE, default=f'.{self.ver.__appid__}/user_list.yml', required=True, multi=False, hide=True, choice=None,
350
- discription_ja="サインイン可能なユーザーとパスワードを記載したファイルを指定します。省略した時は認証を要求しません。",
351
- discription_en="Specify a file containing users and passwords with which they can signin. If omitted, no authentication is required."),)
352
- fn = f"{mode}_{cmd}"
353
- func_txt = f'def {fn}(' + ", ".join([f'{o["opt"]}:{_t2s(o, False)}' for o in choices]) + '):\n'
354
- func_txt += f' """\n'
355
- func_txt += f' {discription}\n'
356
- func_txt += f' Args:\n'
357
- func_txt += "\n".join([_arg(o, is_japan) for o in choices])
358
- func_txt += f'\n'
359
- func_txt += f' Returns:\n'
360
- func_txt += f' Dict[str, Any]:{"処理結果" if is_japan else "Processing Result"}\n'
361
- func_txt += f' """\n'
362
- func_txt += f' scope = signin.get_request_scope()\n'
363
- func_txt += f' logger = common.default_logger()\n'
364
- func_txt += f' opt = dict()\n'
365
- func_txt += f' opt["mode"] = "{mode}"\n'
366
- func_txt += f' opt["cmd"] = "{cmd}"\n'
367
- func_txt += f' opt["data"] = opt["data"] if hasattr(opt, "data") else common.HOME_DIR / ".{self.ver.__appid__}"\n'
368
- func_txt += f' opt["format"] = False\n'
369
- func_txt += f' opt["output_json"] = None\n'
370
- func_txt += f' opt["output_json_append"] = False\n'
371
- func_txt += f' opt["debug"] = logger.level == logging.DEBUG\n'
372
- func_txt += '\n'.join([f' opt["{o["opt"]}"] = {o["opt"]}' for o in choices])+'\n'
373
- func_txt += f' {_coercion(args, "host", self.default_host)}\n'
374
- func_txt += f' {_coercion(args, "port", self.default_port)}\n'
375
- func_txt += f' {_coercion(args, "password", self.default_pass)}\n'
376
- func_txt += f' {_coercion(args, "svname", self.default_svname)}\n'
377
- func_txt += f' {_coercion(args, "retry_count", 3)}\n'
378
- func_txt += f' {_coercion(args, "retry_interval", 3)}\n'
379
- func_txt += f' {_coercion(args, "timeout", 15)}\n'
380
- func_txt += f' {_coercion(args, "output_json", None)}\n'
381
- func_txt += f' {_coercion(args, "output_json_append", False)}\n'
382
- func_txt += f' {_coercion(args, "stdout_log", False)}\n'
383
- func_txt += f' {_coercion(args, "capture_stdout", False)}\n'
384
- func_txt += f' {_coercion(args, "capture_maxsize", 1024*1024)}\n'
385
- func_txt += f' {_coercion(args, "tag", None)}\n'
386
- func_txt += f' {_coercion(args, "clmsg_id", None)}\n'
387
- func_txt += f' opt["signin_file"] = signin_file if signin_file else ".{self.ver.__appid__}/user_list.yml"\n'
388
- func_txt += f' args = argparse.Namespace(**opt)\n'
389
- func_txt += f' signin_data = signin.Signin.load_signin_file(args.signin_file)\n'
390
- func_txt += f' req = scope["req"] if scope["req"] is not None else scope["websocket"]\n'
391
- func_txt += f' sign = signin.Signin._check_signin(req, scope["res"], signin_data, logger)\n'
392
- func_txt += f' if sign is not None:\n'
393
- func_txt += f' logger.warning("Unable to execute command because authentication information cannot be obtained")\n'
394
- func_txt += f' return dict(warn="Unable to execute command because authentication information cannot be obtained")\n'
395
- func_txt += f' groups = req.session["signin"]["groups"]\n'
396
- func_txt += f' logger.info("Call agent tool `{mode}_{cmd}`:user="+str(req.session["signin"]["name"])+" groups="+str(groups)+" args="+str(args))\n'
397
- func_txt += f' if not signin.Signin._check_cmd(signin_data, groups, "{mode}", "{cmd}", logger):\n'
398
- func_txt += f' logger.warning("You do not have permission to execute this command.")\n'
399
- func_txt += f' return dict(warn="You do not have permission to execute this command.")\n'
400
- func_txt += f' feat = Options.getInstance().get_cmd_attr("{mode}", "{cmd}", "feature")\n'
401
- func_txt += f' try:\n'
402
- func_txt += f' st, ret, _ = feat.apprun(logger, args, time.perf_counter(), [])\n'
403
- func_txt += f' return ret\n'
404
- func_txt += f' except Exception as e:\n'
405
- func_txt += f' logger.error("Error occurs when tool is executed:", exc_info=True)\n'
406
- func_txt += f' raise e\n'
407
- func_txt += f'tools.append({fn})\n'
408
- if logger.level == logging.DEBUG:
409
- logger.debug(f"generating agent tool: {fn}")
410
-
411
- exec(func_txt,
412
- dict(time=time,List=List, argparse=argparse, common=common, Options=Options, logging=logging, signin=signin,),
413
- dict(tools=tools, mcp=mcp))
414
- exec(f"@mcp.tool\n{func_txt}",
415
- dict(time=time,List=List, argparse=argparse, common=common, Options=Options, logging=logging, signin=signin,),
416
- dict(tools=[], mcp=mcp))
417
- root_agent = self.create_agent(logger, args, tools)
418
- runner = self.create_runner(logger, args, session_service, root_agent)
419
- if logger.level == logging.DEBUG:
420
- logger.debug(f"init_agent_runner complate.")
421
- return runner, mcp
@@ -210,8 +210,6 @@ class AuditSearch(audit_base.AuditBase):
210
210
  ret = buf.getvalue()
211
211
  ret = ret.replace('\r\n', '\n') if ret is not None else ''
212
212
 
213
- common.print_format(ret, getattr(args, 'format', False), tm, None, False, pf=pf)
214
-
215
213
  return 0, ret, cl
216
214
 
217
215
  def is_cluster_redirect(self):
@@ -41,6 +41,9 @@ class AuditWrite(audit_base.AuditBase):
41
41
  opt['discription_ja'] = "監査を記録します。"
42
42
  opt['discription_en'] = "Record the audit."
43
43
  opt['choice'] += [
44
+ dict(opt="client_only", type=Options.T_BOOL, default=False, required=False, multi=False, hide=True, choice=[True, False],
45
+ discription_ja="サーバーへの接続を行わないようにします。",
46
+ discription_en="Do not make connections to the server."),
44
47
  dict(opt="audit_type", type=Options.T_STR, default=None, required=True, multi=False, hide=False, choice=Options.AUDITS,
45
48
  discription_ja="監査の種類を指定します。",
46
49
  discription_en="Specifies the audit type."),
@@ -105,6 +108,12 @@ class AuditWrite(audit_base.AuditBase):
105
108
  args.clmsg_id = str(uuid.uuid4())
106
109
  if args.clmsg_date is None:
107
110
  args.clmsg_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + common.get_tzoffset_str()
111
+ if hasattr(args, 'client_only') and args.client_only==True:
112
+ # クライアントのみの場合は、サーバーへの接続を行わない
113
+ logger.warning(f"client_only is True. Not connecting to server. Skip writing the audit log.")
114
+ ret = dict(success={k:v for k, v in vars(args).items() if v})
115
+ common.print_format(ret, False, tm, args.output_json, args.output_json_append, pf=pf)
116
+ return 0, ret, None
108
117
 
109
118
  audit_type_b64 = convert.str2b64str(args.audit_type)
110
119
  clmsg_id_b64 = convert.str2b64str(args.clmsg_id)
@@ -90,7 +90,7 @@ class CmdList(feature.OneshotResultEdgeFeature):
90
90
  if kwd is None or kwd == '':
91
91
  kwd = '*'
92
92
  if not hasattr(self, 'signin_file_data') or self.signin_file_data is None:
93
- self.signin_file_data = signin.Signin.load_signin_file(args.signin_file, None)
93
+ self.signin_file_data = signin.Signin.load_signin_file(args.signin_file, None, self=self)
94
94
  paths = glob.glob(str(Path(args.data) / ".cmds" / f"cmd-{kwd}.json"))
95
95
  ret = [common.loadopt(path, True) for path in paths]
96
96
  ret = sorted(ret, key=lambda cmd: cmd["title"])
@@ -91,7 +91,7 @@ class CmdLoad(feature.OneshotResultEdgeFeature):
91
91
  common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
92
92
  return 1, msg, None
93
93
  if not hasattr(self, 'signin_file_data') or self.signin_file_data is None:
94
- self.signin_file_data = signin.Signin.load_signin_file(args.signin_file, None)
94
+ self.signin_file_data = signin.Signin.load_signin_file(args.signin_file, None, self=self)
95
95
  opt_path = Path(args.data) / ".cmds" / f"cmd-{args.title}.json"
96
96
  opt = common.loadopt(opt_path, True)
97
97
  ret = dict(success=opt)
@@ -0,0 +1,90 @@
1
+ from cmdbox.app import common, feature
2
+ from cmdbox.app.features.cli import cmdbox_web_start
3
+ from cmdbox.app.options import Options
4
+ from typing import Dict, Any, Tuple, List, Union
5
+ import argparse
6
+ import logging
7
+
8
+
9
+ class McpStart(feature.UnsupportEdgeFeature):
10
+ def get_mode(self) -> Union[str, List[str]]:
11
+ """
12
+ この機能のモードを返します
13
+
14
+ Returns:
15
+ Union[str, List[str]]: モード
16
+ """
17
+ return 'mcp'
18
+
19
+ def get_cmd(self) -> str:
20
+ """
21
+ この機能のコマンドを返します
22
+
23
+ Returns:
24
+ str: コマンド
25
+ """
26
+ return 'proxy'
27
+
28
+ def get_option(self):
29
+ """
30
+ この機能のオプションを返します
31
+
32
+ Returns:
33
+ Dict[str, Any]: オプション
34
+ """
35
+ return dict(
36
+ use_redis=self.USE_REDIS_FALSE, nouse_webmode=False, use_agent=False,
37
+ discription_ja="標準入力を受け付け、リモートMCPサーバーにリクエストを行うProxyサーバーを起動します。",
38
+ discription_en="-",
39
+ choice=[
40
+ dict(opt="mcpserver_name", type=Options.T_STR, default='mcpserver', required=True, multi=False, hide=False, choice=None,
41
+ discription_ja="リモートMCPサーバーの名前を指定します。省略した場合は`mcpserver`となります。",
42
+ discription_en="Specify the name of the MCP server. If omitted, it will be `mcpserver`.",),
43
+ dict(opt="mcpserver_url", type=Options.T_STR, default='http://localhost:8081/mcpsv/mcp', required=True, multi=False, hide=False, choice=None,
44
+ discription_ja="リモートMCPサーバーのURLを指定します。省略した場合は`http://localhost:8081/mcpsv/mcp`となります。",
45
+ discription_en="Specifies the URL of the remote MCP server. If omitted, it will be `http://localhost:8081/mcpsv/mcp`.",),
46
+ dict(opt="mcpserver_transport", type=Options.T_STR, default='streamable-http', required=True, multi=False, hide=False, choice=['', 'streamable-http', 'sse', 'http'],
47
+ discription_ja="リモートMCPサーバーのトランスポートを指定します。省略した場合は`streamable-http`となります。",
48
+ discription_en="Specifies the transport of the remote MCP server. If omitted, it is `streamable-http`.",),
49
+ dict(opt="mcpserver_transport", type=Options.T_STR, default='streamable-http', required=True, multi=False, hide=False, choice=['', 'streamable-http', 'sse', 'http'],
50
+ discription_ja="リモートMCPサーバーのトランスポートを指定します。省略した場合は`streamable-http`となります。",
51
+ discription_en="Specifies the transport of the remote MCP server. If omitted, it is `streamable-http`.",),
52
+ ])
53
+
54
+ def apprun(self, logger:logging.Logger, args:argparse.Namespace, tm:float, pf:List[Dict[str, float]]=[]) -> Tuple[int, Dict[str, Any], Any]:
55
+ """
56
+ この機能の実行を行います
57
+
58
+ Args:
59
+ logger (logging.Logger): ロガー
60
+ args (argparse.Namespace): 引数
61
+ tm (float): 実行開始時間
62
+ pf (List[Dict[str, float]]): 呼出元のパフォーマンス情報
63
+
64
+ Returns:
65
+ Tuple[int, Dict[str, Any], Any]: 終了コード, 結果, オブジェクト
66
+ """
67
+ if not hasattr(args, 'mcpserver_name'):
68
+ args.mcpserver_name = 'mcpserver'
69
+ if not hasattr(args, 'mcpserver_url'):
70
+ args.mcpserver_url = 'http://localhost:8081/mcpsv/mcp'
71
+ if not hasattr(args, 'mcpserver_transport'):
72
+ args.mcpserver_transport = 'streamable-http'
73
+
74
+ from fastmcp import FastMCP
75
+ config = dict(
76
+ mcpServers=dict(
77
+ default=dict(
78
+ url=args.mcpserver_url,
79
+ transport=args.mcpserver_transport,
80
+ )
81
+ )
82
+ )
83
+ try:
84
+ common.reset_logger('FastMCP.fastmcp.server.server')
85
+ proxy = FastMCP.as_proxy(config, name="Config-Based Proxy")
86
+ proxy.run()
87
+ except Exception as e:
88
+ logger.error(f"Failed to start MCP proxy: {e}", exc_info=True)
89
+ return self.RESP_ERROR, dict(warn=f"Failed to start MCP proxy: {e}"), None
90
+ return self.RESP_SCCESS, dict(info="MCP proxy successfully."), None
@@ -51,6 +51,12 @@ class WebGencert(feature.UnsupportEdgeFeature):
51
51
  dict(opt="output_cert_format", type=Options.T_STR, default="PEM", required=False, multi=False, hide=False, choice=["DER", "PEM"],
52
52
  discription_ja="出力する自己署名証明書のファイルフォーマットを指定します。",
53
53
  discription_en="Specifies the file format of the self-signed certificate to be output."),
54
+ dict(opt="output_pkey", type=Options.T_FILE, default=None, required=False, multi=False, hide=False, choice=None,
55
+ discription_ja="出力する自己署名証明書の公開鍵のファイルを指定します。省略した場合は `webhostオプションに指定したホスト名` .pkey に出力されます。",
56
+ discription_en="Specifies the public key file of the self-signed certificate to output. If omitted, the output will be in the `hostname specified in the `webhost option` .pkey."),
57
+ dict(opt="output_pkey_format", type=Options.T_STR, default="PEM", required=False, multi=False, hide=False, choice=["DER", "PEM"],
58
+ discription_ja="出力する自己署名証明書の公開鍵のファイルフォーマットを指定します。",
59
+ discription_en="Specifies the file format of the public key of the self-signed certificate to be output."),
54
60
  dict(opt="output_key", type=Options.T_FILE, default=None, required=False, multi=False, hide=False, choice=None,
55
61
  discription_ja="出力する自己署名証明書の秘密鍵ファイルを指定します。省略した場合は `webhostオプションに指定したホスト名` .key に出力されます。",
56
62
  discription_en="Specifies the private key file of the self-signed certificate to be output.If omitted, the hostname specified in the `webhost option` .key will be output."),
@@ -91,22 +97,32 @@ class WebGencert(feature.UnsupportEdgeFeature):
91
97
  return 1, msg, None
92
98
  if args.output_cert is None:
93
99
  args.output_cert = f"{args.webhost}.crt"
100
+ if args.output_pkey is None:
101
+ args.output_pkey = f"{args.webhost}.pkey"
94
102
  if args.output_key is None:
95
103
  args.output_key = f"{args.webhost}.key"
96
104
  output_cert = Path(args.output_cert)
105
+ output_pkey = Path(args.output_pkey)
97
106
  output_key = Path(args.output_key)
98
107
  if not args.overwrite and output_cert.exists():
99
108
  msg = dict(warn=f"File already exists. {output_cert}")
100
109
  common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
101
110
  return 1, msg, None
111
+ if not args.overwrite and output_pkey.exists():
112
+ msg = dict(warn=f"File already exists. {output_pkey}")
113
+ common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
114
+ return 1, msg, None
102
115
  if not args.overwrite and output_key.exists():
103
116
  msg = dict(warn=f"File already exists. {output_key}")
104
117
  common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
105
118
  return 1, msg, None
106
119
 
107
120
  try:
108
- self.gen_cert(logger, args.webhost, output_cert, output_key)
109
- ret = dict(success=f"Generate certificate. {output_cert}, {output_key}")
121
+ self.gen_cert(logger, args.webhost,
122
+ output_cert, args.output_cert_format,
123
+ output_pkey, args.output_pkey_format,
124
+ output_key, args.output_key_format)
125
+ ret = dict(success=f"Generate certificate. {output_cert}, {output_pkey}, {output_key}")
110
126
  except Exception as e:
111
127
  msg = dict(error=f"Failed to generate certificate. {e}")
112
128
  common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
@@ -115,6 +131,7 @@ class WebGencert(feature.UnsupportEdgeFeature):
115
131
 
116
132
  def gen_cert(self, logger:logging.Logger, webhost:str,
117
133
  output_cert:Path, output_cert_format:str,
134
+ output_pkey:Path, output_pkey_format:str,
118
135
  output_key:Path, output_key_format:str) -> None:
119
136
  # 秘密鍵の作成
120
137
  private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
@@ -151,6 +168,12 @@ class WebGencert(feature.UnsupportEdgeFeature):
151
168
  critical=False,
152
169
  ).sign(private_key, hashes.SHA256())
153
170
 
171
+ # 自己署名証明書の公開鍵の保存
172
+ with open(output_pkey, "wb") as f:
173
+ f.write(self_cert.public_key().public_bytes(serialization.Encoding.DER if output_pkey_format == "DER" else serialization.Encoding.PEM,
174
+ format=serialization.PublicFormat.SubjectPublicKeyInfo))
175
+ logger.info(f"Save self-signed public key. {output_pkey}")
176
+
154
177
  # 自己署名証明書の保存
155
178
  with open(output_cert, "wb") as f:
156
179
  f.write(self_cert.public_bytes(serialization.Encoding.DER if output_cert_format == "DER" else serialization.Encoding.PEM))
@@ -204,13 +204,16 @@ class WebStart(feature.UnsupportEdgeFeature, agent_base.AgentBase):
204
204
  """
205
205
  logger.info(f"Agent={args.agent}")
206
206
  if args.agent=='use':
207
+ if not hasattr(self, 'mcp'):
208
+ from cmdbox.app import mcp
209
+ self.mcp = mcp.Mcp(logger, args.data, w.signin, self.appcls, self.ver)
207
210
  if args.agent_session_store == 'sqlite':
208
211
  args.agent_session_dburl = "sqlite://" + pathname2url(str(w.agent_path / 'session.db'))
209
212
  elif args.agent_session_store == 'postgresql':
210
213
  args.agent_session_dburl = f"postgresql+psycopg://{args.agent_pg_user}:{args.agent_pg_password}@{args.agent_pg_host}:{args.agent_pg_port}/{args.agent_pg_dbname}"
211
214
  else:
212
215
  args.agent_session_dburl = None
213
- return self.init_agent_runner(logger, args)
216
+ return self.mcp.init_agent_runner(logger, args)
214
217
  return None, None
215
218
 
216
219
  def start(self, w:web.Web, agent_runner, mcp, logger:logging.Logger, args:argparse.Namespace) -> None:
@@ -16,7 +16,7 @@ class Signin(feature.WebFeature):
16
16
  web (Web): Webオブジェクト
17
17
  app (FastAPI): FastAPIオブジェクト
18
18
  """
19
- web.signin.signin_file_data = web.signin.load_signin_file(web.signin_file, web.signin.get_data())
19
+ web.signin.signin_file_data = web.signin.load_signin_file(web.signin_file, web.signin.get_data(), self=self)
20
20
  if web.signin_html is not None:
21
21
  if not web.signin_html.is_file():
22
22
  raise HTTPException(status_code=500, detail=f'signin_html is not found. ({web.signin_html})')