agentengine-sdk-python 0.6.2__py3-none-any.whl → 0.6.9__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 (490) hide show
  1. agentengine_sdk_python-0.6.9.dist-info/METADATA +179 -0
  2. agentengine_sdk_python-0.6.9.dist-info/RECORD +487 -0
  3. {agentengine_sdk_python-0.6.2.dist-info → agentengine_sdk_python-0.6.9.dist-info}/WHEEL +1 -1
  4. agentengine_sdk_python-0.6.9.dist-info/entry_points.txt +3 -0
  5. agentengine_sdk_python-0.6.9.dist-info/licenses/LICENSE +175 -0
  6. agentengine_sdk_python-0.6.9.dist-info/top_level.txt +2 -0
  7. ksadk/__init__.py +13 -0
  8. ksadk/__main__.py +4 -0
  9. ksadk/a2a/__init__.py +15 -0
  10. ksadk/a2a/card_builder.py +64 -0
  11. ksadk/a2a/client.py +309 -0
  12. ksadk/a2a/executor.py +201 -0
  13. ksadk/a2a/server.py +79 -0
  14. ksadk/agents/__init__.py +20 -0
  15. ksadk/agents/base.py +370 -0
  16. ksadk/agents/context.py +38 -0
  17. ksadk/agents/event.py +35 -0
  18. ksadk/agents/loop_agent.py +71 -0
  19. ksadk/agents/parallel_agent.py +109 -0
  20. ksadk/agents/runner_adapter.py +24 -0
  21. ksadk/agents/sequential_agent.py +34 -0
  22. ksadk/api/__init__.py +3 -0
  23. ksadk/api/client.py +2227 -0
  24. ksadk/builders/__init__.py +20 -0
  25. ksadk/builders/base.py +66 -0
  26. ksadk/builders/code_builder.py +1990 -0
  27. ksadk/builders/container_builder.py +786 -0
  28. ksadk/builders/framework_requirements.py +59 -0
  29. ksadk/builders/ks3_uploader.py +389 -0
  30. ksadk/builders/mcp_builder.py +476 -0
  31. ksadk/builders/requirements_utils.py +75 -0
  32. ksadk/cli/__init__.py +531 -0
  33. ksadk/cli/__main__.py +4 -0
  34. ksadk/cli/agent_ref.py +204 -0
  35. ksadk/cli/cmd_a2a.py +167 -0
  36. ksadk/cli/cmd_agent.py +201 -0
  37. ksadk/cli/cmd_build.py +270 -0
  38. ksadk/cli/cmd_completion.py +304 -0
  39. ksadk/cli/cmd_config.py +758 -0
  40. ksadk/cli/cmd_create.py +2277 -0
  41. ksadk/cli/cmd_dashboard.py +900 -0
  42. ksadk/cli/cmd_deploy.py +704 -0
  43. ksadk/cli/cmd_destroy.py +345 -0
  44. ksadk/cli/cmd_files.py +1227 -0
  45. ksadk/cli/cmd_hermes.py +1259 -0
  46. ksadk/cli/cmd_invoke.py +1336 -0
  47. ksadk/cli/cmd_launch.py +564 -0
  48. ksadk/cli/cmd_mcp.py +1174 -0
  49. ksadk/cli/cmd_model.py +302 -0
  50. ksadk/cli/cmd_openclaw.py +3918 -0
  51. ksadk/cli/cmd_run.py +232 -0
  52. ksadk/cli/cmd_status.py +588 -0
  53. ksadk/cli/cmd_version.py +522 -0
  54. ksadk/cli/cmd_web.py +288 -0
  55. ksadk/cli/deploy_utils.py +87 -0
  56. ksadk/cli/dry_run.py +214 -0
  57. ksadk/cli/env_options.py +82 -0
  58. ksadk/cli/error_utils.py +525 -0
  59. ksadk/cli/global_options.py +31 -0
  60. ksadk/cli/local_runtime.py +97 -0
  61. ksadk/cli/model_catalog.py +136 -0
  62. ksadk/cli/network_options.py +410 -0
  63. ksadk/cli/resource_common.py +621 -0
  64. ksadk/cli/storage.py +84 -0
  65. ksadk/cli/ui.py +431 -0
  66. ksadk/cli/workflow_common.py +552 -0
  67. ksadk/common/__init__.py +14 -0
  68. ksadk/common/aicp_env.py +128 -0
  69. ksadk/common/auth.py +190 -0
  70. ksadk/common/constants.py +84 -0
  71. ksadk/common/llm_utils.py +61 -0
  72. ksadk/configs/__init__.py +61 -0
  73. ksadk/configs/env_registry.py +342 -0
  74. ksadk/configs/global_config.py +200 -0
  75. ksadk/configs/settings.py +706 -0
  76. ksadk/conversations/__init__.py +95 -0
  77. ksadk/conversations/attachment_storage.py +379 -0
  78. ksadk/conversations/attachments.py +774 -0
  79. ksadk/conversations/compaction_pipeline.py +387 -0
  80. ksadk/conversations/compaction_prompt.py +128 -0
  81. ksadk/conversations/context.py +303 -0
  82. ksadk/conversations/model_context.py +360 -0
  83. ksadk/conversations/model_options.py +136 -0
  84. ksadk/conversations/normalize.py +446 -0
  85. ksadk/conversations/reasoning_markup.py +91 -0
  86. ksadk/conversations/run_kinds.py +61 -0
  87. ksadk/conversations/run_status.py +53 -0
  88. ksadk/conversations/runtime.py +5208 -0
  89. ksadk/conversations/semantic_summary.py +359 -0
  90. ksadk/conversations/session_title.py +254 -0
  91. ksadk/deployment/__init__.py +83 -0
  92. ksadk/deployment/agent_access.py +226 -0
  93. ksadk/deployment/base.py +229 -0
  94. ksadk/deployment/manager.py +332 -0
  95. ksadk/deployment/providers/__init__.py +10 -0
  96. ksadk/deployment/providers/serverless.py +1105 -0
  97. ksadk/deployment/registry.py +120 -0
  98. ksadk/deployment/state.py +78 -0
  99. ksadk/deployment/ui_config.py +21 -0
  100. ksadk/detection/__init__.py +7 -0
  101. ksadk/detection/detector.py +431 -0
  102. ksadk/detection/mcp_detector.py +250 -0
  103. ksadk/hermes_terminal.py +467 -0
  104. ksadk/identity/__init__.py +17 -0
  105. ksadk/identity/resolver.py +385 -0
  106. ksadk/knowledge_base/__init__.py +62 -0
  107. ksadk/knowledge_base/adk_tool.py +47 -0
  108. ksadk/knowledge_base/client.py +297 -0
  109. ksadk/knowledge_base/langchain_tool.py +55 -0
  110. ksadk/knowledge_base/service.py +66 -0
  111. ksadk/knowledge_base/tool.py +50 -0
  112. ksadk/markdown.py +169 -0
  113. ksadk/mcp_runtime/__init__.py +231 -0
  114. ksadk/memory/__init__.py +57 -0
  115. ksadk/memory/adk/__init__.py +51 -0
  116. ksadk/memory/adk/backends/__init__.py +5 -0
  117. ksadk/memory/adk/backends/base_ltm_backend.py +52 -0
  118. ksadk/memory/adk/backends/http_ltm_backend.py +183 -0
  119. ksadk/memory/adk/backends/inmemory_ltm_backend.py +96 -0
  120. ksadk/memory/adk/backends/sdk_ltm_backend.py +456 -0
  121. ksadk/memory/adk/long_term_memory.py +273 -0
  122. ksadk/memory/adk/short_term_memory.py +289 -0
  123. ksadk/memory/adk_tool.py +31 -0
  124. ksadk/memory/backends/__init__.py +6 -0
  125. ksadk/memory/backends/base.py +103 -0
  126. ksadk/memory/backends/memory.py +112 -0
  127. ksadk/memory/backends/redis.py +146 -0
  128. ksadk/memory/langchain_tool.py +39 -0
  129. ksadk/memory/ltm_backend_factory.py +24 -0
  130. ksadk/memory/manager.py +215 -0
  131. ksadk/memory/service.py +172 -0
  132. ksadk/memory/tool.py +96 -0
  133. ksadk/model_policy.py +223 -0
  134. ksadk/openclaw_gateway.py +378 -0
  135. ksadk/runners/__init__.py +8 -0
  136. ksadk/runners/adk_runner.py +1135 -0
  137. ksadk/runners/base_runner.py +305 -0
  138. ksadk/runners/deepagents_runner.py +13 -0
  139. ksadk/runners/factory.py +73 -0
  140. ksadk/runners/langchain_runner.py +539 -0
  141. ksadk/runners/langgraph_runner.py +852 -0
  142. ksadk/runners/patch_langchain.py +187 -0
  143. ksadk/runners/remote_runner.py +667 -0
  144. ksadk/runners/usage_accumulator.py +38 -0
  145. ksadk/runners/utils/__init__.py +19 -0
  146. ksadk/runners/utils/langfuse.py +230 -0
  147. ksadk/runners/utils/loader.py +62 -0
  148. ksadk/runtime_context.py +166 -0
  149. ksadk/runtime_state.py +25 -0
  150. ksadk/sandbox/__init__.py +28 -0
  151. ksadk/sandbox/backends/__init__.py +9 -0
  152. ksadk/sandbox/backends/e2b.py +154 -0
  153. ksadk/sandbox/backends/local_process.py +131 -0
  154. ksadk/sandbox/base.py +101 -0
  155. ksadk/sandbox/factory.py +53 -0
  156. ksadk/sandbox/registry.py +187 -0
  157. ksadk/server/__init__.py +7 -0
  158. ksadk/server/api_models.py +73 -0
  159. ksadk/server/app.py +3789 -0
  160. ksadk/server/static/assets/ArtifactsPanel-C0meuOdi.js +1 -0
  161. ksadk/server/static/assets/CodeBlock-BbI4HPtJ.js +9 -0
  162. ksadk/server/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  163. ksadk/server/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  164. ksadk/server/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  165. ksadk/server/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  166. ksadk/server/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  167. ksadk/server/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  168. ksadk/server/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  169. ksadk/server/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  170. ksadk/server/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  171. ksadk/server/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  172. ksadk/server/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  173. ksadk/server/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  174. ksadk/server/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  175. ksadk/server/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  176. ksadk/server/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  177. ksadk/server/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  178. ksadk/server/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  179. ksadk/server/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  180. ksadk/server/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  181. ksadk/server/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  182. ksadk/server/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  183. ksadk/server/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  184. ksadk/server/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  185. ksadk/server/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  186. ksadk/server/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  187. ksadk/server/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  188. ksadk/server/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  189. ksadk/server/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  190. ksadk/server/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  191. ksadk/server/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  192. ksadk/server/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  193. ksadk/server/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  194. ksadk/server/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  195. ksadk/server/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  196. ksadk/server/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  197. ksadk/server/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  198. ksadk/server/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  199. ksadk/server/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  200. ksadk/server/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  201. ksadk/server/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  202. ksadk/server/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  203. ksadk/server/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  204. ksadk/server/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  205. ksadk/server/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  206. ksadk/server/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  207. ksadk/server/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  208. ksadk/server/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  209. ksadk/server/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  210. ksadk/server/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  211. ksadk/server/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  212. ksadk/server/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  213. ksadk/server/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  214. ksadk/server/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  215. ksadk/server/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  216. ksadk/server/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  217. ksadk/server/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  218. ksadk/server/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  219. ksadk/server/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  220. ksadk/server/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  221. ksadk/server/static/assets/MathMessageMarkdown-DMLQYoLp.js +8 -0
  222. ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +1 -0
  223. ksadk/server/static/assets/MermaidBlock-DCR8WZ17.js +303 -0
  224. ksadk/server/static/assets/NativeTerminalPanel-CHOd7Rch.css +1 -0
  225. ksadk/server/static/assets/NativeTerminalPanel-CKUvWhUz.js +1 -0
  226. ksadk/server/static/assets/addon-fit-DthTIhi3.js +1 -0
  227. ksadk/server/static/assets/apl-CnwPGSsG.js +1 -0
  228. ksadk/server/static/assets/arc-bj2rZnP5.js +1 -0
  229. ksadk/server/static/assets/architecture-7EHR7CIX-Cr6Xz1_c.js +1 -0
  230. ksadk/server/static/assets/architectureDiagram-3BPJPVTR-2u1ltDIj.js +36 -0
  231. ksadk/server/static/assets/asciiarmor-qTkVPQu6.js +1 -0
  232. ksadk/server/static/assets/asn1-Dr8qZg38.js +1 -0
  233. ksadk/server/static/assets/asterisk-Bja0s6e1.js +1 -0
  234. ksadk/server/static/assets/blockDiagram-GPEHLZMM-D6fvdK20.js +132 -0
  235. ksadk/server/static/assets/brainfuck-D5EjA2JK.js +1 -0
  236. ksadk/server/static/assets/c4Diagram-AAUBKEIU-BK82L5n5.js +10 -0
  237. ksadk/server/static/assets/channel-BSSOwFIb.js +1 -0
  238. ksadk/server/static/assets/chunk-2J33WTMH-DLVdkeyQ.js +1 -0
  239. ksadk/server/static/assets/chunk-4BX2VUAB-BbwsYcbW.js +1 -0
  240. ksadk/server/static/assets/chunk-55IACEB6-DOairxzw.js +1 -0
  241. ksadk/server/static/assets/chunk-727SXJPM-hCO487gs.js +206 -0
  242. ksadk/server/static/assets/chunk-AQP2D5EJ-XU8vDOuG.js +231 -0
  243. ksadk/server/static/assets/chunk-FMBD7UC4-PrapyfMu.js +15 -0
  244. ksadk/server/static/assets/chunk-ND2GUHAM-CboKhTZ3.js +1 -0
  245. ksadk/server/static/assets/chunk-QZHKN3VN-XXpdiwUL.js +1 -0
  246. ksadk/server/static/assets/classDiagram-4FO5ZUOK-C5HvGiyK.js +1 -0
  247. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-C5HvGiyK.js +1 -0
  248. ksadk/server/static/assets/clike-DHH8Ad3s.js +1 -0
  249. ksadk/server/static/assets/clojure-BflJGmDX.js +1 -0
  250. ksadk/server/static/assets/cmake-CyVbuzPu.js +1 -0
  251. ksadk/server/static/assets/cobol-B_OZ4V-R.js +1 -0
  252. ksadk/server/static/assets/coffeescript-B2pKbFk8.js +1 -0
  253. ksadk/server/static/assets/commonlisp-CcllspGY.js +1 -0
  254. ksadk/server/static/assets/cose-bilkent-S5V4N54A-_N8bJ-EU.js +1 -0
  255. ksadk/server/static/assets/crystal-M5-qzICs.js +1 -0
  256. ksadk/server/static/assets/css-CYpP4FRV.js +1 -0
  257. ksadk/server/static/assets/cypher-p9eYesGn.js +1 -0
  258. ksadk/server/static/assets/cytoscape.esm-DelgaX4f.js +321 -0
  259. ksadk/server/static/assets/d-BhMjBjQP.js +1 -0
  260. ksadk/server/static/assets/dagre-BM42HDAG-FoDlo5J2.js +4 -0
  261. ksadk/server/static/assets/dagre-Bx709z4p.js +1 -0
  262. ksadk/server/static/assets/defaultLocale-C8Fc0cco.js +1 -0
  263. ksadk/server/static/assets/diagram-2AECGRRQ-BBp6ebBw.js +43 -0
  264. ksadk/server/static/assets/diagram-5GNKFQAL-CqOvG1PR.js +10 -0
  265. ksadk/server/static/assets/diagram-KO2AKTUF-O9T3t6ba.js +3 -0
  266. ksadk/server/static/assets/diagram-LMA3HP47-CGG8ekBO.js +24 -0
  267. ksadk/server/static/assets/diagram-OG6HWLK6-4BmH1EEg.js +24 -0
  268. ksadk/server/static/assets/diff-ChtP43wD.js +1 -0
  269. ksadk/server/static/assets/dist-6kSZvCZh.js +1 -0
  270. ksadk/server/static/assets/dist-B67uF2uK.js +1 -0
  271. ksadk/server/static/assets/dist-BMKM66B4.js +1 -0
  272. ksadk/server/static/assets/dist-BVzcWa6D.js +1 -0
  273. ksadk/server/static/assets/dist-Bk1l05Ni.js +1 -0
  274. ksadk/server/static/assets/dist-BkJjNih3.js +1 -0
  275. ksadk/server/static/assets/dist-BmuTWcm7.js +9 -0
  276. ksadk/server/static/assets/dist-C2DKRFVK.js +1 -0
  277. ksadk/server/static/assets/dist-CWiTDN_V.js +6 -0
  278. ksadk/server/static/assets/dist-CZ6C3x8B.js +23 -0
  279. ksadk/server/static/assets/dist-CiZHB6ZW.js +1 -0
  280. ksadk/server/static/assets/dist-Cp1_jKwf.js +1 -0
  281. ksadk/server/static/assets/dist-Cwhk4lwI.js +2 -0
  282. ksadk/server/static/assets/dist-D5JGcxBx.js +11 -0
  283. ksadk/server/static/assets/dist-D99wf6_X.js +1 -0
  284. ksadk/server/static/assets/dist-DCpZrjaK.js +1 -0
  285. ksadk/server/static/assets/dist-DI-oVAXw.js +1 -0
  286. ksadk/server/static/assets/dist-DLMjL01k.js +1 -0
  287. ksadk/server/static/assets/dist-DLeM1OCK.js +1 -0
  288. ksadk/server/static/assets/dist-DM0rEQPk.js +1 -0
  289. ksadk/server/static/assets/dist-DbaH3p5h.js +1 -0
  290. ksadk/server/static/assets/dist-S4klkK5W.js +1 -0
  291. ksadk/server/static/assets/dockerfile-BLkNEvjs.js +1 -0
  292. ksadk/server/static/assets/dtd-DTF72YNO.js +1 -0
  293. ksadk/server/static/assets/dylan-C6jEEEk-.js +1 -0
  294. ksadk/server/static/assets/ebnf-D4c0_ac3.js +1 -0
  295. ksadk/server/static/assets/ecl-BSZaIHnp.js +1 -0
  296. ksadk/server/static/assets/eiffel-BEjRio4Q.js +1 -0
  297. ksadk/server/static/assets/elm-Cshzl8qu.js +1 -0
  298. ksadk/server/static/assets/erDiagram-TEJ5UH35-oJhaci7S.js +85 -0
  299. ksadk/server/static/assets/erlang-DaB2Rkuy.js +1 -0
  300. ksadk/server/static/assets/eventmodeling-FCH6USID-CIgwHJLL.js +1 -0
  301. ksadk/server/static/assets/factor-D7LVTn2l.js +1 -0
  302. ksadk/server/static/assets/fcl-ClOhbFR7.js +1 -0
  303. ksadk/server/static/assets/flowDiagram-I6XJVG4X-DtTmUan-.js +162 -0
  304. ksadk/server/static/assets/forth-Cezjo90N.js +1 -0
  305. ksadk/server/static/assets/fortran-Bt6PBEDR.js +1 -0
  306. ksadk/server/static/assets/ganttDiagram-6RSMTGT7-BSsb_eij.js +292 -0
  307. ksadk/server/static/assets/gas-BHEdbvp9.js +1 -0
  308. ksadk/server/static/assets/gherkin-oBAE_ms0.js +1 -0
  309. ksadk/server/static/assets/gitGraph-WXDBUCRP-BVAJ7uo0.js +1 -0
  310. ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-BR5s6Pws.js +106 -0
  311. ksadk/server/static/assets/graphlib-B8gBHxth.js +1 -0
  312. ksadk/server/static/assets/groovy-BC3IOsC8.js +1 -0
  313. ksadk/server/static/assets/haskell-BRsoo5mP.js +1 -0
  314. ksadk/server/static/assets/haxe-DIz0ZZqd.js +1 -0
  315. ksadk/server/static/assets/http-CLVgA2GD.js +1 -0
  316. ksadk/server/static/assets/idl-BUZw3wgd.js +1 -0
  317. ksadk/server/static/assets/index-BH7-pC0B.js +165 -0
  318. ksadk/server/static/assets/index-DAURbCsP.css +1 -0
  319. ksadk/server/static/assets/info-J43DQDTF-MT80V4ge.js +1 -0
  320. ksadk/server/static/assets/infoDiagram-5YYISTIA-DYPc5cvh.js +2 -0
  321. ksadk/server/static/assets/init-D6jRqBbL.js +1 -0
  322. ksadk/server/static/assets/ishikawaDiagram-YF4QCWOH-MoBdALDg.js +70 -0
  323. ksadk/server/static/assets/javascript-9Tg8ixDm.js +1 -0
  324. ksadk/server/static/assets/journeyDiagram-JHISSGLW-DgLiQT8l.js +139 -0
  325. ksadk/server/static/assets/julia-CQfgDRfP.js +1 -0
  326. ksadk/server/static/assets/kanban-definition-UN3LZRKU-CsFx112F.js +89 -0
  327. ksadk/server/static/assets/katex-DRsiwpM2.js +265 -0
  328. ksadk/server/static/assets/linear-TNRQ5Orv.js +1 -0
  329. ksadk/server/static/assets/livescript-BXxG0Yva.js +1 -0
  330. ksadk/server/static/assets/lua-CiA1ziua.js +1 -0
  331. ksadk/server/static/assets/mathematica-u8YMmbU0.js +1 -0
  332. ksadk/server/static/assets/mbox-BEMVcqjs.js +1 -0
  333. ksadk/server/static/assets/mermaid-parser.core-D2eMVOgo.js +161 -0
  334. ksadk/server/static/assets/mindmap-definition-RKZ34NQL-BtByYFhL.js +96 -0
  335. ksadk/server/static/assets/mirc-C9zpzAZU.js +1 -0
  336. ksadk/server/static/assets/mllike-B45xgp2S.js +1 -0
  337. ksadk/server/static/assets/modelica-CqHI_q-D.js +1 -0
  338. ksadk/server/static/assets/mscgen-qgSLujhx.js +1 -0
  339. ksadk/server/static/assets/mumps-CW_TBmxz.js +1 -0
  340. ksadk/server/static/assets/nginx-BMaDbqW3.js +1 -0
  341. ksadk/server/static/assets/nsis-AQ_alPln.js +1 -0
  342. ksadk/server/static/assets/ntriples-d28e9m0E.js +1 -0
  343. ksadk/server/static/assets/octave-D2Q8cUp1.js +1 -0
  344. ksadk/server/static/assets/ordinal-hYBb2elL.js +1 -0
  345. ksadk/server/static/assets/oz-BwTct_5T.js +1 -0
  346. ksadk/server/static/assets/packet-YPE3B663-BLKhbXZB.js +1 -0
  347. ksadk/server/static/assets/pascal-Dp_KdFgX.js +1 -0
  348. ksadk/server/static/assets/perl-CdEHsPfU.js +1 -0
  349. ksadk/server/static/assets/pie-LRSECV5Y-DFOikjSY.js +1 -0
  350. ksadk/server/static/assets/pieDiagram-4H26LBE5-DPnuCB8c.js +30 -0
  351. ksadk/server/static/assets/pig-AF4Hwhju.js +1 -0
  352. ksadk/server/static/assets/powershell-CzG71I4L.js +1 -0
  353. ksadk/server/static/assets/properties-C357ku5U.js +1 -0
  354. ksadk/server/static/assets/protobuf-D1ij_kNL.js +1 -0
  355. ksadk/server/static/assets/pug-Bugr-47h.js +1 -0
  356. ksadk/server/static/assets/puppet-B4hC2X4m.js +1 -0
  357. ksadk/server/static/assets/python-BqYw9LYJ.js +1 -0
  358. ksadk/server/static/assets/q-B9NhS7L_.js +1 -0
  359. ksadk/server/static/assets/quadrantDiagram-W4KKPZXB-miFpCPv4.js +7 -0
  360. ksadk/server/static/assets/r-DADKenSm.js +1 -0
  361. ksadk/server/static/assets/radar-GUYGQ44K-095b1Ikw.js +1 -0
  362. ksadk/server/static/assets/requirementDiagram-4Y6WPE33-mjB_yYkW.js +84 -0
  363. ksadk/server/static/assets/rpm-gpDK5sbt.js +1 -0
  364. ksadk/server/static/assets/ruby-DsYpTuWg.js +1 -0
  365. ksadk/server/static/assets/sankeyDiagram-5OEKKPKP-D7hSlZZZ.js +40 -0
  366. ksadk/server/static/assets/sas-C2OyD2Y6.js +1 -0
  367. ksadk/server/static/assets/scheme-CyDdOh7e.js +1 -0
  368. ksadk/server/static/assets/sequenceDiagram-3UESZ5HK-D9Cx6hC3.js +162 -0
  369. ksadk/server/static/assets/shell-Du5Qg9im.js +1 -0
  370. ksadk/server/static/assets/sieve-BAxa3IjF.js +1 -0
  371. ksadk/server/static/assets/simple-mode-DRpGK0lJ.js +1 -0
  372. ksadk/server/static/assets/smalltalk-BLp5-jwC.js +1 -0
  373. ksadk/server/static/assets/solr-BBopId9w.js +1 -0
  374. ksadk/server/static/assets/sparql-Dz-mlCAC.js +1 -0
  375. ksadk/server/static/assets/spreadsheet-CTIncYxj.js +1 -0
  376. ksadk/server/static/assets/sql-DcCJ9jop.js +1 -0
  377. ksadk/server/static/assets/stateDiagram-AJRCARHV-D_zrg47o.js +1 -0
  378. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-J9kCb0nC.js +1 -0
  379. ksadk/server/static/assets/stex-sDrdk2BW.js +1 -0
  380. ksadk/server/static/assets/stylus-DLLZ8dgm.js +1 -0
  381. ksadk/server/static/assets/swift-DKB6_1j6.js +1 -0
  382. ksadk/server/static/assets/tcl-BGfruO1u.js +1 -0
  383. ksadk/server/static/assets/textile-DWBqthVk.js +1 -0
  384. ksadk/server/static/assets/tiddlywiki-VlUiK86J.js +1 -0
  385. ksadk/server/static/assets/tiki-CxVlf5KZ.js +1 -0
  386. ksadk/server/static/assets/timeline-definition-PNZ67QCA-CwSec0Wa.js +120 -0
  387. ksadk/server/static/assets/toml-LvoKBwCs.js +1 -0
  388. ksadk/server/static/assets/treeView-BLDUP644-yinfJEY6.js +1 -0
  389. ksadk/server/static/assets/treemap-LRROVOQU-DosUqN1Q.js +1 -0
  390. ksadk/server/static/assets/troff-C2dAgh7P.js +1 -0
  391. ksadk/server/static/assets/ttcn-BePYh-hG.js +1 -0
  392. ksadk/server/static/assets/ttcn-cfg-CY0aot7Q.js +1 -0
  393. ksadk/server/static/assets/turtle-BDLWE2cD.js +1 -0
  394. ksadk/server/static/assets/vb-BthdM_4N.js +1 -0
  395. ksadk/server/static/assets/vbscript-D9f6rSsU.js +1 -0
  396. ksadk/server/static/assets/velocity-CqftRsjg.js +1 -0
  397. ksadk/server/static/assets/vennDiagram-CIIHVFJN-agCVobiF.js +34 -0
  398. ksadk/server/static/assets/verilog-D-x6ne0Z.js +1 -0
  399. ksadk/server/static/assets/vhdl-CMrOq2q1.js +1 -0
  400. ksadk/server/static/assets/wardley-L42UT6IY-Bvp7-5uH.js +1 -0
  401. ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-TmrlhWNt.js +78 -0
  402. ksadk/server/static/assets/webidl-D5jiJvOU.js +1 -0
  403. ksadk/server/static/assets/xquery-fj_R-kMw.js +1 -0
  404. ksadk/server/static/assets/xterm-DooSxjI5.js +36 -0
  405. ksadk/server/static/assets/xychartDiagram-2RQKCTM6-DV71V-ah.js +7 -0
  406. ksadk/server/static/assets/yacas-CXXgtw0p.js +1 -0
  407. ksadk/server/static/assets/z80-CL1naaMV.js +1 -0
  408. ksadk/server/static/favicon.svg +1 -0
  409. ksadk/server/static/icons.svg +24 -0
  410. ksadk/server/static/index.html +14 -0
  411. ksadk/server/terminal_sessions.py +551 -0
  412. ksadk/sessions/__init__.py +283 -0
  413. ksadk/sessions/base.py +354 -0
  414. ksadk/sessions/continuity.py +313 -0
  415. ksadk/sessions/errors.py +7 -0
  416. ksadk/sessions/in_memory.py +273 -0
  417. ksadk/sessions/local_service.py +949 -0
  418. ksadk/sessions/postgres_service.py +838 -0
  419. ksadk/sessions/sqlite_service.py +13 -0
  420. ksadk/skills/__init__.py +9 -0
  421. ksadk/skills/loader.py +46 -0
  422. ksadk/skills/models.py +120 -0
  423. ksadk/skills/package_store.py +104 -0
  424. ksadk/skills/runtime/__init__.py +17 -0
  425. ksadk/skills/runtime/agent.py +183 -0
  426. ksadk/skills/runtime/artifacts.py +39 -0
  427. ksadk/skills/runtime/backends/__init__.py +1 -0
  428. ksadk/skills/runtime/backends/disabled.py +8 -0
  429. ksadk/skills/runtime/backends/e2b.py +168 -0
  430. ksadk/skills/runtime/backends/local.py +95 -0
  431. ksadk/skills/runtime/base.py +103 -0
  432. ksadk/skills/runtime/executor.py +219 -0
  433. ksadk/skills/runtime/factory.py +37 -0
  434. ksadk/skills/runtime/loader.py +131 -0
  435. ksadk/skills/runtime/registry.py +150 -0
  436. ksadk/skills/runtime/request.py +67 -0
  437. ksadk/skills/service_client.py +239 -0
  438. ksadk/skills/service_env.py +58 -0
  439. ksadk/skills/tool_defs.py +221 -0
  440. ksadk/terminal_client.py +69 -0
  441. ksadk/terminal_exec_policy.py +229 -0
  442. ksadk/tools/__init__.py +17 -0
  443. ksadk/tools/gateway.py +230 -0
  444. ksadk/tools/result_budget.py +154 -0
  445. ksadk/toolsets/__init__.py +852 -0
  446. ksadk/toolsets/_langchain.py +11 -0
  447. ksadk/toolsets/platform.py +93 -0
  448. ksadk/toolsets/sandbox.py +310 -0
  449. ksadk/toolsets/skills.py +217 -0
  450. ksadk/toolsets/web.py +266 -0
  451. ksadk/toolsets/workspace.py +878 -0
  452. ksadk/toolsets/workspace_state.py +44 -0
  453. ksadk/tracing/__init__.py +37 -0
  454. ksadk/tracing/exporters/__init__.py +1 -0
  455. ksadk/tracing/exporters/inmemory_exporter.py +116 -0
  456. ksadk/tracing/exporters/langfuse_exporter.py +445 -0
  457. ksadk/tracing/setup.py +829 -0
  458. ksadk/tracing/span_utils.py +114 -0
  459. ksadk/tui/__init__.py +12 -0
  460. ksadk/tui/app.py +400 -0
  461. ksadk/tui/clipboard.py +100 -0
  462. ksadk/tui/widgets/__init__.py +22 -0
  463. ksadk/tui/widgets/assistant.py +89 -0
  464. ksadk/tui/widgets/base.py +54 -0
  465. ksadk/tui/widgets/chat_input.py +246 -0
  466. ksadk/tui/widgets/history.py +156 -0
  467. ksadk/tui/widgets/system.py +87 -0
  468. ksadk/tui/widgets/thinking.py +110 -0
  469. ksadk/tui/widgets/tool_call.py +161 -0
  470. ksadk/tui/widgets/user.py +37 -0
  471. ksadk/ui_config.py +168 -0
  472. ksadk/version.py +4 -0
  473. ksadk_runtime_common/__init__.py +20 -0
  474. ksadk_runtime_common/memory_backend/__init__.py +29 -0
  475. ksadk_runtime_common/memory_backend/manifest.py +79 -0
  476. ksadk_runtime_common/memory_backend/providers/__init__.py +6 -0
  477. ksadk_runtime_common/memory_backend/providers/lancedb.py +151 -0
  478. ksadk_runtime_common/memory_backend/providers/mem0.py +74 -0
  479. ksadk_runtime_common/memory_backend/registry.py +56 -0
  480. ksadk_runtime_common/memory_backend/render.py +71 -0
  481. ksadk_runtime_common/schemas/memory_backend_manifest.schema.json +148 -0
  482. ksadk_runtime_common/workspace_files/__init__.py +29 -0
  483. ksadk_runtime_common/workspace_files/bootstrap.py +56 -0
  484. ksadk_runtime_common/workspace_files/constants.py +9 -0
  485. ksadk_runtime_common/workspace_files/path_utils.py +71 -0
  486. ksadk_runtime_common/workspace_files/preview.py +96 -0
  487. ksadk_runtime_common/workspace_files/router.py +254 -0
  488. agentengine_sdk_python-0.6.2.dist-info/METADATA +0 -46
  489. agentengine_sdk_python-0.6.2.dist-info/RECORD +0 -4
  490. agentengine_sdk_python-0.6.2.dist-info/top_level.txt +0 -1
@@ -0,0 +1,136 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, Mapping
4
+
5
+
6
+ _VALID_REASONING_EFFORTS = {"none", "minimal", "low", "medium", "high", "xhigh"}
7
+ _CHAT_COMPLETIONS_REASONING_EFFORTS = {"low", "medium", "high"}
8
+ _PASSTHROUGH_OPTION_KEYS = {"temperature", "top_p", "max_tokens", "max_completion_tokens"}
9
+
10
+
11
+ def _normalized_effort(value: Any) -> str | None:
12
+ effort = str(value or "").strip().lower()
13
+ return effort if effort in _VALID_REASONING_EFFORTS else None
14
+
15
+
16
+ def _is_disabled_thinking(value: Any) -> bool:
17
+ if isinstance(value, bool):
18
+ return not value
19
+ if isinstance(value, Mapping):
20
+ raw_type = str(value.get("type") or value.get("status") or "").strip().lower()
21
+ return raw_type in {"disabled", "disable", "off", "none", "false", "0"}
22
+ raw = str(value or "").strip().lower()
23
+ return raw in {"disabled", "disable", "off", "none", "false", "0"}
24
+
25
+
26
+ def _is_enabled_thinking(value: Any) -> bool:
27
+ if isinstance(value, bool):
28
+ return value
29
+ if isinstance(value, Mapping):
30
+ raw_type = str(value.get("type") or value.get("status") or "").strip().lower()
31
+ return raw_type in {"enabled", "enable", "on", "true", "1"}
32
+ raw = str(value or "").strip().lower()
33
+ return raw in {"enabled", "enable", "on", "true", "1"}
34
+
35
+
36
+ def normalize_model_options(model_options: Mapping[str, Any] | None) -> dict[str, Any]:
37
+ """Normalize request model options while preserving provider-specific fallbacks.
38
+
39
+ The runtime's canonical reasoning switch is `reasoning.effort`. Legacy
40
+ `thinking` inputs are accepted for compatibility and kept in the normalized
41
+ payload because some OpenAI-compatible providers still read them.
42
+ """
43
+
44
+ if not isinstance(model_options, Mapping):
45
+ return {}
46
+
47
+ normalized = dict(model_options)
48
+ reasoning = normalized.get("reasoning")
49
+ canonical_effort: str | None = None
50
+ if isinstance(reasoning, Mapping):
51
+ canonical_effort = _normalized_effort(reasoning.get("effort"))
52
+ canonical_effort = canonical_effort or _normalized_effort(normalized.get("reasoning_effort"))
53
+
54
+ thinking = normalized.get("thinking")
55
+ if canonical_effort is None and "thinking_enabled" in normalized:
56
+ thinking = bool(normalized.get("thinking_enabled"))
57
+ normalized.setdefault(
58
+ "thinking",
59
+ {"type": "enabled"} if thinking else {"type": "disabled"},
60
+ )
61
+ if canonical_effort is None and "thinking" in normalized:
62
+ if _is_disabled_thinking(thinking):
63
+ canonical_effort = "none"
64
+ if isinstance(thinking, Mapping):
65
+ normalized["thinking"] = {**dict(thinking), "type": "disabled"}
66
+ else:
67
+ normalized["thinking"] = {"type": "disabled"}
68
+ normalized.setdefault("max_reasoning_tokens", 0)
69
+ elif _is_enabled_thinking(thinking):
70
+ if isinstance(thinking, Mapping):
71
+ explicit_effort = _normalized_effort(thinking.get("effort"))
72
+ if explicit_effort:
73
+ canonical_effort = explicit_effort
74
+ normalized["thinking"] = {**dict(thinking), "type": "enabled"}
75
+ else:
76
+ normalized["thinking"] = {"type": "enabled"}
77
+ canonical_effort = canonical_effort or "medium"
78
+
79
+ if canonical_effort is not None:
80
+ existing_reasoning = dict(reasoning) if isinstance(reasoning, Mapping) else {}
81
+ existing_reasoning["effort"] = canonical_effort
82
+ normalized["reasoning"] = existing_reasoning
83
+
84
+ return normalized
85
+
86
+
87
+ def model_options_for_chat_completions(model_options: Mapping[str, Any] | None) -> dict[str, Any]:
88
+ normalized = normalize_model_options(model_options)
89
+ payload: dict[str, Any] = {}
90
+ for key in _PASSTHROUGH_OPTION_KEYS:
91
+ if key in normalized:
92
+ payload[key] = normalized[key]
93
+ reasoning = normalized.get("reasoning")
94
+ if isinstance(reasoning, Mapping):
95
+ effort = _normalized_effort(reasoning.get("effort"))
96
+ if effort in _CHAT_COMPLETIONS_REASONING_EFFORTS:
97
+ payload["reasoning_effort"] = effort
98
+
99
+ extra_body = dict(normalized.get("extra_body") or {})
100
+ if _is_disabled_thinking(normalized.get("thinking")):
101
+ extra_body.setdefault("enable_thinking", False)
102
+ chat_template_kwargs = dict(extra_body.get("chat_template_kwargs") or {})
103
+ chat_template_kwargs.setdefault("enable_thinking", False)
104
+ extra_body["chat_template_kwargs"] = chat_template_kwargs
105
+ if "max_reasoning_tokens" in normalized:
106
+ extra_body.setdefault("max_reasoning_tokens", normalized["max_reasoning_tokens"])
107
+ if extra_body:
108
+ payload["extra_body"] = extra_body
109
+ return payload
110
+
111
+
112
+ def model_options_for_responses(model_options: Mapping[str, Any] | None) -> dict[str, Any]:
113
+ normalized = normalize_model_options(model_options)
114
+ payload: dict[str, Any] = {}
115
+ for key in _PASSTHROUGH_OPTION_KEYS:
116
+ if key in normalized:
117
+ payload[key] = normalized[key]
118
+ reasoning = normalized.get("reasoning")
119
+ if isinstance(reasoning, Mapping):
120
+ effort = _normalized_effort(reasoning.get("effort"))
121
+ if effort:
122
+ payload["reasoning"] = {"effort": effort}
123
+
124
+ extra_body = dict(normalized.get("extra_body") or {})
125
+ if "thinking" in normalized:
126
+ extra_body.setdefault("thinking", normalized["thinking"])
127
+ if _is_disabled_thinking(normalized.get("thinking")):
128
+ extra_body.setdefault("enable_thinking", False)
129
+ chat_template_kwargs = dict(extra_body.get("chat_template_kwargs") or {})
130
+ chat_template_kwargs.setdefault("enable_thinking", False)
131
+ extra_body["chat_template_kwargs"] = chat_template_kwargs
132
+ if "max_reasoning_tokens" in normalized:
133
+ extra_body.setdefault("max_reasoning_tokens", normalized["max_reasoning_tokens"])
134
+ if extra_body:
135
+ payload["extra_body"] = extra_body
136
+ return payload
@@ -0,0 +1,446 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, Dict, List, Optional
4
+ from pathlib import Path
5
+
6
+ from ksadk.conversations.attachments import (
7
+ build_attachment_prompt_text,
8
+ build_attachment_results,
9
+ compact_attachment_result_for_session,
10
+ decode_inline_data,
11
+ extract_pdf_text,
12
+ is_textual_mime,
13
+ looks_like_textual_attachment,
14
+ read_attachment_bytes,
15
+ resolve_attachment_storage_path,
16
+ resolve_uploads_dir,
17
+ )
18
+ from ksadk.conversations.context import canonical_event_type
19
+ from ksadk.server.api_models import Part
20
+
21
+
22
+ def _extract_openai_image_url(value: Any) -> str:
23
+ if isinstance(value, str):
24
+ return value.strip()
25
+ if isinstance(value, dict):
26
+ url = value.get("url")
27
+ if isinstance(url, str):
28
+ return url.strip()
29
+ return ""
30
+
31
+
32
+ def _data_url_from_inline_data(inline_data: Dict[str, Any]) -> str:
33
+ data = str(inline_data.get("data") or "").strip()
34
+ if not data:
35
+ return ""
36
+ mime_type = str(inline_data.get("mimeType") or "application/octet-stream").strip()
37
+ return f"data:{mime_type};base64,{data}"
38
+
39
+
40
+ def _inline_data_from_data_url(url: str, *, display_name: str) -> Optional[Dict[str, Any]]:
41
+ normalized = (url or "").strip()
42
+ if not normalized.lower().startswith("data:") or "," not in normalized:
43
+ return None
44
+
45
+ metadata, data = normalized.split(",", 1)
46
+ if ";base64" not in metadata.lower():
47
+ return None
48
+
49
+ mime_type = metadata[5:].split(";", 1)[0].strip() or "application/octet-stream"
50
+ return {
51
+ "data": data.strip(),
52
+ "mimeType": mime_type,
53
+ "displayName": display_name,
54
+ }
55
+
56
+
57
+ def _file_data_from_openai_image_url(url: str, *, display_name: str) -> Optional[Dict[str, Any]]:
58
+ normalized = (url or "").strip()
59
+ if not normalized or normalized.lower().startswith("data:"):
60
+ return None
61
+ return {
62
+ "fileUri": normalized,
63
+ "mimeType": "image/*",
64
+ "displayName": display_name,
65
+ }
66
+
67
+
68
+ def _guess_mime_type(display_name: str) -> str:
69
+ suffix = Path(display_name or "").suffix.lower()
70
+ if suffix == ".pdf":
71
+ return "application/pdf"
72
+ if suffix == ".txt":
73
+ return "text/plain"
74
+ if suffix in {".md", ".markdown"}:
75
+ return "text/markdown"
76
+ if suffix == ".json":
77
+ return "application/json"
78
+ if suffix in {".yaml", ".yml"}:
79
+ return "application/yaml"
80
+ if suffix == ".csv":
81
+ return "text/csv"
82
+ if suffix == ".html" or suffix == ".htm":
83
+ return "text/html"
84
+ if suffix == ".docx":
85
+ return "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
86
+ if suffix == ".pptx":
87
+ return "application/vnd.openxmlformats-officedocument.presentationml.presentation"
88
+ if suffix == ".xlsx":
89
+ return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
90
+ if suffix == ".zip":
91
+ return "application/zip"
92
+ if suffix in {".png", ".jpg", ".jpeg", ".webp"}:
93
+ return f"image/{'jpeg' if suffix in {'.jpg', '.jpeg'} else suffix.removeprefix('.')}"
94
+ return "application/octet-stream"
95
+
96
+
97
+ def _openai_file_display_name(item: Dict[str, Any]) -> str:
98
+ return str(
99
+ item.get("filename")
100
+ or item.get("displayName")
101
+ or item.get("display_name")
102
+ or "uploaded_file"
103
+ )
104
+
105
+
106
+ def _inline_data_from_openai_file(item: Dict[str, Any]) -> Optional[Dict[str, Any]]:
107
+ data = item.get("file_data")
108
+ if not isinstance(data, str) or not data.strip():
109
+ return None
110
+ display_name = _openai_file_display_name(item)
111
+ return {
112
+ "data": data.strip(),
113
+ "mimeType": str(item.get("mime_type") or item.get("mimeType") or _guess_mime_type(display_name)),
114
+ "displayName": display_name,
115
+ }
116
+
117
+
118
+ def _file_data_from_openai_file(item: Dict[str, Any]) -> Optional[Dict[str, Any]]:
119
+ file_uri = item.get("file_url") or item.get("file_id") or item.get("fileUri")
120
+ if not isinstance(file_uri, str) or not file_uri.strip():
121
+ return None
122
+ display_name = _openai_file_display_name(item)
123
+ return {
124
+ "fileUri": file_uri.strip(),
125
+ "mimeType": str(item.get("mime_type") or item.get("mimeType") or _guess_mime_type(display_name)),
126
+ "displayName": display_name,
127
+ }
128
+
129
+
130
+ def _canonical_input_content_from_part_payload(payload: Dict[str, Any]) -> Optional[Dict[str, Any]]:
131
+ text = payload.get("text")
132
+ if text is not None:
133
+ return {"type": "input_text", "text": str(text or "")}
134
+
135
+ inline_data = payload.get("inlineData")
136
+ if isinstance(inline_data, dict):
137
+ data = str(inline_data.get("data") or "").strip()
138
+ if not data:
139
+ return None
140
+ display_name = str(inline_data.get("displayName") or "uploaded_file")
141
+ mime_type = str(inline_data.get("mimeType") or _guess_mime_type(display_name)).strip()
142
+ if mime_type.startswith("image/"):
143
+ return {
144
+ "type": "input_image",
145
+ "image_url": _data_url_from_inline_data(inline_data),
146
+ }
147
+ return {
148
+ "type": "input_file",
149
+ "filename": display_name,
150
+ "file_data": data,
151
+ }
152
+
153
+ file_data = payload.get("fileData")
154
+ if isinstance(file_data, dict):
155
+ file_uri = str(file_data.get("fileUri") or "").strip()
156
+ display_name = str(file_data.get("displayName") or file_uri or "uploaded_file")
157
+ mime_type = str(file_data.get("mimeType") or _guess_mime_type(display_name)).strip()
158
+ if mime_type.startswith("image/") and file_uri:
159
+ return {
160
+ "type": "input_image",
161
+ "image_url": file_uri,
162
+ }
163
+ block: Dict[str, Any] = {
164
+ "type": "input_file",
165
+ "filename": display_name,
166
+ }
167
+ if file_uri:
168
+ block["file_url"] = file_uri
169
+ return block
170
+
171
+ return None
172
+
173
+
174
+ def _canonical_input_content_from_item(item: Dict[str, Any]) -> Optional[Dict[str, Any]]:
175
+ item_type = str(item.get("type") or "").strip()
176
+ if item_type in {"input_text", "text"} or (
177
+ not item_type and item.get("text") is not None
178
+ ):
179
+ return {"type": "input_text", "text": str(item.get("text") or "")}
180
+
181
+ if item_type in {"input_image", "image_url"}:
182
+ image_url = _extract_openai_image_url(item.get("image_url"))
183
+ if not image_url:
184
+ return None
185
+ block: Dict[str, Any] = {"type": "input_image", "image_url": image_url}
186
+ if item.get("detail") is not None:
187
+ block["detail"] = item.get("detail")
188
+ return block
189
+
190
+ if item_type == "input_file":
191
+ block = {"type": "input_file"}
192
+ filename = item.get("filename") or item.get("displayName") or item.get("display_name")
193
+ if filename is not None:
194
+ block["filename"] = str(filename)
195
+ if item.get("file_data") is not None:
196
+ block["file_data"] = str(item.get("file_data") or "")
197
+ if item.get("file_url") is not None:
198
+ block["file_url"] = str(item.get("file_url") or "")
199
+ elif item.get("fileUri") is not None:
200
+ block["file_url"] = str(item.get("fileUri") or "")
201
+ if item.get("file_id") is not None:
202
+ block["file_id"] = str(item.get("file_id") or "")
203
+ if len(block) > 1:
204
+ return block
205
+
206
+ legacy_block = _canonical_input_content_from_part_payload(item)
207
+ if legacy_block is not None:
208
+ return legacy_block
209
+ return None
210
+
211
+
212
+ def canonical_input_content_from_parts(parts: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
213
+ canonical: List[Dict[str, Any]] = []
214
+ for part in parts or []:
215
+ if not isinstance(part, dict):
216
+ continue
217
+ block = _canonical_input_content_from_part_payload(part)
218
+ if block is not None:
219
+ canonical.append(block)
220
+ return canonical
221
+
222
+
223
+ def canonical_input_content_from_message_content(content: Any) -> List[Dict[str, Any]]:
224
+ if isinstance(content, list):
225
+ canonical: List[Dict[str, Any]] = []
226
+ for item in content:
227
+ if not isinstance(item, dict):
228
+ continue
229
+ block = _canonical_input_content_from_item(item)
230
+ if block is not None:
231
+ canonical.append(block)
232
+ return canonical
233
+ text = str(content or "")
234
+ return [{"type": "input_text", "text": text}] if text else []
235
+
236
+
237
+ def _part_payload_from_content_item(item: Dict[str, Any]) -> Dict[str, Any]:
238
+ payload: Dict[str, Any] = {}
239
+ if item.get("text") is not None:
240
+ payload["text"] = str(item.get("text") or "")
241
+ if item.get("inlineData") is not None:
242
+ payload["inlineData"] = item.get("inlineData")
243
+ if item.get("fileData") is not None:
244
+ payload["fileData"] = item.get("fileData")
245
+
246
+ item_type = str(item.get("type") or "").strip()
247
+ if item_type == "input_image" and "inlineData" not in payload and "fileData" not in payload:
248
+ display_name = str(item.get("displayName") or item.get("display_name") or "uploaded_image")
249
+ image_url = _extract_openai_image_url(item.get("image_url"))
250
+ inline_data = _inline_data_from_data_url(image_url, display_name=display_name)
251
+ if inline_data is not None:
252
+ payload["inlineData"] = inline_data
253
+ else:
254
+ file_data = _file_data_from_openai_image_url(image_url, display_name=display_name)
255
+ if file_data is not None:
256
+ payload["fileData"] = file_data
257
+ if item_type == "image_url" and "inlineData" not in payload and "fileData" not in payload:
258
+ display_name = str(item.get("displayName") or item.get("display_name") or "uploaded_image")
259
+ image_url = _extract_openai_image_url(item.get("image_url"))
260
+ inline_data = _inline_data_from_data_url(image_url, display_name=display_name)
261
+ if inline_data is not None:
262
+ payload["inlineData"] = inline_data
263
+ else:
264
+ file_data = _file_data_from_openai_image_url(image_url, display_name=display_name)
265
+ if file_data is not None:
266
+ payload["fileData"] = file_data
267
+ if item_type == "input_file" and "inlineData" not in payload and "fileData" not in payload:
268
+ inline_data = _inline_data_from_openai_file(item)
269
+ if inline_data is not None:
270
+ payload["inlineData"] = inline_data
271
+ else:
272
+ file_data = _file_data_from_openai_file(item)
273
+ if file_data is not None:
274
+ payload["fileData"] = file_data
275
+
276
+ return payload
277
+
278
+
279
+ def attachment_prompt_text(attachment: Dict[str, Any]) -> str:
280
+ result = build_attachment_results([attachment])[0]
281
+ return build_attachment_prompt_text(result)
282
+
283
+
284
+ def extract_user_input_from_parts(parts: List[Part]) -> str:
285
+ return str(normalize_parts_content(parts).get("content") or "")
286
+
287
+
288
+ def compact_attachment_for_session(attachment: Dict[str, Any]) -> Dict[str, Any]:
289
+ return {
290
+ key: value
291
+ for key, value in attachment.items()
292
+ if key in {"display_name", "mime_type", "transport", "size_bytes", "is_text", "file_uri"}
293
+ and value not in (None, "")
294
+ }
295
+
296
+
297
+ def attachment_from_part(part: Part) -> Optional[Dict[str, Any]]:
298
+ inline = part.inlineData
299
+ if inline and inline.data:
300
+ display_name = inline.displayName or "uploaded_file"
301
+ mime_type = (inline.mimeType or "").strip() or "application/octet-stream"
302
+ try:
303
+ raw = decode_inline_data(inline.data)
304
+ except Exception:
305
+ raw = b""
306
+ return {
307
+ "display_name": display_name,
308
+ "mime_type": mime_type,
309
+ "transport": "inline",
310
+ "data": inline.data.strip(),
311
+ "is_text": looks_like_textual_attachment(mime_type, display_name),
312
+ "size_bytes": len(raw),
313
+ }
314
+
315
+ file_data = part.fileData
316
+ if file_data and (file_data.fileUri or file_data.displayName):
317
+ display_name = file_data.displayName or file_data.fileUri or "uploaded_file"
318
+ mime_type = (file_data.mimeType or "").strip() or "application/octet-stream"
319
+ storage_path = resolve_attachment_storage_path(file_data.fileUri or "")
320
+ try:
321
+ size_bytes = storage_path.stat().st_size if storage_path and storage_path.exists() else None
322
+ except OSError:
323
+ size_bytes = None
324
+ return {
325
+ "display_name": display_name,
326
+ "mime_type": mime_type,
327
+ "transport": "reference",
328
+ "file_uri": file_data.fileUri or "",
329
+ "is_text": looks_like_textual_attachment(mime_type, display_name),
330
+ "size_bytes": size_bytes,
331
+ "storage_path": str(storage_path) if storage_path else None,
332
+ }
333
+
334
+ return None
335
+
336
+
337
+ def display_content_from_parts(parts: List[Part]) -> str:
338
+ text_segments: List[str] = []
339
+ attachment_names: List[str] = []
340
+
341
+ for part in parts or []:
342
+ if part.text:
343
+ text_segments.append(part.text)
344
+ continue
345
+
346
+ inline = part.inlineData
347
+ if inline and (inline.displayName or inline.data):
348
+ attachment_names.append(inline.displayName or "uploaded_file")
349
+ continue
350
+
351
+ file_data = part.fileData
352
+ if file_data and (file_data.displayName or file_data.fileUri):
353
+ attachment_names.append(file_data.displayName or file_data.fileUri or "uploaded_file")
354
+
355
+ blocks = [segment.strip() for segment in text_segments if str(segment).strip()]
356
+ if attachment_names:
357
+ attachment_block = "## 附件\n" + "\n".join(f"- {name}" for name in attachment_names)
358
+ blocks.append(attachment_block)
359
+ return "\n\n".join(blocks).strip()
360
+
361
+
362
+ def normalize_parts_content(parts: List[Part]) -> dict[str, Any]:
363
+ attachments = [attachment for attachment in (attachment_from_part(part) for part in parts) if attachment]
364
+ attachment_results = build_attachment_results(attachments)
365
+ display_content = display_content_from_parts(parts)
366
+ segments: List[str] = []
367
+ attachment_index = 0
368
+ for part in parts or []:
369
+ if part.text:
370
+ segments.append(part.text)
371
+ continue
372
+ if attachment_index < len(attachment_results):
373
+ segments.append(build_attachment_prompt_text(attachment_results[attachment_index]))
374
+ attachment_index += 1
375
+ return {
376
+ "content": "\n\n".join(segment.strip() for segment in segments if str(segment).strip()).strip(),
377
+ "display_content": display_content,
378
+ "parts": [part.model_dump(exclude_none=True) for part in parts],
379
+ "attachments": attachments,
380
+ "attachment_results": attachment_results,
381
+ }
382
+
383
+
384
+ def normalize_kop_message_content(content: Any) -> dict[str, Any]:
385
+ input_content = canonical_input_content_from_message_content(content)
386
+ if isinstance(content, list):
387
+ parts: List[Part] = []
388
+ for item in content:
389
+ if not isinstance(item, dict):
390
+ continue
391
+ payload = _part_payload_from_content_item(item)
392
+ if not payload:
393
+ continue
394
+ try:
395
+ parts.append(Part.model_validate(payload))
396
+ except Exception:
397
+ continue
398
+ normalized = normalize_parts_content(parts)
399
+ normalized["input_content"] = input_content
400
+ return normalized
401
+ text = str(content or "")
402
+ return {
403
+ "content": text,
404
+ "display_content": text,
405
+ "parts": [{"text": text}] if text else [],
406
+ "input_content": input_content,
407
+ "attachments": [],
408
+ "attachment_results": [],
409
+ }
410
+
411
+
412
+ def normalize_kop_messages(messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
413
+ normalized: List[Dict[str, Any]] = []
414
+ for message in messages or []:
415
+ role = str(message.get("role") or "user")
416
+ normalized_content = normalize_kop_message_content(message.get("content", ""))
417
+ normalized.append(
418
+ {
419
+ "role": role,
420
+ "content": str(normalized_content.get("content") or ""),
421
+ "display_content": str(normalized_content.get("display_content") or ""),
422
+ "parts": list(normalized_content.get("parts") or []),
423
+ "input_content": list(normalized_content.get("input_content") or []),
424
+ "attachments": list(normalized_content.get("attachments") or []),
425
+ "attachment_results": list(normalized_content.get("attachment_results") or []),
426
+ }
427
+ )
428
+ return normalized
429
+
430
+
431
+ def normalize_responses_input(input_payload: Any) -> List[Dict[str, Any]]:
432
+ if isinstance(input_payload, str):
433
+ return [
434
+ {
435
+ "role": "user",
436
+ "content": input_payload,
437
+ "display_content": input_payload,
438
+ "parts": [{"text": input_payload}] if input_payload else [],
439
+ "input_content": [{"type": "input_text", "text": input_payload}] if input_payload else [],
440
+ "attachments": [],
441
+ "attachment_results": [],
442
+ }
443
+ ]
444
+ if isinstance(input_payload, list):
445
+ return normalize_kop_messages(input_payload)
446
+ return []
@@ -0,0 +1,91 @@
1
+ from __future__ import annotations
2
+
3
+ import re
4
+ from dataclasses import dataclass, field
5
+ from typing import Literal
6
+
7
+ ReasoningPartKind = Literal["thinking", "text"]
8
+
9
+
10
+ @dataclass(frozen=True)
11
+ class ReasoningMarkupPart:
12
+ kind: ReasoningPartKind
13
+ text: str
14
+
15
+
16
+ @dataclass
17
+ class ReasoningMarkupParser:
18
+ """Incrementally split inline <think> markup out of streamed text."""
19
+
20
+ _buffer: str = ""
21
+ _in_think: bool = False
22
+ _pending: list[ReasoningMarkupPart] = field(default_factory=list)
23
+
24
+ def feed(self, chunk: str) -> list[ReasoningMarkupPart]:
25
+ self._buffer += str(chunk or "")
26
+ parts: list[ReasoningMarkupPart] = []
27
+
28
+ while self._buffer:
29
+ tag = "</think>" if self._in_think else "<think>"
30
+ index = self._buffer.find(tag)
31
+ if index >= 0:
32
+ self._append(parts, self._buffer[:index])
33
+ self._buffer = self._buffer[index + len(tag):]
34
+ self._in_think = not self._in_think
35
+ continue
36
+
37
+ prefix_len = self._partial_tag_prefix_len(self._buffer, tag)
38
+ if self._in_think:
39
+ break
40
+ emit_len = len(self._buffer) - prefix_len
41
+ if emit_len <= 0:
42
+ break
43
+ self._append(parts, self._buffer[:emit_len])
44
+ self._buffer = self._buffer[emit_len:]
45
+ break
46
+
47
+ return self._merge(parts)
48
+
49
+ def flush(self) -> list[ReasoningMarkupPart]:
50
+ if not self._buffer:
51
+ return []
52
+ parts: list[ReasoningMarkupPart] = []
53
+ self._append(parts, self._buffer)
54
+ self._buffer = ""
55
+ return self._merge(parts)
56
+
57
+ def _append(self, parts: list[ReasoningMarkupPart], text: str) -> None:
58
+ if not text:
59
+ return
60
+ parts.append(ReasoningMarkupPart("thinking" if self._in_think else "text", text))
61
+
62
+ @staticmethod
63
+ def _merge(parts: list[ReasoningMarkupPart]) -> list[ReasoningMarkupPart]:
64
+ merged: list[ReasoningMarkupPart] = []
65
+ for part in parts:
66
+ if not part.text:
67
+ continue
68
+ if merged and merged[-1].kind == part.kind:
69
+ merged[-1] = ReasoningMarkupPart(part.kind, merged[-1].text + part.text)
70
+ else:
71
+ merged.append(part)
72
+ return merged
73
+
74
+ @staticmethod
75
+ def _partial_tag_prefix_len(value: str, tag: str) -> int:
76
+ max_len = min(len(value), len(tag) - 1)
77
+ for size in range(max_len, 0, -1):
78
+ if tag.startswith(value[-size:]):
79
+ return size
80
+ return 0
81
+
82
+
83
+ def strip_reasoning_markup(text: str) -> str:
84
+ """Remove inline <think> blocks from text used as final answer or title input."""
85
+ value = str(text or "")
86
+ if not value:
87
+ return ""
88
+ value = re.sub(r"<think\b[^>]*>.*?</think>", "", value, flags=re.IGNORECASE | re.DOTALL)
89
+ value = re.sub(r"<think\b[^>]*>.*$", "", value, flags=re.IGNORECASE | re.DOTALL)
90
+ value = re.sub(r"</?think\b[^>]*>", "", value, flags=re.IGNORECASE)
91
+ return value