agentengine-sdk-python 0.8.0__py3-none-any.whl → 0.8.2__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 (494) hide show
  1. {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/METADATA +43 -7
  2. agentengine_sdk_python-0.8.2.dist-info/RECORD +778 -0
  3. {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/WHEEL +1 -1
  4. ksadk/a2a/__init__.py +2 -0
  5. ksadk/a2a/_space_client_events.py +381 -0
  6. ksadk/a2a/bootstrap.py +0 -2
  7. ksadk/a2a/card.py +6 -111
  8. ksadk/a2a/control_plane.py +239 -1
  9. ksadk/a2a/event_adapter.py +156 -64
  10. ksadk/a2a/executor.py +195 -172
  11. ksadk/a2a/routes.py +12 -5
  12. ksadk/a2a/server.py +1 -8
  13. ksadk/a2a/service_env.py +33 -0
  14. ksadk/a2a/space_client.py +43 -349
  15. ksadk/a2a_card.py +101 -0
  16. ksadk/a2ui/core.py +222 -53
  17. ksadk/agui/_agent_helpers.py +243 -0
  18. ksadk/agui/a2ui_projection.py +12 -5
  19. ksadk/agui/agent.py +474 -275
  20. ksadk/agui/config.py +11 -5
  21. ksadk/agui/routes.py +7 -15
  22. ksadk/api/client.py +530 -40
  23. ksadk/api/environment.py +27 -0
  24. ksadk/builders/code_builder.py +352 -53
  25. ksadk/builders/container_builder.py +71 -44
  26. ksadk/builders/framework_requirements.py +2 -1
  27. ksadk/builders/ks3_uploader.py +2 -2
  28. ksadk/builders/managed_runtime_builder.py +60 -28
  29. ksadk/cli/__init__.py +25 -0
  30. ksadk/cli/cmd_a2a.py +18 -31
  31. ksadk/cli/cmd_create.py +13 -26
  32. ksadk/cli/cmd_dashboard.py +15 -1
  33. ksadk/cli/cmd_deploy.py +28 -3
  34. ksadk/cli/cmd_eval.py +443 -0
  35. ksadk/cli/cmd_evalset.py +284 -0
  36. ksadk/cli/cmd_files.py +5 -1
  37. ksadk/cli/cmd_hermes.py +137 -163
  38. ksadk/cli/cmd_invoke.py +28 -38
  39. ksadk/cli/cmd_launch.py +12 -0
  40. ksadk/cli/cmd_managed_runtime.py +95 -0
  41. ksadk/cli/cmd_observe.py +85 -0
  42. ksadk/cli/cmd_openclaw.py +85 -479
  43. ksadk/cli/cmd_replay.py +28 -4
  44. ksadk/cli/cmd_run.py +29 -67
  45. ksadk/cli/cmd_studio.py +201 -0
  46. ksadk/cli/cmd_web.py +15 -6
  47. ksadk/cli/dry_run.py +2 -1
  48. ksadk/cli/env_options.py +83 -0
  49. ksadk/cli/global_options.py +3 -1
  50. ksadk/cli/hermes_env.py +151 -0
  51. ksadk/cli/invoke_payload.py +49 -0
  52. ksadk/cli/network_options.py +7 -5
  53. ksadk/cli/openclaw_env.py +458 -0
  54. ksadk/cli/runtime_bootstrap.py +51 -0
  55. ksadk/cli/ui.py +6 -0
  56. ksadk/cli/workflow_common.py +5 -5
  57. ksadk/codex/__init__.py +3 -3
  58. ksadk/codex/client.py +833 -49
  59. ksadk/codex/phase.py +1 -1
  60. ksadk/codex/runtime.py +720 -127
  61. ksadk/common/kop_client.py +232 -0
  62. ksadk/configs/__init__.py +1 -3
  63. ksadk/configs/env_registry.py +244 -45
  64. ksadk/configs/env_registry_pcm.py +181 -0
  65. ksadk/configs/env_var_spec.py +18 -0
  66. ksadk/configs/global_config.py +6 -1
  67. ksadk/configs/settings.py +5 -108
  68. ksadk/context_engine/__init__.py +98 -0
  69. ksadk/context_engine/assembler.py +176 -0
  70. ksadk/context_engine/baseline.py +419 -0
  71. ksadk/context_engine/cache_observability.py +228 -0
  72. ksadk/context_engine/capabilities.py +443 -0
  73. ksadk/context_engine/contributors.py +344 -0
  74. ksadk/context_engine/hosted_pipeline.py +417 -0
  75. ksadk/context_engine/models.py +117 -0
  76. ksadk/context_engine/planner.py +698 -0
  77. ksadk/context_engine/policies.py +319 -0
  78. ksadk/context_engine/projection.py +31 -0
  79. ksadk/context_engine/shadow_plan.py +266 -0
  80. ksadk/context_engine/tokenizer.py +164 -0
  81. ksadk/conversations/__init__.py +85 -94
  82. ksadk/conversations/context.py +126 -6
  83. ksadk/conversations/message_projection.py +292 -28
  84. ksadk/conversations/model_context.py +49 -3
  85. ksadk/conversations/runtime_compaction.py +207 -5
  86. ksadk/conversations/runtime_input.py +193 -3
  87. ksadk/conversations/runtime_invocation.py +81 -3
  88. ksadk/conversations/runtime_observability.py +157 -4
  89. ksadk/conversations/runtime_payloads.py +42 -0
  90. ksadk/conversations/runtime_preparation.py +280 -2
  91. ksadk/conversations/runtime_resume.py +71 -32
  92. ksadk/conversations/runtime_stream_events.py +94 -9
  93. ksadk/conversations/runtime_streaming.py +175 -22
  94. ksadk/conversations/semantic_summary.py +311 -1
  95. ksadk/conversations/session_lock.py +51 -0
  96. ksadk/deployment/env_forward.py +72 -0
  97. ksadk/deployment/managed_runtime.py +38 -0
  98. ksadk/deployment/manager.py +24 -8
  99. ksadk/deployment/providers/serverless.py +228 -92
  100. ksadk/evaluation/__init__.py +116 -0
  101. ksadk/evaluation/a2a_adapter.py +452 -0
  102. ksadk/evaluation/adapters.py +67 -0
  103. ksadk/evaluation/agent_eval_client.py +395 -0
  104. ksadk/evaluation/cloud_binding.py +80 -0
  105. ksadk/evaluation/cloud_converter.py +194 -0
  106. ksadk/evaluation/cloud_service.py +199 -0
  107. ksadk/evaluation/contracts.py +478 -0
  108. ksadk/evaluation/evalset.py +351 -0
  109. ksadk/evaluation/evaluators.py +627 -0
  110. ksadk/evaluation/evidence.py +258 -0
  111. ksadk/evaluation/executor.py +143 -0
  112. ksadk/evaluation/local_adapter.py +550 -0
  113. ksadk/evaluation/service_env.py +27 -0
  114. ksadk/evaluation/storage.py +68 -0
  115. ksadk/evaluation/studio_build_adapter.py +253 -0
  116. ksadk/evaluation/target.py +82 -0
  117. ksadk/events/__init__.py +13 -13
  118. ksadk/events/_v1_compat/__init__.py +1 -0
  119. ksadk/events/_v1_compat/models.py +299 -0
  120. ksadk/events/_v1_compat/parser.py +247 -0
  121. ksadk/events/_v1_compat/projection.py +753 -0
  122. ksadk/events/adapters/__init__.py +34 -0
  123. ksadk/events/adapters/_a2a_snapshot.py +622 -0
  124. ksadk/events/adapters/_a2a_support.py +275 -0
  125. ksadk/events/adapters/_codex_interactions.py +375 -0
  126. ksadk/events/adapters/_codex_items.py +801 -0
  127. ksadk/events/adapters/_codex_validators.py +311 -0
  128. ksadk/events/adapters/_langgraph_support.py +785 -0
  129. ksadk/events/adapters/a2a.py +841 -0
  130. ksadk/events/adapters/adk.py +503 -0
  131. ksadk/events/adapters/codex.py +717 -0
  132. ksadk/events/adapters/langgraph.py +745 -0
  133. ksadk/events/canonical.py +440 -0
  134. ksadk/events/canonical_replay.py +497 -0
  135. ksadk/events/canonical_store.py +468 -0
  136. ksadk/events/cold_recovery.py +257 -0
  137. ksadk/events/content.py +89 -0
  138. ksadk/events/identity.py +86 -0
  139. ksadk/events/pipeline.py +455 -0
  140. ksadk/events/projections.py +66 -0
  141. ksadk/events/reducer.py +661 -0
  142. ksadk/events/replay.py +3 -36
  143. ksadk/events/runtime_event.py +20 -256
  144. ksadk/events/session_event.py +324 -0
  145. ksadk/events/store.py +3 -316
  146. ksadk/events/v1_compat.py +41 -0
  147. ksadk/harness/__init__.py +3 -2
  148. ksadk/harness/app.py +114 -123
  149. ksadk/harness/config.py +1 -1
  150. ksadk/harness/runtime.py +467 -0
  151. ksadk/hermes_terminal.py +5 -0
  152. ksadk/identity/resolver.py +4 -3
  153. ksadk/interaction/__init__.py +28 -0
  154. ksadk/interaction/contracts.py +136 -0
  155. ksadk/interaction/ledger.py +189 -0
  156. ksadk/interaction/provider.py +122 -0
  157. ksadk/interaction/providers/__init__.py +52 -0
  158. ksadk/interaction/providers/adk.py +40 -0
  159. ksadk/interaction/providers/codex.py +94 -0
  160. ksadk/interaction/providers/langgraph.py +58 -0
  161. ksadk/kernel/__init__.py +117 -0
  162. ksadk/kernel/authorization.py +258 -0
  163. ksadk/kernel/bootstrap.py +1074 -0
  164. ksadk/kernel/contract_fingerprints.py +61 -0
  165. ksadk/kernel/contracts.py +362 -0
  166. ksadk/kernel/control.py +219 -0
  167. ksadk/kernel/errors.py +79 -0
  168. ksadk/kernel/ingress.py +1102 -0
  169. ksadk/kernel/mapping.py +111 -0
  170. ksadk/kernel/memory_store.py +1133 -0
  171. ksadk/kernel/postgres_store.py +1756 -0
  172. ksadk/kernel/recovery.py +452 -0
  173. ksadk/kernel/runtime_identity.py +103 -0
  174. ksadk/kernel/sql/001_agent_kernel.sql +120 -0
  175. ksadk/kernel/sqlite_store.py +1410 -0
  176. ksadk/kernel/state.py +145 -0
  177. ksadk/kernel/store.py +232 -0
  178. ksadk/kernel/worker.py +953 -0
  179. ksadk/knowledge_base/client.py +22 -4
  180. ksadk/knowledge_base/service.py +32 -5
  181. ksadk/managed_a2a_card.py +160 -0
  182. ksadk/managed_runtime.py +16 -9
  183. ksadk/memory/__init__.py +61 -0
  184. ksadk/memory/adk/backends/base_ltm_backend.py +96 -1
  185. ksadk/memory/adk/backends/http_ltm_backend.py +14 -5
  186. ksadk/memory/adk/backends/inmemory_ltm_backend.py +136 -3
  187. ksadk/memory/adk/backends/sdk_ltm_backend.py +394 -5
  188. ksadk/memory/adk/backends/sqlite_ltm_backend.py +95 -0
  189. ksadk/memory/adk/long_term_memory.py +3 -2
  190. ksadk/memory/coordinator.py +461 -0
  191. ksadk/memory/events.py +202 -0
  192. ksadk/memory/extraction.py +228 -0
  193. ksadk/memory/ltm_backend_factory.py +16 -3
  194. ksadk/memory/models.py +316 -0
  195. ksadk/memory/policy.py +215 -0
  196. ksadk/memory/provider.py +47 -0
  197. ksadk/memory/provider_adapter.py +159 -0
  198. ksadk/memory/provider_resolver.py +71 -0
  199. ksadk/memory/providers/__init__.py +5 -0
  200. ksadk/memory/providers/local_sqlite.py +490 -0
  201. ksadk/memory/resolved_policy.py +145 -0
  202. ksadk/memory/service.py +198 -8
  203. ksadk/memory/tool.py +4 -0
  204. ksadk/model_proxy/bootstrap.py +16 -9
  205. ksadk/model_proxy/config.py +22 -1
  206. ksadk/model_proxy/detect.py +202 -9
  207. ksadk/model_proxy/namespace.py +67 -15
  208. ksadk/model_proxy/server.py +168 -6
  209. ksadk/model_proxy/transform.py +105 -3
  210. ksadk/observability/__init__.py +25 -0
  211. ksadk/observability/session_log.py +420 -0
  212. ksadk/observability/trajectory.py +105 -0
  213. ksadk/prompts/__init__.py +71 -0
  214. ksadk/prompts/compiler.py +215 -0
  215. ksadk/prompts/models.py +82 -0
  216. ksadk/prompts/projection.py +89 -0
  217. ksadk/prompts/resolved.py +137 -0
  218. ksadk/prompts/sources.py +233 -0
  219. ksadk/runners/_langgraph_runner_streams.py +822 -0
  220. ksadk/runners/adk_runner.py +14 -31
  221. ksadk/runners/base_runner.py +44 -3
  222. ksadk/runners/factory.py +3 -3
  223. ksadk/runners/langgraph_runner.py +252 -433
  224. ksadk/runners/utils/__init__.py +0 -10
  225. ksadk/runners/utils/loader.py +16 -0
  226. ksadk/runtime/__init__.py +67 -41
  227. ksadk/runtime/_runner_adapter/__init__.py +1 -0
  228. ksadk/runtime/_runner_adapter/stream_mapping.py +788 -0
  229. ksadk/runtime/adapter.py +199 -16
  230. ksadk/runtime/conversation_execution.py +687 -0
  231. ksadk/runtime/executor.py +392 -0
  232. ksadk/runtime/factory.py +342 -0
  233. ksadk/runtime/framework_adapters.py +6 -12
  234. ksadk/runtime/hosted_finalizer.py +268 -0
  235. ksadk/runtime/launch.py +61 -0
  236. ksadk/runtime/preprocessing.py +49 -14
  237. ksadk/runtime/runner_adapter.py +330 -391
  238. ksadk/runtime/runner_loading.py +36 -0
  239. ksadk/runtime/usage.py +33 -0
  240. ksadk/sandbox/backends/e2b.py +36 -3
  241. ksadk/server/__init__.py +39 -4
  242. ksadk/server/app.py +18 -492
  243. ksadk/server/composition.py +36 -2
  244. ksadk/server/factory.py +210 -149
  245. ksadk/server/routes/common.py +15 -46
  246. ksadk/server/routes/control.py +13 -9
  247. ksadk/server/routes/kernel_ingress.py +258 -0
  248. ksadk/server/routes/misc.py +10 -33
  249. ksadk/server/routes/models.py +14 -6
  250. ksadk/server/routes/openai_compat.py +129 -27
  251. ksadk/server/routes/projection.py +84 -16
  252. ksadk/server/routes/run.py +347 -460
  253. ksadk/server/routes/sessions.py +37 -40
  254. ksadk/server/routes/streaming.py +52 -7
  255. ksadk/server/routes/workspace.py +54 -21
  256. ksadk/server/static/assets/{ArtifactsPanel-Cjnqt-8W.js → ArtifactsPanel-DSU1sWD_.js} +1 -1
  257. ksadk/server/static/assets/{CodeBlock-BqyqZfuB.js → CodeBlock-DOH6MVcn.js} +4 -4
  258. ksadk/server/static/assets/{MathMessageMarkdown-BpH7jiFM.js → MathMessageMarkdown-BL8my1R2.js} +4 -4
  259. ksadk/server/static/assets/MathMessageMarkdown-BorAY7qD.css +1 -0
  260. ksadk/server/static/assets/MermaidBlock-Dz4IP-Tx.js +312 -0
  261. ksadk/server/static/assets/NativeTerminalPanel-DUrK0JpZ.js +1 -0
  262. ksadk/server/static/assets/abnfDiagram-VCTEODGH-g20pFzNV.js +1 -0
  263. ksadk/server/static/assets/arc-C4FzinUA.js +1 -0
  264. ksadk/server/static/assets/architecture-7GRP2DOG-DjKratdf.js +1 -0
  265. ksadk/server/static/assets/architectureDiagram-5GKGNRK7-DpIqL5h4.js +36 -0
  266. ksadk/server/static/assets/blockDiagram-NRAW4CY4-BjkljTNz.js +129 -0
  267. ksadk/server/static/assets/c4Diagram-UCG6FXSJ-Dk_ieq2X.js +38 -0
  268. ksadk/server/static/assets/channel-4cQHKtx1.js +1 -0
  269. ksadk/server/static/assets/chunk-2Q5K7J3B-DmgWkESh.js +1 -0
  270. ksadk/server/static/assets/{chunk-FMBD7UC4-BGhvzDYt.js → chunk-5VM5RSS4-BVHAchFb.js} +1 -1
  271. ksadk/server/static/assets/{chunk-ND2GUHAM-D98vPd-E.js → chunk-F27PBJKO-C-ipQzuS.js} +1 -1
  272. ksadk/server/static/assets/chunk-G27WJ6UU-C2EyJbIK.js +231 -0
  273. ksadk/server/static/assets/{chunk-4BX2VUAB-CsWIQRhc.js → chunk-JWPE2WC7-vYvVJb_M.js} +1 -1
  274. ksadk/server/static/assets/chunk-LCL6LL3I-BcI6ysPT.js +206 -0
  275. ksadk/server/static/assets/chunk-POPQ4Y6H-C030x_Z1.js +1 -0
  276. ksadk/server/static/assets/chunk-RHFEMEQ7-yyGpsz4n.js +168 -0
  277. ksadk/server/static/assets/chunk-SVP7TREG-BLTlmMU7.js +88 -0
  278. ksadk/server/static/assets/chunk-XXDRQBXY-C_32ArgP.js +1 -0
  279. ksadk/server/static/assets/classDiagram-DTDB5LWJ-DLFd9Xi0.js +1 -0
  280. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-DLFd9Xi0.js +1 -0
  281. ksadk/server/static/assets/{cose-bilkent-S5V4N54A-CX3yotHq.js → cose-bilkent-JH36ORCC-9YQYwdl0.js} +1 -1
  282. ksadk/server/static/assets/cynefin-OW5HDTMX-DjEM48Qp.js +1 -0
  283. ksadk/server/static/assets/cynefinDiagram-5FMLGOSQ-ErLF5N13.js +62 -0
  284. ksadk/server/static/assets/cytoscape.esm-CyCl8rPi.js +321 -0
  285. ksadk/server/static/assets/dagre-3AP2YEHR-DFiQF-6f.js +4 -0
  286. ksadk/server/static/assets/dagre-BuhGnRI1.js +1 -0
  287. ksadk/server/static/assets/diagram-S7CK7UJ4-Bt1v8-GC.js +30 -0
  288. ksadk/server/static/assets/diagram-UQ7AKVKN-DSCxJdBK.js +41 -0
  289. ksadk/server/static/assets/diagram-VSXAHHWV-DHfYwp_9.js +3 -0
  290. ksadk/server/static/assets/diagram-VX7I27RA-DdzD-4Le.js +24 -0
  291. ksadk/server/static/assets/diagram-Z3DM3KII-Du-nAJ9F.js +24 -0
  292. ksadk/server/static/assets/{dist-D82mtD2s.js → dist-8hqcx0sU.js} +1 -1
  293. ksadk/server/static/assets/dist-B7seoj3d.js +1 -0
  294. ksadk/server/static/assets/{dist-DHn6nBzr.js → dist-BE7bu-DL.js} +1 -1
  295. ksadk/server/static/assets/{dist-eoW6tZXA.js → dist-BVDffZ0U.js} +1 -1
  296. ksadk/server/static/assets/{dist-C2xjE7cO.js → dist-BX8z72IC.js} +1 -1
  297. ksadk/server/static/assets/{dist-CgF3fj15.js → dist-Bf2M8m3N.js} +1 -1
  298. ksadk/server/static/assets/{dist-Bs-jQcRX.js → dist-BjU6y-A2.js} +1 -1
  299. ksadk/server/static/assets/{dist-Djgl2wVZ.js → dist-BytlxIDT.js} +1 -1
  300. ksadk/server/static/assets/{dist-CVQRZjPu.js → dist-CSh_DE14.js} +1 -1
  301. ksadk/server/static/assets/{dist-6CVKuTAe.js → dist-CXYYBw3_.js} +1 -1
  302. ksadk/server/static/assets/{dist-DlzCRy0S.js → dist-C_wsv-Qd.js} +1 -1
  303. ksadk/server/static/assets/{dist-DF06ORQo.js → dist-ClxGviKw.js} +1 -1
  304. ksadk/server/static/assets/{dist-Cf23NY4L.js → dist-CttYUqzS.js} +1 -1
  305. ksadk/server/static/assets/{dist-ivOya1LD.js → dist-DNp6rLRA.js} +1 -1
  306. ksadk/server/static/assets/{dist-BibcG1V9.js → dist-DUX-id_F.js} +1 -1
  307. ksadk/server/static/assets/{dist-BUHRxvDG.js → dist-DmldrHd_.js} +1 -1
  308. ksadk/server/static/assets/{dist-BZ9n9AjO.js → dist-DnfXs8Vn.js} +2 -2
  309. ksadk/server/static/assets/{dist-DqNnNFrw.js → dist-Dq9gLD7L.js} +1 -1
  310. ksadk/server/static/assets/{dist-CGcp2ex8.js → dist-W-TIVntx.js} +1 -1
  311. ksadk/server/static/assets/{dist-Cwt7koer.js → dist-dDdADKFA.js} +1 -1
  312. ksadk/server/static/assets/{dist-C7-3jInC.js → dist-dydu68Fl.js} +1 -1
  313. ksadk/server/static/assets/{dist-C99THtIA.js → dist-ngtN0DJB.js} +1 -1
  314. ksadk/server/static/assets/ebnfDiagram-PWID7BFC-Da9C9NO1.js +1 -0
  315. ksadk/server/static/assets/erDiagram-SSCWMZ5O-EAGqqR79.js +99 -0
  316. ksadk/server/static/assets/eventmodeling-NTZA5JFV-CMgMaJrC.js +1 -0
  317. ksadk/server/static/assets/flowDiagram-A5DVABFB-BBKL0x3P.js +1 -0
  318. ksadk/server/static/assets/ganttDiagram-EL5Y4UJY-DqJsKb59.js +292 -0
  319. ksadk/server/static/assets/gitGraph-4MIJSDKK-Dw63mrhw.js +1 -0
  320. ksadk/server/static/assets/gitGraphDiagram-WWUBYQGX-B6g4dtDi.js +106 -0
  321. ksadk/server/static/assets/index-8ipRcQ-M.js +240 -0
  322. ksadk/server/static/assets/index-ByFCqjlh.css +2 -0
  323. ksadk/server/static/assets/info-A6RAGUB7-B6iAblII.js +1 -0
  324. ksadk/server/static/assets/infoDiagram-RXCK75RN-Djm_nbd5.js +2 -0
  325. ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-DLOHGvWw.js → ishikawaDiagram-5VMMS53U-DWya9SG2.js} +6 -6
  326. ksadk/server/static/assets/{journeyDiagram-JHISSGLW-BIzKeejT.js → journeyDiagram-EYS64GPL-DutxhSNI.js} +6 -6
  327. ksadk/server/static/assets/{kanban-definition-UN3LZRKU-BWHoFSw2.js → kanban-definition-3QL26DDD-DJdOF8Fm.js} +10 -10
  328. ksadk/server/static/assets/katex-vFWytM5c.js +257 -0
  329. ksadk/server/static/assets/{linear-CvMBw9cA.js → linear-BHjG8b-J.js} +1 -1
  330. ksadk/server/static/assets/mermaid-parser.core-KGSy4jWT.js +166 -0
  331. ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-CSAQxEAe.js → mindmap-definition-FBJOCRG2-9-HC88D4.js} +29 -29
  332. ksadk/server/static/assets/packet-AYTQ26CC-BOYAipuq.js +1 -0
  333. ksadk/server/static/assets/pegDiagram-XKGWAZYB-DrEZd4fD.js +1 -0
  334. ksadk/server/static/assets/pie-WAS4IAKB-Ctq0Kbku.js +1 -0
  335. ksadk/server/static/assets/pieDiagram-E7YTZNPT-DpjqOFFp.js +39 -0
  336. ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-CxIR4JXI.js → quadrantDiagram-AXDQQJYC-BiNhgOXX.js} +6 -6
  337. ksadk/server/static/assets/radar-RG4KPBEZ-DN0-ul_0.js +1 -0
  338. ksadk/server/static/assets/railroad-74A4TZTK-C6cC_to0.js +1 -0
  339. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BimjIuRc.js +1 -0
  340. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-CvY65ABq.js +1 -0
  341. ksadk/server/static/assets/railroad-peg-WCYAUIDC-D72Iq_Tv.js +1 -0
  342. ksadk/server/static/assets/railroadDiagram-O6MQD6OU-_Y3Ojg6G.js +1 -0
  343. ksadk/server/static/assets/requirementDiagram-EFPCY7ZU-DeCFdg9K.js +84 -0
  344. ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-DpGa6EAV.js → sankeyDiagram-P5KCCOFB-CPH75rhw.js} +7 -7
  345. ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-NTKNGGe5.js → sequenceDiagram-WJ2MYXX4-OEpQQdr4.js} +10 -10
  346. ksadk/server/static/assets/sizeCapture-X5ZJPWSS-heUErzhI.js +1 -0
  347. ksadk/server/static/assets/stateDiagram-HBIQ2CUA-DvA3jSMB.js +1 -0
  348. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BgQY03nz.js +1 -0
  349. ksadk/server/static/assets/swimlanes-XN3QIQJK-CR-dfN_t.js +1 -0
  350. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-DLVw3q5Q.js +8 -0
  351. ksadk/server/static/assets/{timeline-definition-PNZ67QCA-jqoYs3jQ.js → timeline-definition-24CTP7MA-DAVJf1TX.js} +7 -7
  352. ksadk/server/static/assets/treeView-Q6P3EWNA-BMpO0wsB.js +1 -0
  353. ksadk/server/static/assets/treemap-WGGIJYW6-Et0aqzU3.js +1 -0
  354. ksadk/server/static/assets/vennDiagram-4TSXK5OY-DwM8eDkh.js +34 -0
  355. ksadk/server/static/assets/wardley-WFR3VGLG-CbY0mhpl.js +1 -0
  356. ksadk/server/static/assets/wardleyDiagram-VM6X3IG4-DZL-Zz2t.js +78 -0
  357. ksadk/server/static/assets/xychartDiagram-S5SC5T6Z-Dy6Yh_hu.js +7 -0
  358. ksadk/server/static/index.html +2 -2
  359. ksadk/sessions/__init__.py +26 -9
  360. ksadk/sessions/_local_service_sync.py +688 -0
  361. ksadk/sessions/_local_tables.py +21 -0
  362. ksadk/sessions/_postgres_schema.py +305 -0
  363. ksadk/sessions/_postgres_tables.py +15 -0
  364. ksadk/sessions/base.py +80 -1
  365. ksadk/sessions/in_memory.py +53 -2
  366. ksadk/sessions/local_service.py +63 -604
  367. ksadk/sessions/postgres_service.py +58 -148
  368. ksadk/sessions/resilient.py +35 -1
  369. ksadk/skills/runtime/backends/e2b.py +1 -1
  370. ksadk/skills/service_client.py +13 -3
  371. ksadk/studio/__init__.py +5 -0
  372. ksadk/studio/agent_avatar_assets.py +120 -0
  373. ksadk/studio/agent_lifecycle.py +51 -0
  374. ksadk/studio/api.py +1598 -0
  375. ksadk/studio/api_catalog_routes.py +324 -0
  376. ksadk/studio/api_contracts.py +286 -0
  377. ksadk/studio/api_helpers.py +132 -0
  378. ksadk/studio/api_memory_routes.py +82 -0
  379. ksadk/studio/authoring.py +749 -0
  380. ksadk/studio/authoring_coordinator.py +1017 -0
  381. ksadk/studio/builder.py +397 -0
  382. ksadk/studio/capabilities.py +368 -0
  383. ksadk/studio/cloud.py +2099 -0
  384. ksadk/studio/codex_agent_service.py +694 -0
  385. ksadk/studio/codex_authoring.py +469 -0
  386. ksadk/studio/codex_builder.py +437 -0
  387. ksadk/studio/codex_manifest.py +307 -0
  388. ksadk/studio/codex_run.py +395 -0
  389. ksadk/studio/compiler.py +190 -0
  390. ksadk/studio/contracts.py +755 -0
  391. ksadk/studio/errors.py +47 -0
  392. ksadk/studio/event_store.py +214 -0
  393. ksadk/studio/framework_run.py +342 -0
  394. ksadk/studio/hosted_kernel.py +317 -0
  395. ksadk/studio/identifiers.py +33 -0
  396. ksadk/studio/manifest_resolver.py +131 -0
  397. ksadk/studio/mcp_runtime.py +229 -0
  398. ksadk/studio/model_client.py +629 -0
  399. ksadk/studio/model_profile_service.py +214 -0
  400. ksadk/studio/operations.py +275 -0
  401. ksadk/studio/otel_trace.py +1060 -0
  402. ksadk/studio/pagination.py +182 -0
  403. ksadk/studio/pcm_memory.py +85 -0
  404. ksadk/studio/python_tool_inspection.py +183 -0
  405. ksadk/studio/repository.py +327 -0
  406. ksadk/studio/resource_catalog.py +1260 -0
  407. ksadk/studio/run_service.py +1133 -0
  408. ksadk/studio/runtime_catalog.py +74 -0
  409. ksadk/studio/runtime_source.py +365 -0
  410. ksadk/studio/service.py +2249 -0
  411. ksadk/studio/shared_web.py +1004 -0
  412. ksadk/studio/skill_discovery.py +628 -0
  413. ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +3 -0
  414. ksadk/studio/static/assets/index-BLpcdrgW.css +1 -0
  415. ksadk/studio/static/assets/index-CYekR2Xv.js +260 -0
  416. ksadk/studio/static/assets/react-vendor-BNmTiJ-I.js +9 -0
  417. ksadk/studio/static/assets/rolldown-runtime-hePW80VL.js +1 -0
  418. ksadk/studio/static/index.html +15 -0
  419. ksadk/studio/templates.py +722 -0
  420. ksadk/studio/validator.py +265 -0
  421. ksadk/studio/workspace.py +135 -0
  422. ksadk/tools/gateway.py +9 -0
  423. ksadk/toolsets/__init__.py +27 -1
  424. ksadk/toolsets/a2a.py +426 -0
  425. ksadk/tracing/__init__.py +19 -21
  426. ksadk/tracing/setup.py +317 -403
  427. ksadk/tracing/span_utils.py +0 -44
  428. ksadk/version.py +1 -1
  429. ksadk_runtime_common/memory_backend/registry.py +56 -56
  430. ksadk_runtime_common/schemas/runtime_event_v1.json +37 -0
  431. ksadk_runtime_common/schemas/runtime_event_v2.json +271 -0
  432. ksadk_runtime_common/workspace_files/router.py +8 -2
  433. agentengine_sdk_python-0.8.0.dist-info/RECORD +0 -578
  434. ksadk/a2a/card_builder.py +0 -64
  435. ksadk/a2a/client.py +0 -309
  436. ksadk/events/parser.py +0 -191
  437. ksadk/harness/runner.py +0 -211
  438. ksadk/runners/codex_runner.py +0 -132
  439. ksadk/runners/utils/langfuse.py +0 -230
  440. ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +0 -1
  441. ksadk/server/static/assets/MermaidBlock-DWuxETaJ.js +0 -303
  442. ksadk/server/static/assets/NativeTerminalPanel-MDTopWMO.js +0 -1
  443. ksadk/server/static/assets/arc-CFKwSk_B.js +0 -1
  444. ksadk/server/static/assets/architecture-7EHR7CIX-CynqOWjZ.js +0 -1
  445. ksadk/server/static/assets/architectureDiagram-3BPJPVTR-Dej8jX8c.js +0 -36
  446. ksadk/server/static/assets/blockDiagram-GPEHLZMM-1F64jqvy.js +0 -132
  447. ksadk/server/static/assets/c4Diagram-AAUBKEIU-9q7AUAKb.js +0 -10
  448. ksadk/server/static/assets/channel-iUGv2N24.js +0 -1
  449. ksadk/server/static/assets/chunk-2J33WTMH-6qgwJm7Q.js +0 -1
  450. ksadk/server/static/assets/chunk-55IACEB6-BK8paA20.js +0 -1
  451. ksadk/server/static/assets/chunk-727SXJPM-B-JEhy7h.js +0 -206
  452. ksadk/server/static/assets/chunk-AQP2D5EJ-DYBvMHAa.js +0 -231
  453. ksadk/server/static/assets/chunk-QZHKN3VN-YQIEXeF6.js +0 -1
  454. ksadk/server/static/assets/classDiagram-4FO5ZUOK-CDAUuoXK.js +0 -1
  455. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-CDAUuoXK.js +0 -1
  456. ksadk/server/static/assets/cytoscape.esm-DelgaX4f.js +0 -321
  457. ksadk/server/static/assets/dagre-BM42HDAG-C7TguAWo.js +0 -4
  458. ksadk/server/static/assets/dagre-Bx709z4p.js +0 -1
  459. ksadk/server/static/assets/diagram-2AECGRRQ-Dd17_kws.js +0 -43
  460. ksadk/server/static/assets/diagram-5GNKFQAL-DVIClIil.js +0 -10
  461. ksadk/server/static/assets/diagram-KO2AKTUF-Df_3gYQa.js +0 -3
  462. ksadk/server/static/assets/diagram-LMA3HP47-BhLk6ZtA.js +0 -24
  463. ksadk/server/static/assets/diagram-OG6HWLK6-D4GNGvuu.js +0 -24
  464. ksadk/server/static/assets/dist-DyvYLMW9.js +0 -1
  465. ksadk/server/static/assets/erDiagram-TEJ5UH35-CnfRcY2M.js +0 -85
  466. ksadk/server/static/assets/eventmodeling-FCH6USID-ChYO-ijM.js +0 -1
  467. ksadk/server/static/assets/flowDiagram-I6XJVG4X-DGaJjGNJ.js +0 -162
  468. ksadk/server/static/assets/ganttDiagram-6RSMTGT7-DpCoB2g9.js +0 -292
  469. ksadk/server/static/assets/gitGraph-WXDBUCRP-BN_0Fk-j.js +0 -1
  470. ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-9IKVFBVT.js +0 -106
  471. ksadk/server/static/assets/graphlib-B8gBHxth.js +0 -1
  472. ksadk/server/static/assets/index-QSwCHuB8.js +0 -177
  473. ksadk/server/static/assets/index-jOPmTOZH.css +0 -2
  474. ksadk/server/static/assets/info-J43DQDTF-Cp6o3vId.js +0 -1
  475. ksadk/server/static/assets/infoDiagram-5YYISTIA-CYIIsb8y.js +0 -2
  476. ksadk/server/static/assets/katex-DATssjp1.js +0 -265
  477. ksadk/server/static/assets/mermaid-parser.core-mGAcEwcq.js +0 -161
  478. ksadk/server/static/assets/packet-YPE3B663-wQzct3cT.js +0 -1
  479. ksadk/server/static/assets/pie-LRSECV5Y-BgTQiv-9.js +0 -1
  480. ksadk/server/static/assets/pieDiagram-4H26LBE5-By-ra07M.js +0 -30
  481. ksadk/server/static/assets/radar-GUYGQ44K-BIq5fXsn.js +0 -1
  482. ksadk/server/static/assets/requirementDiagram-4Y6WPE33-DpW90iu3.js +0 -84
  483. ksadk/server/static/assets/stateDiagram-AJRCARHV-DGpd9yFG.js +0 -1
  484. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-B3o579IQ.js +0 -1
  485. ksadk/server/static/assets/treeView-BLDUP644-Dqi-E0EM.js +0 -1
  486. ksadk/server/static/assets/treemap-LRROVOQU-ClQP9CJ9.js +0 -1
  487. ksadk/server/static/assets/vennDiagram-CIIHVFJN-l3Z7-wbP.js +0 -34
  488. ksadk/server/static/assets/wardley-L42UT6IY-8XLvnNIs.js +0 -1
  489. ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-BR54GPmr.js +0 -78
  490. ksadk/server/static/assets/xychartDiagram-2RQKCTM6-SkiH8GsK.js +0 -7
  491. ksadk/tracing/exporters/langfuse_exporter.py +0 -460
  492. {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/entry_points.txt +0 -0
  493. {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/licenses/LICENSE +0 -0
  494. {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,722 @@
1
+ """Agent templates and deterministic composition for Studio authoring."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ from collections.abc import Iterable
7
+
8
+ import yaml # type: ignore[import-untyped]
9
+
10
+ from ksadk.studio.contracts import (
11
+ AgentBehaviorDesign,
12
+ AgentBindings,
13
+ AgentSpec,
14
+ AgentTemplateComposeRequest,
15
+ AgentTemplateComposition,
16
+ AgentTemplateRecommendation,
17
+ CapabilityBinding,
18
+ ContextSpec,
19
+ ExecutionSpec,
20
+ Instructions,
21
+ ModelParameters,
22
+ ResourceDescriptor,
23
+ )
24
+ from ksadk.studio.errors import StudioError
25
+ from ksadk.studio.resource_catalog import LocalResourceCatalog
26
+ from ksadk.studio.workspace import Workspace
27
+
28
+ RESEARCH_SKILL_NAME = "deep-research-methodology"
29
+ RESEARCH_SKILL_VERSION = "1.0.0"
30
+
31
+
32
+ def _explicit_boundaries(goal: str) -> list[str]:
33
+ clauses = [item.strip() for item in re.split(r"[。;;\n]+", goal) if item.strip()]
34
+ boundary_markers = (
35
+ "必须",
36
+ "不得",
37
+ "不要",
38
+ "禁止",
39
+ "仅限",
40
+ "只能",
41
+ "确认",
42
+ "审批",
43
+ "敏感",
44
+ "隐私",
45
+ )
46
+ return [
47
+ clause
48
+ for clause in clauses
49
+ if any(marker in clause for marker in boundary_markers)
50
+ ][:4]
51
+
52
+
53
+ def _blank_behavior_design(goal: str, policy_template: str) -> AgentBehaviorDesign:
54
+ primary_goal = next(
55
+ (item.strip() for item in re.split(r"[。;;\n]+", goal) if item.strip()),
56
+ goal,
57
+ )
58
+ explicit = _explicit_boundaries(goal)
59
+ safety = list(explicit)
60
+ policy_boundary = (
61
+ "执行外部写入、生产变更或其他高风险操作前,说明影响并取得用户确认。"
62
+ if policy_template == "strict"
63
+ else "调用工具和外部服务时遵守当前权限策略,不宣称未实际完成的操作。"
64
+ )
65
+ if policy_boundary not in safety:
66
+ safety.append(policy_boundary)
67
+ return AgentBehaviorDesign(
68
+ role=f"以“{primary_goal[:80]}”为核心职责的智能助手",
69
+ objective=goal,
70
+ operating_principles=[
71
+ "优先理解当前目标、已知事实和成功标准,不把假设表述为事实。",
72
+ "信息不足或存在关键歧义时,先提出最少必要问题。",
73
+ "只在确有需要时调用已绑定能力,并检查工具输入与返回结果。",
74
+ ],
75
+ workflow=[
76
+ "识别本次请求、约束条件和期望结果",
77
+ "检查信息是否充分并澄清关键缺口",
78
+ "制定并执行必要步骤,使用可用 Tool、MCP 或 Skill",
79
+ "核对结果、说明限制并按约定结构交付",
80
+ ],
81
+ explicit_boundaries=explicit,
82
+ safety_boundaries=safety,
83
+ output_expectations=[
84
+ "回答准确、清晰、可执行,并区分事实、判断和建议。",
85
+ "涉及风险、假设或未完成事项时明确说明,不伪造执行结果。",
86
+ ],
87
+ source_notes=[
88
+ "用户输入:核心目标和明确提出的边界",
89
+ "模板补充:通用执行流程、澄清原则和交付要求",
90
+ "平台策略:工具权限与高风险操作边界",
91
+ ],
92
+ )
93
+
94
+
95
+ def _blank_system_prompt(design: AgentBehaviorDesign) -> str:
96
+ principles = "\n".join(f"- {item}" for item in design.operating_principles)
97
+ boundaries = "\n".join(f"- {item}" for item in design.safety_boundaries)
98
+ outputs = "\n".join(f"- {item}" for item in design.output_expectations)
99
+ return (
100
+ f"# 角色\n{design.role}\n\n"
101
+ f"# 核心目标\n{design.objective}\n\n"
102
+ f"# 工作原则\n{principles}\n\n"
103
+ f"# 安全与边界\n{boundaries}\n\n"
104
+ f"# 回答要求\n{outputs}"
105
+ )
106
+
107
+
108
+ def _blank_task_prompt(design: AgentBehaviorDesign) -> str:
109
+ workflow = "\n".join(f"{index}. {item}" for index, item in enumerate(design.workflow, 1))
110
+ return f"每次收到请求时遵循以下执行契约:\n{workflow}"
111
+
112
+ _RESEARCH_SKILL_MANIFEST = {
113
+ "name": RESEARCH_SKILL_NAME,
114
+ "displayName": "深度调研方法",
115
+ "version": RESEARCH_SKILL_VERSION,
116
+ "description": "用于问题拆解、来源检索、交叉验证、证据归档与引用输出的标准方法。",
117
+ "category": "research",
118
+ "instructionsFile": "SKILL.md",
119
+ }
120
+
121
+ _RESEARCH_SKILL_CONTENT = """---
122
+ name: Deep Research Methodology
123
+ description: A rigorous workflow for evidence-backed research and source synthesis.
124
+ version: 1.0.0
125
+ ---
126
+
127
+ # Deep Research Methodology
128
+
129
+ Apply this workflow to every research request:
130
+
131
+ 1. Clarify the research question, decision context, scope, time range, and exclusions.
132
+ 2. Build a question tree before collecting evidence. Separate facts, hypotheses, and unknowns.
133
+ 3. Search broadly, then prefer primary and authoritative sources over summaries.
134
+ 4. Record every material claim in a source ledger with title, URL, publisher, date, and access time.
135
+ 5. Cross-check important claims with at least two independent sources when possible.
136
+ 6. Explicitly identify conflicting evidence, stale information, and confidence limits.
137
+ 7. Synthesize findings around the user's decision instead of returning a source dump.
138
+ 8. Cite sources using stable labels such as [S1], [S2], and include a source table.
139
+ 9. Never invent a source, URL, statistic, quotation, or publication date.
140
+ 10. When external research tools are unavailable, state the limitation before answering.
141
+ """
142
+
143
+ _MCP_KEYWORDS = {
144
+ "browser",
145
+ "crawl",
146
+ "fetch",
147
+ "http",
148
+ "research",
149
+ "search",
150
+ "url",
151
+ "web",
152
+ }
153
+
154
+ _DEPTH_SETTINGS = {
155
+ "focused": {"max_steps": 8, "timeout_seconds": 180, "max_tokens": 3072},
156
+ "standard": {"max_steps": 16, "timeout_seconds": 360, "max_tokens": 4096},
157
+ "deep": {"max_steps": 28, "timeout_seconds": 900, "max_tokens": 6144},
158
+ }
159
+
160
+ _OUTPUT_NAMES_ZH = {
161
+ "brief": "决策简报",
162
+ "report": "结构化研究报告",
163
+ "evidence-table": "证据矩阵与结论",
164
+ }
165
+
166
+ _OUTPUT_NAMES_EN = {
167
+ "brief": "decision brief",
168
+ "report": "structured research report",
169
+ "evidence-table": "evidence matrix and conclusions",
170
+ }
171
+
172
+
173
+ def list_agent_templates() -> list[dict]:
174
+ return [
175
+ {
176
+ "id": "blank",
177
+ "name": "空白 Agent",
178
+ "description": "输入系统提示词,自主选择模型、Tool、MCP、Skill 与执行策略。",
179
+ "category": "general",
180
+ "recommended": True,
181
+ "steps": ["定义 Agent", "绑定能力", "配置 Prompt", "检查并创建"],
182
+ },
183
+ {
184
+ "id": "research",
185
+ "name": "Research Agent",
186
+ "description": "围绕一个研究目标规划检索、调用 MCP、验证来源并生成带引用的报告。",
187
+ "category": "knowledge-work",
188
+ "recommended": False,
189
+ "steps": ["定义目标", "绑定能力", "生成 Prompt", "检查并创建"],
190
+ },
191
+ ]
192
+
193
+
194
+ def default_agent_spec(
195
+ template: str,
196
+ *,
197
+ description: str = "",
198
+ ) -> AgentSpec:
199
+ if template == "blank":
200
+ return AgentSpec(
201
+ description=description,
202
+ instructions=Instructions(system="你是一个可靠的企业智能助手。", task=""),
203
+ )
204
+ if template == "research":
205
+ prompt = _research_instructions(
206
+ AgentTemplateComposeRequest(
207
+ goal="围绕用户输入的问题进行系统性深度调研并输出可核验结论",
208
+ ),
209
+ has_research_mcp=False,
210
+ )
211
+ return AgentSpec(
212
+ description=description or "执行深度调研并输出带来源引用的研究报告。",
213
+ instructions=prompt,
214
+ execution=ExecutionSpec(
215
+ strategy="plan-act-observe",
216
+ max_steps=28,
217
+ timeout_seconds=900,
218
+ ),
219
+ )
220
+ raise StudioError(
221
+ "AGENT_TEMPLATE_UNSUPPORTED",
222
+ "不支持的 Agent 模板",
223
+ status_code=422,
224
+ field="template",
225
+ details={"template": template},
226
+ )
227
+
228
+
229
+ def ensure_research_skill(workspace: Workspace) -> None:
230
+ root = workspace.resolve(f"capabilities/skills/{RESEARCH_SKILL_NAME}")
231
+ manifest = root / "skill.yaml"
232
+ instructions = root / "SKILL.md"
233
+ if root.exists():
234
+ if manifest.is_file() and instructions.is_file():
235
+ return
236
+ raise StudioError(
237
+ "RESEARCH_SKILL_CONFLICT",
238
+ "工作区存在不完整的同名 Research Skill",
239
+ status_code=409,
240
+ details={"path": workspace.relative(root)},
241
+ )
242
+ root.mkdir(parents=True)
243
+ workspace.atomic_write_text(
244
+ manifest,
245
+ yaml.safe_dump(
246
+ _RESEARCH_SKILL_MANIFEST,
247
+ allow_unicode=True,
248
+ sort_keys=False,
249
+ ),
250
+ )
251
+ workspace.atomic_write_text(instructions, _RESEARCH_SKILL_CONTENT)
252
+
253
+
254
+ def compose_blank_agent(
255
+ workspace: Workspace,
256
+ catalog: LocalResourceCatalog,
257
+ request: AgentTemplateComposeRequest,
258
+ ) -> AgentTemplateComposition:
259
+ del workspace
260
+ resources = catalog.list(limit=200)
261
+ models = [item for item in resources if item.kind == "model"]
262
+ tools = [item for item in resources if item.kind == "tool"]
263
+ skills = [item for item in resources if item.kind == "skill"]
264
+ mcps = [item for item in resources if item.kind == "mcp"]
265
+
266
+ requested_primary_model = request.model_profile_id or next(
267
+ iter(request.model_profile_ids), None
268
+ )
269
+ model = _select_model(models, requested_primary_model)
270
+ selected_model_ids = _select_model_ids(
271
+ models, request.model_profile_id, request.model_profile_ids
272
+ )
273
+ selected_tools = _select_resources(
274
+ tools,
275
+ request.tool_resource_ids,
276
+ kind="tool",
277
+ )
278
+ selected_skills = _select_resources(
279
+ skills,
280
+ request.skill_resource_ids,
281
+ kind="skill",
282
+ )
283
+ selected_mcps = _select_resources(
284
+ mcps,
285
+ request.mcp_resource_ids,
286
+ kind="mcp",
287
+ )
288
+ goal = request.goal.strip() or request.prompt.strip()
289
+ behavior_design = _blank_behavior_design(goal, request.policy_template)
290
+ # Explicit ``prompt`` is a compatibility path for callers that already own the
291
+ # final system instructions. Studio quick-create sends ``goal`` and therefore
292
+ # receives the compiled, reviewable behavior contract below.
293
+ system_prompt = request.prompt.strip() or _blank_system_prompt(behavior_design)
294
+ task_prompt = request.task_prompt.strip() or _blank_task_prompt(behavior_design)
295
+ description = request.description.strip() or goal[:160]
296
+ bindings = AgentBindings(
297
+ model_profile_id=model.resource_id,
298
+ model_profile_ids=selected_model_ids,
299
+ model_parameters=ModelParameters(
300
+ temperature=0.2,
301
+ max_tokens=4096,
302
+ ),
303
+ policy_template=request.policy_template,
304
+ tools=[CapabilityBinding(resource_id=item.resource_id) for item in selected_tools],
305
+ mcp_servers=[CapabilityBinding(resource_id=item.resource_id) for item in selected_mcps],
306
+ skills=[CapabilityBinding(resource_id=item.resource_id) for item in selected_skills],
307
+ )
308
+ spec = AgentSpec(
309
+ description=description,
310
+ instructions=Instructions(system=system_prompt, task=task_prompt),
311
+ bindings=bindings,
312
+ execution=ExecutionSpec(
313
+ strategy=request.execution_strategy,
314
+ max_steps=request.max_steps,
315
+ timeout_seconds=request.timeout_seconds,
316
+ ),
317
+ context=ContextSpec(
318
+ max_input_tokens=65536,
319
+ reserve_output_tokens=8192,
320
+ ),
321
+ )
322
+ recommendations = [
323
+ AgentTemplateRecommendation(
324
+ kind="model",
325
+ status="bound",
326
+ title=model.display_name,
327
+ reason="负责理解用户请求、规划执行并生成回答。",
328
+ resource_id=model.resource_id,
329
+ )
330
+ ]
331
+ recommendations.extend(
332
+ _bound_recommendations(
333
+ selected_tools,
334
+ reason="按用户选择绑定到 Agent,可用范围由权限策略控制。",
335
+ )
336
+ )
337
+ recommendations.extend(
338
+ _bound_recommendations(
339
+ selected_mcps,
340
+ reason="按用户选择连接外部 MCP Server。",
341
+ )
342
+ )
343
+ recommendations.extend(
344
+ _bound_recommendations(
345
+ selected_skills,
346
+ reason="按用户选择注入版本化 Skill 指令。",
347
+ )
348
+ )
349
+ return AgentTemplateComposition(
350
+ template_id="blank",
351
+ spec=spec,
352
+ behavior_design=behavior_design,
353
+ recommendations=recommendations,
354
+ warnings=[],
355
+ )
356
+
357
+
358
+ def compose_research_agent(
359
+ workspace: Workspace,
360
+ catalog: LocalResourceCatalog,
361
+ request: AgentTemplateComposeRequest,
362
+ ) -> AgentTemplateComposition:
363
+ ensure_research_skill(workspace)
364
+ resources = catalog.list(limit=200)
365
+ models = [item for item in resources if item.kind == "model"]
366
+ tools = [item for item in resources if item.kind == "tool"]
367
+ skills = [item for item in resources if item.kind == "skill"]
368
+ mcps = [item for item in resources if item.kind == "mcp"]
369
+
370
+ requested_primary_model = request.model_profile_id or next(
371
+ iter(request.model_profile_ids), None
372
+ )
373
+ model = _select_model(models, requested_primary_model)
374
+ selected_model_ids = _select_model_ids(
375
+ models, request.model_profile_id, request.model_profile_ids
376
+ )
377
+ research_skill = next(
378
+ (
379
+ item
380
+ for item in skills
381
+ if item.name == RESEARCH_SKILL_NAME and item.version == RESEARCH_SKILL_VERSION
382
+ ),
383
+ None,
384
+ )
385
+ if research_skill is None or research_skill.status != "ready":
386
+ raise StudioError(
387
+ "RESEARCH_SKILL_UNAVAILABLE",
388
+ "Research 模板无法解析内置调研 Skill",
389
+ status_code=409,
390
+ )
391
+
392
+ selected_skills = _select_resources(
393
+ skills,
394
+ [research_skill.resource_id, *request.skill_resource_ids],
395
+ kind="skill",
396
+ )
397
+ compatible_mcps = [item for item in mcps if _is_research_mcp(item)]
398
+ requested_mcp_ids = request.mcp_resource_ids or (
399
+ [item.resource_id for item in compatible_mcps[:1]] if request.auto_bind_mcp else []
400
+ )
401
+ selected_mcps = _select_resources(
402
+ mcps,
403
+ requested_mcp_ids,
404
+ kind="mcp",
405
+ )
406
+ default_tool_ids = [
407
+ item.resource_id
408
+ for item in tools
409
+ if item.name
410
+ in {
411
+ "list_workspace_files",
412
+ "search_workspace_files",
413
+ "read_workspace_file",
414
+ }
415
+ and item.status == "ready"
416
+ ]
417
+ requested_tool_ids = request.tool_resource_ids or (
418
+ default_tool_ids if request.auto_bind_tools else []
419
+ )
420
+ selected_tools = _select_resources(
421
+ tools,
422
+ requested_tool_ids,
423
+ kind="tool",
424
+ )
425
+
426
+ settings = _DEPTH_SETTINGS[request.depth]
427
+ bindings = AgentBindings(
428
+ model_profile_id=model.resource_id,
429
+ model_profile_ids=selected_model_ids,
430
+ model_parameters=ModelParameters(
431
+ temperature=0.2,
432
+ max_tokens=settings["max_tokens"],
433
+ ),
434
+ policy_template=request.policy_template,
435
+ tools=[CapabilityBinding(resource_id=item.resource_id) for item in selected_tools],
436
+ mcp_servers=[CapabilityBinding(resource_id=item.resource_id) for item in selected_mcps],
437
+ skills=[CapabilityBinding(resource_id=item.resource_id) for item in selected_skills],
438
+ )
439
+ has_research_mcp = bool(selected_mcps)
440
+ instructions = _research_instructions(
441
+ request,
442
+ has_research_mcp=has_research_mcp,
443
+ )
444
+ spec = AgentSpec(
445
+ description=request.description.strip()
446
+ or f"围绕“{_research_goal(request)[:160]}”执行深度调研并形成可核验结论。",
447
+ instructions=instructions,
448
+ bindings=bindings,
449
+ execution=ExecutionSpec(
450
+ strategy="plan-act-observe",
451
+ max_steps=settings["max_steps"],
452
+ timeout_seconds=settings["timeout_seconds"],
453
+ ),
454
+ context=ContextSpec(
455
+ max_input_tokens=65536,
456
+ reserve_output_tokens=8192,
457
+ ),
458
+ )
459
+
460
+ recommendations = [
461
+ AgentTemplateRecommendation(
462
+ kind="model",
463
+ status="bound",
464
+ title=model.display_name,
465
+ reason="负责问题拆解、证据综合与报告生成。",
466
+ resource_id=model.resource_id,
467
+ ),
468
+ AgentTemplateRecommendation(
469
+ kind="skill",
470
+ status="bound",
471
+ title=research_skill.display_name,
472
+ reason="注入问题树、来源分级、交叉验证和引用账本方法。",
473
+ resource_id=research_skill.resource_id,
474
+ ),
475
+ ]
476
+ recommendations.extend(
477
+ AgentTemplateRecommendation(
478
+ kind="tool",
479
+ status="bound",
480
+ title=item.display_name,
481
+ reason="用于读取和检索当前工作区中的研究资料。",
482
+ resource_id=item.resource_id,
483
+ )
484
+ for item in selected_tools
485
+ )
486
+ warnings: list[str] = []
487
+ if selected_mcps:
488
+ recommendations.extend(
489
+ AgentTemplateRecommendation(
490
+ kind="mcp",
491
+ status="bound",
492
+ title=item.display_name,
493
+ reason="提供外部来源搜索、抓取或浏览能力。",
494
+ resource_id=item.resource_id,
495
+ )
496
+ for item in selected_mcps
497
+ )
498
+ else:
499
+ warning = (
500
+ "当前没有已探测且包含搜索或抓取 Tool 的 MCP。Agent 仍可基于用户输入和"
501
+ "工作区资料调研,但无法主动检索外部来源。"
502
+ )
503
+ warnings.append(warning)
504
+ recommendations.append(
505
+ AgentTemplateRecommendation(
506
+ kind="mcp",
507
+ status="missing",
508
+ title="Web Research MCP",
509
+ reason=warning,
510
+ )
511
+ )
512
+ return AgentTemplateComposition(
513
+ template_id="research",
514
+ spec=spec,
515
+ recommendations=recommendations,
516
+ warnings=warnings,
517
+ )
518
+
519
+
520
+ def _select_model(
521
+ models: list[ResourceDescriptor],
522
+ resource_id: str | None,
523
+ ) -> ResourceDescriptor:
524
+ if resource_id:
525
+ selected = next(
526
+ (item for item in models if item.resource_id == resource_id),
527
+ None,
528
+ )
529
+ if selected is None:
530
+ raise StudioError(
531
+ "RESOURCE_NOT_FOUND",
532
+ "选择的 Model Profile 不存在",
533
+ status_code=404,
534
+ details={"resourceId": resource_id},
535
+ )
536
+ if selected.status not in {"ready", "missing-secret"}:
537
+ raise StudioError(
538
+ "RESOURCE_NOT_READY",
539
+ "选择的 Model Profile 当前不可用",
540
+ status_code=409,
541
+ details={"resourceId": resource_id, "status": selected.status},
542
+ )
543
+ return selected
544
+ selected = next(
545
+ (item for item in models if item.status in {"ready", "missing-secret"}),
546
+ None,
547
+ )
548
+ if selected is None:
549
+ raise StudioError(
550
+ "AGENT_MODEL_REQUIRED",
551
+ "Agent 需要一个可用的 Model Profile",
552
+ status_code=409,
553
+ )
554
+ return selected
555
+
556
+
557
+ def _select_model_ids(
558
+ models: list[ResourceDescriptor],
559
+ primary_id: str | None,
560
+ requested_ids: list[str] | None,
561
+ ) -> list[str]:
562
+ """Resolve the full set of bound model profile ids, deduped, primary first."""
563
+ valid = [item for item in models if item.status in {"ready", "missing-secret"}]
564
+ valid_ids = {item.resource_id for item in valid}
565
+ ordered: list[str] = []
566
+ if primary_id and primary_id in valid_ids:
567
+ ordered.append(primary_id)
568
+ for rid in requested_ids or []:
569
+ if rid in valid_ids and rid not in ordered:
570
+ ordered.append(rid)
571
+ return ordered
572
+
573
+
574
+
575
+ def _bound_recommendations(
576
+ resources: list[ResourceDescriptor],
577
+ *,
578
+ reason: str,
579
+ ) -> list[AgentTemplateRecommendation]:
580
+ return [
581
+ AgentTemplateRecommendation(
582
+ kind=item.kind,
583
+ status="bound",
584
+ title=item.display_name,
585
+ reason=reason,
586
+ resource_id=item.resource_id,
587
+ )
588
+ for item in resources
589
+ ]
590
+
591
+
592
+ def _select_resources(
593
+ resources: list[ResourceDescriptor],
594
+ resource_ids: Iterable[str],
595
+ *,
596
+ kind: str,
597
+ ) -> list[ResourceDescriptor]:
598
+ selected: list[ResourceDescriptor] = []
599
+ seen: set[str] = set()
600
+ by_id = {item.resource_id: item for item in resources}
601
+ for resource_id in resource_ids:
602
+ if resource_id in seen:
603
+ continue
604
+ seen.add(resource_id)
605
+ descriptor = by_id.get(resource_id)
606
+ if descriptor is None:
607
+ raise StudioError(
608
+ "RESOURCE_NOT_FOUND",
609
+ "模板引用的资源不存在",
610
+ status_code=404,
611
+ details={"resourceId": resource_id},
612
+ )
613
+ if descriptor.kind != kind:
614
+ raise StudioError(
615
+ "RESOURCE_KIND_INVALID",
616
+ "模板资源类型不匹配",
617
+ status_code=422,
618
+ details={"resourceId": resource_id, "expectedKind": kind},
619
+ )
620
+ if descriptor.status != "ready":
621
+ raise StudioError(
622
+ "RESOURCE_NOT_READY",
623
+ "模板不能绑定不可用资源",
624
+ status_code=409,
625
+ details={"resourceId": resource_id, "status": descriptor.status},
626
+ )
627
+ selected.append(descriptor)
628
+ return selected
629
+
630
+
631
+ def _is_research_mcp(resource: ResourceDescriptor) -> bool:
632
+ if resource.status != "ready":
633
+ return False
634
+ discovered_tools = resource.contract.get("discoveredTools") or []
635
+ if not discovered_tools:
636
+ return False
637
+ searchable = " ".join(
638
+ [
639
+ resource.name,
640
+ resource.display_name,
641
+ resource.description,
642
+ *[str(tool.get("name") or "") for tool in discovered_tools],
643
+ *[str(tool.get("description") or "") for tool in discovered_tools],
644
+ ]
645
+ ).lower()
646
+ return any(keyword in searchable for keyword in _MCP_KEYWORDS)
647
+
648
+
649
+ def _research_instructions(
650
+ request: AgentTemplateComposeRequest,
651
+ *,
652
+ has_research_mcp: bool,
653
+ ) -> Instructions:
654
+ research_goal = _research_goal(request)
655
+ if request.language == "en-US":
656
+ output_name = _OUTPUT_NAMES_EN[request.output_format]
657
+ role = f"You are Research Agent, a rigorous research specialist serving {request.audience}."
658
+ system = f"""{role}
659
+
660
+ Research objective:
661
+ {research_goal}
662
+
663
+ Operating principles:
664
+ 1. Clarify scope and assumptions before collecting evidence.
665
+ 2. Create a question tree and an explicit research plan.
666
+ 3. Prefer primary, authoritative, and recent sources.
667
+ 4. Cross-check material claims and distinguish facts from inference.
668
+ 5. Keep a source ledger and cite every externally verifiable claim.
669
+ 6. Never invent a source, URL, quotation, statistic, or publication date.
670
+ 7. Surface conflicting evidence, uncertainty, and information gaps.
671
+ 8. Produce a {output_name} for the user's decision context.
672
+ """
673
+ if not has_research_mcp:
674
+ system += (
675
+ "\nExternal research MCP is not currently bound. Use only supplied or "
676
+ "workspace evidence and state this limitation before the answer.\n"
677
+ )
678
+ task = """For each request, execute this contract:
679
+ - Restate the research question, scope, and exclusions.
680
+ - Present the plan before long-running research.
681
+ - Gather and rank evidence by source quality and recency.
682
+ - Synthesize findings into an executive summary, key findings, evidence table,
683
+ disagreements or risks, recommendations, and a source list.
684
+ - Use stable citations such as [S1] and map each citation to a real source.
685
+ - End with confidence and unresolved questions.
686
+ """
687
+ return Instructions(system=system.strip(), task=task.strip())
688
+
689
+ output_name = _OUTPUT_NAMES_ZH[request.output_format]
690
+ system = f"""你是 Research Agent,一名为{request.audience}服务的严谨深度调研专家。
691
+
692
+ 调研目标:
693
+ {research_goal}
694
+
695
+ 工作原则:
696
+ 1. 收集证据前先明确范围、时间窗口、假设和排除项。
697
+ 2. 建立问题树和可执行调研计划,再开始调用工具。
698
+ 3. 优先使用一手、权威且时效性匹配的来源。
699
+ 4. 对重要结论交叉验证,清楚区分事实、推断与未知。
700
+ 5. 维护来源账本,为每个可外部核验的关键主张提供引用。
701
+ 6. 不得虚构来源、URL、引文、统计数据或发布日期。
702
+ 7. 主动呈现冲突证据、不确定性和信息缺口。
703
+ 8. 围绕用户的决策场景输出{output_name}。
704
+ """
705
+ if not has_research_mcp:
706
+ system += (
707
+ "\n当前未绑定外部调研 MCP。只能使用用户提供内容和工作区资料,"
708
+ "回答前必须明确说明这一限制。\n"
709
+ )
710
+ task = """每次请求都必须执行以下任务契约:
711
+ - 复述研究问题、范围和排除项。
712
+ - 在长时间调研前先展示计划。
713
+ - 按来源质量和时效性收集、筛选和排序证据。
714
+ - 输出执行摘要、关键发现、证据表、冲突或风险、建议和来源列表。
715
+ - 使用 [S1]、[S2] 等稳定引用,并映射到真实来源。
716
+ - 结尾给出置信度和仍待解决的问题。
717
+ """
718
+ return Instructions(system=system.strip(), task=task.strip())
719
+
720
+
721
+ def _research_goal(request: AgentTemplateComposeRequest) -> str:
722
+ return request.goal.strip() or request.prompt.strip()