cognis-executor 0.2.0__tar.gz → 0.3.0__tar.gz

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 (300) hide show
  1. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/PKG-INFO +2 -2
  2. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/app.py +100 -5
  3. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/common.py +80 -3
  4. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/executor_runtime.py +39 -7
  5. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/executor_ws.py +5 -0
  6. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/middleware.py +40 -20
  7. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/models.py +238 -26
  8. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/routes/agents.py +435 -75
  9. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/routes/auth.py +150 -51
  10. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/routes/conversations.py +51 -29
  11. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/routes/credentials.py +13 -1
  12. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/routes/executors.py +61 -10
  13. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/routes/images.py +2 -2
  14. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/routes/notifications.py +8 -1
  15. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/routes/schedules.py +242 -18
  16. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/routes/secrets.py +27 -5
  17. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/routes/sessions.py +5 -5
  18. cognis_executor-0.3.0/cognis/api/routes/settings.py +796 -0
  19. cognis_executor-0.3.0/cognis/api/routes/skills.py +1002 -0
  20. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/routes/system.py +36 -0
  21. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/routes/tasks.py +340 -62
  22. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/routes/tools.py +314 -29
  23. cognis_executor-0.3.0/cognis/api/routes/workflows.py +359 -0
  24. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/runtime_support.py +379 -180
  25. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/serializers.py +133 -12
  26. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/sse.py +56 -0
  27. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/websocket.py +268 -31
  28. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/bootstrap.py +292 -31
  29. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/adapters/signal.py +41 -6
  30. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/delivery.py +147 -94
  31. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/inbound.py +68 -59
  32. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/cli/admin.py +27 -0
  33. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/config.py +17 -0
  34. cognis_executor-0.3.0/cognis/core/agent_loop.py +10204 -0
  35. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/agent_registry.py +307 -212
  36. cognis_executor-0.3.0/cognis/core/anchored_output.py +71 -0
  37. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/attachment_utils.py +30 -4
  38. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/commands.py +298 -54
  39. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/compaction.py +12 -4
  40. cognis_executor-0.3.0/cognis/core/context.py +2396 -0
  41. cognis_executor-0.3.0/cognis/core/context_budget.py +69 -0
  42. cognis_executor-0.3.0/cognis/core/context_projection.py +371 -0
  43. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/decision.py +29 -1
  44. cognis_executor-0.3.0/cognis/core/errors.py +11 -0
  45. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/events.py +76 -3
  46. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/executor_policy.py +14 -2
  47. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/executor_resolution.py +27 -26
  48. cognis_executor-0.3.0/cognis/core/harness_guards.py +369 -0
  49. cognis_executor-0.3.0/cognis/core/immutable_prefix.py +105 -0
  50. cognis_executor-0.3.0/cognis/core/invariants.py +233 -0
  51. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/management.py +54 -5
  52. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/notifications.py +160 -3
  53. cognis_executor-0.3.0/cognis/core/project_context.py +122 -0
  54. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/prompts.py +174 -16
  55. cognis_executor-0.3.0/cognis/core/pruning.py +33 -0
  56. cognis_executor-0.3.0/cognis/core/remember_queue.py +583 -0
  57. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/runtime.py +1 -0
  58. cognis_executor-0.3.0/cognis/core/schedule_management.py +102 -0
  59. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/scheduler.py +58 -16
  60. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/session.py +168 -23
  61. cognis_executor-0.3.0/cognis/core/session_cache.py +1139 -0
  62. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/step_evaluator.py +77 -21
  63. cognis_executor-0.3.0/cognis/core/step_profiles.py +411 -0
  64. cognis_executor-0.3.0/cognis/core/system_skills.py +304 -0
  65. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/task_queue.py +403 -54
  66. cognis_executor-0.3.0/cognis/core/tool_arguments.py +128 -0
  67. cognis_executor-0.3.0/cognis/core/tool_classification_queue.py +359 -0
  68. cognis_executor-0.3.0/cognis/core/tool_exposure.py +702 -0
  69. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/tool_output_store.py +273 -40
  70. cognis_executor-0.3.0/cognis/core/tool_retrieval.py +291 -0
  71. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/tool_router.py +377 -26
  72. cognis_executor-0.3.0/cognis/core/truncation.py +136 -0
  73. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/turn_scheduler.py +779 -117
  74. cognis_executor-0.3.0/cognis/core/workflow_composition.py +562 -0
  75. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/workflow_engine.py +991 -158
  76. cognis_executor-0.3.0/cognis/core/workflow_management.py +429 -0
  77. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/workflow_registry.py +281 -35
  78. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/executor/runner.py +138 -117
  79. cognis_executor-0.3.0/cognis/json_stream.py +92 -0
  80. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/models/agent.py +29 -1
  81. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/models/config.py +40 -5
  82. cognis_executor-0.3.0/cognis/models/deliverable.py +51 -0
  83. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/models/schedule.py +5 -2
  84. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/models/session.py +18 -0
  85. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/models/skill.py +53 -4
  86. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/models/task.py +22 -5
  87. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/models/tool.py +98 -1
  88. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/models/workflow.py +145 -2
  89. cognis_executor-0.3.0/cognis/ownership.py +26 -0
  90. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/auth/jwt.py +17 -5
  91. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/base.py +28 -3
  92. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/executor/in_process.py +109 -82
  93. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/executor/websocket.py +15 -5
  94. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/guardrails/intaris.py +133 -21
  95. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/llm/inference_router.py +5 -1
  96. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/llm/litellm.py +1330 -120
  97. cognis_executor-0.3.0/cognis/providers/llm/reasoning.py +584 -0
  98. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/llm/responses_bridge.py +399 -69
  99. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/memory/mnemory.py +401 -56
  100. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/secrets/encrypted_db.py +8 -6
  101. cognis_executor-0.3.0/cognis/runtime_context.py +56 -0
  102. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/settings_schema.py +2 -0
  103. cognis_executor-0.3.0/cognis/store/migrations/versions/032_system_asset_overrides.py +67 -0
  104. cognis_executor-0.3.0/cognis/store/migrations/versions/033_system_agent_skill_overrides.py +24 -0
  105. cognis_executor-0.3.0/cognis/store/migrations/versions/033_task_working_directory.py +30 -0
  106. cognis_executor-0.3.0/cognis/store/migrations/versions/034_completion_delivery_policy.py +74 -0
  107. cognis_executor-0.3.0/cognis/store/migrations/versions/035_harness_recovery_tables.py +93 -0
  108. cognis_executor-0.3.0/cognis/store/migrations/versions/036_workflow_deliverables.py +66 -0
  109. cognis_executor-0.3.0/cognis/store/migrations/versions/037_workflow_composition_lifecycle.py +38 -0
  110. cognis_executor-0.3.0/cognis/store/migrations/versions/038_tool_classifications.py +66 -0
  111. cognis_executor-0.3.0/cognis/store/migrations/versions/039_tool_classification_overrides.py +48 -0
  112. cognis_executor-0.3.0/cognis/store/migrations/versions/040_browser_sessions.py +64 -0
  113. cognis_executor-0.3.0/cognis/store/migrations/versions/041_schedule_skill_sources.py +26 -0
  114. cognis_executor-0.3.0/cognis/store/migrations/versions/042_skill_linked_tool_ids.py +30 -0
  115. cognis_executor-0.3.0/cognis/store/migrations/versions/043_agent_grants.py +70 -0
  116. cognis_executor-0.3.0/cognis/store/migrations/versions/044_step_run_runtime_info.py +26 -0
  117. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/models.py +303 -3
  118. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/queries.py +1254 -97
  119. cognis_executor-0.3.0/cognis/tools/builtin/artifact_tools.py +1050 -0
  120. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/builtin/memory.py +99 -96
  121. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/builtin/orchestration.py +167 -15
  122. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/builtin/schedule.py +24 -13
  123. cognis_executor-0.3.0/cognis/tools/builtin/skill_management.py +1662 -0
  124. cognis_executor-0.3.0/cognis/tools/builtin/tool_output.py +356 -0
  125. cognis_executor-0.3.0/cognis/tools/builtin/tool_search.py +230 -0
  126. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/builtin/workflow.py +77 -2
  127. cognis_executor-0.3.0/cognis/tools/classification.py +693 -0
  128. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/definitions.py +171 -21
  129. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/filesystem.py +572 -90
  130. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/lsp/client.py +75 -0
  131. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/lsp/manager.py +104 -0
  132. cognis_executor-0.3.0/cognis/tools/executor/lsp/tool.py +86 -0
  133. cognis_executor-0.3.0/cognis/tools/executor/paths.py +79 -0
  134. cognis_executor-0.3.0/cognis/tools/executor/project_context.py +263 -0
  135. cognis_executor-0.3.0/cognis/tools/executor/search.py +344 -0
  136. cognis_executor-0.3.0/cognis/tools/executor/shell.py +443 -0
  137. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/web/backends/brave.py +15 -15
  138. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/web/backends/direct.py +12 -14
  139. cognis_executor-0.3.0/cognis/tools/executor/web/backends/formatting.py +83 -0
  140. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/web/backends/tavily.py +19 -21
  141. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/web/definitions.py +119 -8
  142. cognis_executor-0.3.0/cognis/tools/executor/web/handlers.py +498 -0
  143. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/mcp.py +145 -17
  144. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/registry.py +1 -0
  145. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/skill_parser.py +46 -2
  146. cognis_executor-0.3.0/cognis/tools/skill_service.py +613 -0
  147. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/skills.py +185 -15
  148. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/pyproject.toml +2 -2
  149. cognis_executor-0.2.0/cognis/api/routes/settings.py +0 -438
  150. cognis_executor-0.2.0/cognis/api/routes/skills.py +0 -428
  151. cognis_executor-0.2.0/cognis/api/routes/workflows.py +0 -160
  152. cognis_executor-0.2.0/cognis/core/agent_loop.py +0 -4667
  153. cognis_executor-0.2.0/cognis/core/context.py +0 -1505
  154. cognis_executor-0.2.0/cognis/core/pruning.py +0 -142
  155. cognis_executor-0.2.0/cognis/core/remember_queue.py +0 -99
  156. cognis_executor-0.2.0/cognis/core/session_cache.py +0 -638
  157. cognis_executor-0.2.0/cognis/core/system_skills.py +0 -149
  158. cognis_executor-0.2.0/cognis/core/tool_exposure.py +0 -241
  159. cognis_executor-0.2.0/cognis/core/truncation.py +0 -52
  160. cognis_executor-0.2.0/cognis/core/workflow_management.py +0 -192
  161. cognis_executor-0.2.0/cognis/runtime_context.py +0 -27
  162. cognis_executor-0.2.0/cognis/tools/builtin/skill_management.py +0 -666
  163. cognis_executor-0.2.0/cognis/tools/builtin/tool_output.py +0 -178
  164. cognis_executor-0.2.0/cognis/tools/builtin/tool_search.py +0 -85
  165. cognis_executor-0.2.0/cognis/tools/executor/paths.py +0 -16
  166. cognis_executor-0.2.0/cognis/tools/executor/search.py +0 -196
  167. cognis_executor-0.2.0/cognis/tools/executor/shell.py +0 -127
  168. cognis_executor-0.2.0/cognis/tools/executor/web/handlers.py +0 -211
  169. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/README.md +0 -0
  170. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/__init__.py +0 -0
  171. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/__init__.py +0 -0
  172. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/error_sanitizer.py +0 -0
  173. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/routes/__init__.py +0 -0
  174. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/routes/artifacts.py +0 -0
  175. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/routes/channels.py +0 -0
  176. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/routes/escalations.py +0 -0
  177. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/routes/users.py +0 -0
  178. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/api/tool_inventory.py +0 -0
  179. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/artifacts/__init__.py +0 -0
  180. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/artifacts/store.py +0 -0
  181. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/__init__.py +0 -0
  182. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/adapters/__init__.py +0 -0
  183. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/adapters/bluebubbles.py +0 -0
  184. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/adapters/discord.py +0 -0
  185. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/adapters/google_chat.py +0 -0
  186. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/adapters/irc.py +0 -0
  187. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/adapters/matrix.py +0 -0
  188. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/adapters/signal_cli_runtime.py +0 -0
  189. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/adapters/slack.py +0 -0
  190. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/adapters/telegram.py +0 -0
  191. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/adapters/whatsapp.py +0 -0
  192. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/factory.py +0 -0
  193. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/formatting.py +0 -0
  194. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/manager.py +0 -0
  195. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/pairing.py +0 -0
  196. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/protocol.py +0 -0
  197. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/registry.py +0 -0
  198. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/remote.py +0 -0
  199. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/channels/signal_formatting.py +0 -0
  200. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/cli/__init__.py +0 -0
  201. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/cli/executor.py +0 -0
  202. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/cli/serve.py +0 -0
  203. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/__init__.py +0 -0
  204. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/artifact_maintenance.py +0 -0
  205. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/followups.py +0 -0
  206. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/json_utils.py +0 -0
  207. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/core/title_policy.py +0 -0
  208. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/executor/__init__.py +0 -0
  209. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/executor/__main__.py +0 -0
  210. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/executor/channel_handler.py +0 -0
  211. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/executor/inference.py +0 -0
  212. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/logging.py +0 -0
  213. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/main.py +0 -0
  214. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/models/__init__.py +0 -0
  215. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/models/artifact.py +0 -0
  216. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/models/channel.py +0 -0
  217. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/models/credential.py +0 -0
  218. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/models/delegation.py +0 -0
  219. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/__init__.py +0 -0
  220. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/auth/__init__.py +0 -0
  221. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/auth/protocol.py +0 -0
  222. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/circuit_breaker.py +0 -0
  223. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/credentials/encrypted_db.py +0 -0
  224. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/executor/__init__.py +0 -0
  225. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/executor/composite.py +0 -0
  226. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/executor/protocol.py +0 -0
  227. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/executor/subprocess.py +0 -0
  228. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/guardrails/__init__.py +0 -0
  229. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/guardrails/protocol.py +0 -0
  230. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/llm/__init__.py +0 -0
  231. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/llm/protocol.py +0 -0
  232. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/llm/retry.py +0 -0
  233. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/memory/__init__.py +0 -0
  234. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/memory/protocol.py +0 -0
  235. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/registry.py +0 -0
  236. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/retry.py +0 -0
  237. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/secrets/__init__.py +0 -0
  238. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/providers/secrets/protocol.py +0 -0
  239. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/security.py +0 -0
  240. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/__init__.py +0 -0
  241. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/database.py +0 -0
  242. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/alembic.ini +0 -0
  243. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/env.py +0 -0
  244. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/script.py.mako +0 -0
  245. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/001_initial.py +0 -0
  246. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/002_session_lifecycle_fields.py +0 -0
  247. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/003_tasks_workflows_schedules.py +0 -0
  248. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/004_api_key_last_used_at.py +0 -0
  249. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/005_agent_sync_metadata.py +0 -0
  250. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/006_provider_is_default.py +0 -0
  251. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/007_skills_table.py +0 -0
  252. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/008_executors_table.py +0 -0
  253. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/009_session_compaction_fields.py +0 -0
  254. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/010_task_expected_output.py +0 -0
  255. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/011_rename_root_to_active_session_id.py +0 -0
  256. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/012_step_run_conversation_id.py +0 -0
  257. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/013_user_management_fields.py +0 -0
  258. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/014_notifications_table.py +0 -0
  259. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/015_conversation_last_read_at.py +0 -0
  260. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/016_channel_accounts_contacts.py +0 -0
  261. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/017_channel_pairing_requests.py +0 -0
  262. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/018_channel_adapter_location.py +0 -0
  263. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/019_channel_executor_fk.py +0 -0
  264. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/020_agent_avatar_image.py +0 -0
  265. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/021_artifact_records.py +0 -0
  266. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/022_mcp_servers_table.py +0 -0
  267. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/023_executor_runtime_state.py +0 -0
  268. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/024_skill_versions.py +0 -0
  269. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/025_channel_delivery_outbox.py +0 -0
  270. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/026_executor_runtime_metadata.py +0 -0
  271. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/027_extend_schedules.py +0 -0
  272. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/028_credentials_table.py +0 -0
  273. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/029_conversation_title_source.py +0 -0
  274. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/030_mcp_http_headers.py +0 -0
  275. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/store/migrations/versions/031_skill_is_system.py +0 -0
  276. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/__init__.py +0 -0
  277. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/argument_normalization.py +0 -0
  278. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/builtin/__init__.py +0 -0
  279. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/builtin/datetime_tools.py +0 -0
  280. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/builtin/image.py +0 -0
  281. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/builtin/system.py +0 -0
  282. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/__init__.py +0 -0
  283. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/browser/definitions.py +0 -0
  284. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/browser/handlers.py +0 -0
  285. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/browser/install.py +0 -0
  286. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/browser/manager.py +0 -0
  287. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/document.py +0 -0
  288. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/file_freshness.py +0 -0
  289. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/lsp/__init__.py +0 -0
  290. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/lsp/diagnostics.py +0 -0
  291. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/lsp/install.py +0 -0
  292. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/lsp/runtime.py +0 -0
  293. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/lsp/servers.py +0 -0
  294. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/lsp/types.py +0 -0
  295. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/web/__init__.py +0 -0
  296. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/web/backends/__init__.py +0 -0
  297. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/web/backends/protocol.py +0 -0
  298. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/executor/web/headers.py +0 -0
  299. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/tools/skill_import.py +0 -0
  300. {cognis_executor-0.2.0 → cognis_executor-0.3.0}/cognis/ui_assets.py +4 -4
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cognis-executor
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Standalone remote executor for Cognis
5
5
  Author-email: Filip Pytloun <filip@pytloun.cz>
6
6
  License: TBD
@@ -18,7 +18,7 @@ Requires-Dist: ddgs>=9.0.0
18
18
  Requires-Dist: email-validator>=2.0.0
19
19
  Requires-Dist: fastapi>=0.115.0
20
20
  Requires-Dist: httpx>=0.27.0
21
- Requires-Dist: litellm>=1.40.0
21
+ Requires-Dist: litellm>=1.82.0
22
22
  Requires-Dist: markdown>=3.7
23
23
  Requires-Dist: markdownify>=0.14.0
24
24
  Requires-Dist: mcp>=1.6.0
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import asyncio
6
+ import contextlib
6
7
  import hashlib
7
8
  import secrets
8
9
  import sys
@@ -43,6 +44,7 @@ from cognis.api.websocket import handle_websocket
43
44
  from cognis.bootstrap import bootstrap_runtime
44
45
  from cognis.config import load_config
45
46
  from cognis.core.agent_loop import AgentLoop, PauseWaiter, SessionLock
47
+ from cognis.core.agent_registry import AgentRegistry
46
48
  from cognis.core.compaction import CompactionStrategy
47
49
  from cognis.core.context import ContextAssembler
48
50
  from cognis.core.decision import DecisionEngine
@@ -52,7 +54,9 @@ from cognis.core.scheduler import Scheduler
52
54
  from cognis.core.session import SessionManager
53
55
  from cognis.core.session_cache import SessionCache
54
56
  from cognis.core.step_evaluator import StepEvaluator
57
+ from cognis.core.step_profiles import StepProfileRegistry
55
58
  from cognis.core.task_queue import TaskQueue
59
+ from cognis.core.tool_classification_queue import ToolClassificationQueue
56
60
  from cognis.core.tool_output_store import ToolOutputStore
57
61
  from cognis.core.tool_router import ToolRouter
58
62
  from cognis.core.workflow_engine import WorkflowEngine
@@ -145,8 +149,19 @@ def create_app() -> FastAPI:
145
149
  config_runtime.jwt_private_key_path, config_runtime.jwt_public_key_path
146
150
  )
147
151
  providers = build_provider_registry(config_runtime, session_factory, auth_provider)
148
- remember_queue = RememberRetryQueue(providers.memory)
152
+ event_bus = EventBus()
153
+ remember_queue = RememberRetryQueue(
154
+ providers.memory,
155
+ session_factory=session_factory,
156
+ event_reader=providers.guardrails,
157
+ event_bus=event_bus,
158
+ )
149
159
  await remember_queue.start()
160
+ tool_classification_queue = ToolClassificationQueue(
161
+ session_factory=session_factory,
162
+ llm_provider=providers.llm,
163
+ )
164
+ await tool_classification_queue.start()
150
165
  await _print_startup_status(config_runtime, providers, ui_build_dir)
151
166
 
152
167
  async with session_factory() as session:
@@ -188,14 +203,20 @@ def create_app() -> FastAPI:
188
203
  )
189
204
  sys.stdout.flush()
190
205
 
191
- event_bus = EventBus()
206
+ pause_waiter = PauseWaiter()
207
+ session_lock = SessionLock()
208
+ session_lock_sweeper_task: asyncio.Task[None] | None = None
192
209
  session_cache = SessionCache(
193
210
  providers.guardrails,
194
211
  max_entries=cache_max_entries,
195
212
  redis_url=config_runtime.redis_url,
196
213
  )
197
214
  session_manager = SessionManager(
198
- session_factory, providers, session_cache, event_bus=event_bus
215
+ session_factory,
216
+ providers,
217
+ session_cache,
218
+ event_bus=event_bus,
219
+ session_lock=session_lock,
199
220
  )
200
221
  context_assembler = await ContextAssembler.from_session_factory(
201
222
  session_factory=session_factory,
@@ -215,8 +236,6 @@ def create_app() -> FastAPI:
215
236
  session_factory=session_factory,
216
237
  llm=providers.llm,
217
238
  )
218
- pause_waiter = PauseWaiter()
219
- session_lock = SessionLock()
220
239
  from cognis.core.tool_output_store import (
221
240
  FilesystemToolOutputBackend,
222
241
  S3ToolOutputBackend,
@@ -263,6 +282,7 @@ def create_app() -> FastAPI:
263
282
  )
264
283
 
265
284
  from cognis.core.artifact_maintenance import ArtifactMaintenanceService
285
+ from cognis.store.queries import get_setting_value
266
286
 
267
287
  artifact_maintenance = ArtifactMaintenanceService(
268
288
  session_factory=session_factory,
@@ -273,13 +293,16 @@ def create_app() -> FastAPI:
273
293
  tool_router = await ToolRouter.from_session_factory(
274
294
  providers.guardrails,
275
295
  session_factory,
296
+ llm=providers.llm,
276
297
  memory=providers.memory,
277
298
  credentials_provider=providers.credentials,
278
299
  tool_output_store=tool_output_store,
279
300
  image_generation_provider=providers.image_generation,
280
301
  artifact_store=artifact_store,
281
302
  )
303
+ agent_registry = AgentRegistry(session_factory)
282
304
  workflow_registry = WorkflowRegistry(session_factory)
305
+ step_profile_registry = await StepProfileRegistry.from_session_factory(session_factory)
283
306
  step_evaluator = await StepEvaluator.from_session_factory(
284
307
  session_factory=session_factory,
285
308
  llm=providers.llm,
@@ -290,7 +313,14 @@ def create_app() -> FastAPI:
290
313
  shared_registry=shared_runtime.tool_registry,
291
314
  shared_connection=shared_runtime.executor_connection,
292
315
  session_factory=session_factory,
316
+ artifact_store=artifact_store,
293
317
  )
318
+ async with session_factory() as session:
319
+ step_timeout_seconds = await get_setting_value(
320
+ session,
321
+ "session.step_timeout_seconds",
322
+ 3600,
323
+ )
294
324
  agent_loop = AgentLoop(
295
325
  providers=providers,
296
326
  session_manager=session_manager,
@@ -302,6 +332,12 @@ def create_app() -> FastAPI:
302
332
  event_bus=event_bus,
303
333
  session_lock=session_lock,
304
334
  pause_waiter=pause_waiter,
335
+ session_factory=session_factory,
336
+ tool_classification_queue=tool_classification_queue,
337
+ step_profile_registry=step_profile_registry,
338
+ default_step_timeout_seconds=(
339
+ int(step_timeout_seconds) if isinstance(step_timeout_seconds, int) else 3600
340
+ ),
305
341
  tool_output_store=tool_output_store,
306
342
  step_runtime_factory=step_runtime_factory,
307
343
  )
@@ -324,6 +360,7 @@ def create_app() -> FastAPI:
324
360
  workflow_engine=workflow_engine,
325
361
  workflow_registry=workflow_registry,
326
362
  event_bus=event_bus,
363
+ agent_registry=agent_registry,
327
364
  llm_provider=providers.llm,
328
365
  )
329
366
  agent_loop.set_task_queue(task_queue)
@@ -383,6 +420,41 @@ def create_app() -> FastAPI:
383
420
  recovered_sessions = await session_manager.recover_stale_sessions()
384
421
  recovered_tasks = await task_queue.recover_stale_tasks()
385
422
  recovered_paused_tasks = await task_queue.recover_paused_tasks()
423
+ recovered_orphaned_step_runs = await task_queue.recover_orphaned_running_step_runs()
424
+
425
+ # System-wide invariant reconciliation. Runs after the focused
426
+ # recovery helpers above so any residual drift (e.g. conversations
427
+ # whose active_session_id still points at a terminal session) is
428
+ # cleaned before the drain loop starts picking tasks. The
429
+ # implementation is idempotent and covered by unit tests.
430
+ from cognis.core.invariants import reconcile_invariants
431
+
432
+ async with session_factory() as recon_session:
433
+ invariant_reports = await reconcile_invariants(recon_session)
434
+ reconciled_invariant_counts = {
435
+ report.category: report.reconciled_count
436
+ for report in invariant_reports
437
+ if report.reconciled_count
438
+ }
439
+ if reconciled_invariant_counts:
440
+ logger.warning(
441
+ "startup: reconciled invariant violations",
442
+ extra={"extra_data": {"counts": reconciled_invariant_counts}},
443
+ )
444
+
445
+ logger.info(
446
+ "startup: recovery summary",
447
+ extra={
448
+ "extra_data": {
449
+ "recovered_sessions": len(recovered_sessions),
450
+ "recovered_tasks": len(recovered_tasks),
451
+ "recovered_paused_tasks": len(recovered_paused_tasks),
452
+ "recovered_orphaned_step_runs": recovered_orphaned_step_runs,
453
+ "invariant_reports": [report.as_dict() for report in invariant_reports],
454
+ }
455
+ },
456
+ )
457
+
386
458
  await task_queue.start()
387
459
 
388
460
  # Scheduler — evaluates cron/interval/one-shot schedules and
@@ -410,6 +482,7 @@ def create_app() -> FastAPI:
410
482
  app.state.provider_test_results = {}
411
483
  app.state.provider_test_cooldowns = {}
412
484
  app.state.remember_queue = remember_queue
485
+ app.state.tool_classification_queue = tool_classification_queue
413
486
  app.state.artifact_store = artifact_store
414
487
  app.state.artifact_maintenance = artifact_maintenance
415
488
  app.state.serve_ui = config_runtime.serve_ui
@@ -425,7 +498,9 @@ def create_app() -> FastAPI:
425
498
  app.state.pause_waiter = pause_waiter
426
499
  app.state.session_lock = session_lock
427
500
  app.state.tool_router = tool_router
501
+ app.state.agent_registry = agent_registry
428
502
  app.state.workflow_registry = workflow_registry
503
+ app.state.step_profile_registry = step_profile_registry
429
504
  app.state.step_evaluator = step_evaluator
430
505
  app.state.agent_loop = agent_loop
431
506
  app.state.workflow_engine = workflow_engine
@@ -438,6 +513,8 @@ def create_app() -> FastAPI:
438
513
  app.state.recovered_session_ids = frozenset(recovered_sessions)
439
514
  app.state.recovered_task_ids = frozenset(recovered_tasks)
440
515
  app.state.recovered_paused_task_ids = frozenset(recovered_paused_tasks)
516
+ app.state.recovered_orphaned_step_runs = recovered_orphaned_step_runs
517
+ app.state.startup_invariant_reports = [report.as_dict() for report in invariant_reports]
441
518
 
442
519
  app.state.notification_service = notification_service
443
520
  app.state.turn_scheduler = turn_scheduler
@@ -488,6 +565,7 @@ def create_app() -> FastAPI:
488
565
  channel_manager_ref=_get_channel_manager,
489
566
  turn_scheduler=turn_scheduler,
490
567
  )
568
+ workflow_engine._channel_delivery = channel_delivery # noqa: SLF001
491
569
 
492
570
  app.state.channel_manager = channel_manager
493
571
  app.state.channel_delivery = channel_delivery
@@ -506,8 +584,24 @@ def create_app() -> FastAPI:
506
584
 
507
585
  await channel_delivery.start()
508
586
 
587
+ async def _session_lock_sweeper() -> None:
588
+ interval_seconds = 900.0
589
+ idle_seconds = 900.0
590
+ while True:
591
+ await asyncio.sleep(interval_seconds)
592
+ for session_id in session_lock.stale_unlocked_session_ids(
593
+ max_idle_seconds=idle_seconds
594
+ ):
595
+ session_lock.evict(session_id, reason="sweeper")
596
+
597
+ session_lock_sweeper_task = asyncio.create_task(_session_lock_sweeper())
598
+
509
599
  yield
510
600
 
601
+ if session_lock_sweeper_task is not None:
602
+ session_lock_sweeper_task.cancel()
603
+ with contextlib.suppress(asyncio.CancelledError):
604
+ await session_lock_sweeper_task
511
605
  await artifact_maintenance.stop()
512
606
  await channel_delivery.stop()
513
607
  await channel_manager.stop_all()
@@ -515,6 +609,7 @@ def create_app() -> FastAPI:
515
609
  await task_queue.stop()
516
610
  await shared_runtime.cleanup()
517
611
  await remember_queue.stop()
612
+ await tool_classification_queue.stop()
518
613
  await providers.executor.cleanup()
519
614
  await session_cache.aclose()
520
615
  await providers.memory.client.aclose()
@@ -6,6 +6,7 @@ import base64
6
6
  import json
7
7
  import re
8
8
  from collections.abc import Callable
9
+ from dataclasses import dataclass
9
10
  from datetime import datetime
10
11
  from typing import Any, cast
11
12
 
@@ -14,6 +15,8 @@ from fastapi.responses import JSONResponse
14
15
 
15
16
  from cognis.api.middleware import AuthenticatedUser
16
17
  from cognis.api.models import ErrorBody, ErrorResponse
18
+ from cognis.ownership import normalize_executor_scope
19
+ from cognis.store.queries import get_active_agent_grant
17
20
 
18
21
 
19
22
  def api_exception(
@@ -54,15 +57,21 @@ def require_current_user(request: Request) -> AuthenticatedUser:
54
57
  return user
55
58
 
56
59
 
57
- def require_jwt_user(request: Request) -> AuthenticatedUser:
58
- """Require a user authenticated with a JWT/session token."""
60
+ def require_session_user(request: Request) -> AuthenticatedUser:
61
+ """Require a human interactive session authenticated by cookie or bearer."""
59
62
 
60
63
  user = require_current_user(request)
61
- if user.auth_type != "jwt":
64
+ if user.auth_type not in {"jwt", "session"}:
62
65
  raise api_exception(403, "forbidden", "This endpoint requires session authentication")
63
66
  return user
64
67
 
65
68
 
69
+ def require_jwt_user(request: Request) -> AuthenticatedUser:
70
+ """Backward-compatible alias for interactive session auth."""
71
+
72
+ return require_session_user(request)
73
+
74
+
66
75
  def require_admin(request: Request) -> AuthenticatedUser:
67
76
  """Require the authenticated user to be an admin."""
68
77
  user = require_current_user(request)
@@ -79,6 +88,74 @@ def require_owner_or_admin(request: Request, owner_email: str) -> AuthenticatedU
79
88
  return user
80
89
 
81
90
 
91
+ def require_resource_owner(request: Request, owner_email: str) -> AuthenticatedUser:
92
+ """Require strict resource ownership with no admin bypass."""
93
+
94
+ user = require_current_user(request)
95
+ if user.email != owner_email:
96
+ raise api_exception(403, "forbidden", "Resource access denied")
97
+ return user
98
+
99
+
100
+ @dataclass(slots=True)
101
+ class AgentAccess:
102
+ """Resolved caller access to an agent."""
103
+
104
+ user: AuthenticatedUser
105
+ owner_email: str
106
+ is_owner: bool
107
+ grant: Any | None = None
108
+
109
+ @property
110
+ def granted_permission(self) -> str | None:
111
+ return str(self.grant.permission) if self.grant is not None else None
112
+
113
+ @property
114
+ def executor_scope(self) -> str | None:
115
+ return normalize_executor_scope(str(self.grant.executor_scope)) if self.grant is not None else None
116
+
117
+
118
+ async def check_agent_access(request: Request, agent: Any, *, required: str) -> AgentAccess:
119
+ """Resolve agent access for the caller.
120
+
121
+ ``required`` may be ``view``, ``use``, ``edit``, ``delete``, or ``share``.
122
+ Ownership is the only write path; active ``use`` grants permit only
123
+ ``view`` and ``use``. Admin role is intentionally ignored here.
124
+ """
125
+
126
+ user = require_current_user(request)
127
+ owner_email = str(getattr(agent, "owner_email", "") or "")
128
+ if not owner_email:
129
+ raise api_exception(500, "internal_error", "Agent owner is missing")
130
+ if user.email == owner_email:
131
+ return AgentAccess(user=user, owner_email=owner_email, is_owner=True)
132
+
133
+ if required not in {"view", "use", "edit", "delete", "share"}:
134
+ raise api_exception(500, "internal_error", f"Unsupported agent access requirement: {required}")
135
+ if required not in {"view", "use"}:
136
+ raise api_exception(403, "forbidden", "Resource access denied")
137
+
138
+ session_factory = getattr(request.app.state, "session_factory", None)
139
+ if session_factory is None:
140
+ raise api_exception(500, "internal_error", "Session factory unavailable")
141
+ async with session_factory() as session:
142
+ grant = await get_active_agent_grant(session, str(agent.agent_id), user.email)
143
+ if grant is None:
144
+ raise api_exception(403, "forbidden", "Resource access denied")
145
+ return AgentAccess(user=user, owner_email=owner_email, is_owner=False, grant=grant)
146
+
147
+
148
+ def apply_agent_access_metadata(agent: Any, access: AgentAccess) -> Any:
149
+ """Annotate an agent row/definition with caller-scoped sharing metadata."""
150
+
151
+ agent.is_shared_with_me = not access.is_owner
152
+ agent.shared_by_email = None if access.is_owner else access.owner_email
153
+ agent.granted_permission = access.granted_permission
154
+ agent.executor_scope = access.executor_scope
155
+ agent.is_readonly_for_caller = not access.is_owner
156
+ return agent
157
+
158
+
82
159
  def forbid_mutation_for_viewer(request: Request) -> None:
83
160
  """Reject mutation attempts from viewer accounts."""
84
161
  user = require_current_user(request)
@@ -9,7 +9,7 @@ from typing import Any
9
9
 
10
10
  from cognis.logging import get_logger
11
11
  from cognis.models.agent import AgentDefinition
12
- from cognis.models.tool import ExecutorCapabilities
12
+ from cognis.models.tool import ExecutorCapabilities, ToolDefinition
13
13
  from cognis.store.queries import get_executor_row, update_executor_runtime_state
14
14
  from cognis.tools.skills import resolve_skills_for_agent
15
15
 
@@ -247,7 +247,7 @@ async def _persist_runtime_state(
247
247
  runtime_metadata: dict[str, Any],
248
248
  ) -> None:
249
249
  async with app.state.session_factory() as session:
250
- await update_executor_runtime_state(
250
+ row = await update_executor_runtime_state(
251
251
  session,
252
252
  executor_id,
253
253
  applied_config_version=applied_config_version,
@@ -257,6 +257,22 @@ async def _persist_runtime_state(
257
257
  runtime_state=runtime_state,
258
258
  )
259
259
  await session.commit()
260
+ queue = getattr(app.state, "tool_classification_queue", None)
261
+ if queue is None or row is None or not observed_tools:
262
+ return
263
+ try:
264
+ tool_defs = [
265
+ ToolDefinition.model_validate(item)
266
+ for item in observed_tools
267
+ if isinstance(item, dict)
268
+ ]
269
+ await queue.enqueue_tools(tool_defs, owner_email=getattr(row, "owner_email", None))
270
+ except Exception:
271
+ _logger.warning(
272
+ "executor_runtime: failed to enqueue tool classifications",
273
+ extra={"extra_data": {"executor_id": executor_id, "observed_tools": len(observed_tools)}},
274
+ exc_info=True,
275
+ )
260
276
 
261
277
 
262
278
  async def _build_configure_payload(
@@ -266,6 +282,7 @@ async def _build_configure_payload(
266
282
  ) -> tuple[dict[str, Any], dict[str, Any]]:
267
283
  from cognis.api.executor_ws import _resolve_executor_mcp_payload
268
284
  from cognis.api.runtime_support import _resolve_web_config
285
+ from cognis.tools.skills import _qualified_skill_tool_name
269
286
 
270
287
  mcp_servers, scoped_secrets = await _resolve_executor_mcp_payload(row, app.state.providers)
271
288
  web_config = await _resolve_web_config(app.state.providers, row.owner_email)
@@ -287,19 +304,34 @@ async def _build_configure_payload(
287
304
  "skill_id": skill.skill_id,
288
305
  "version_id": skill.version_id,
289
306
  "content_hash": skill.content_hash,
290
- "tools": [t.model_dump(mode="json") for t in skill.tools],
307
+ "tools": [
308
+ {
309
+ **t.model_dump(mode="json"),
310
+ "qualified_name": _qualified_skill_tool_name(skill.skill_id, t.name),
311
+ }
312
+ for t in skill.tools
313
+ ],
291
314
  "asset_manifest": [a.model_dump(mode="json") for a in skill.asset_manifest],
292
315
  }
293
- artifact_store = getattr(app.state.providers, "artifact_store", None)
316
+ artifact_store = getattr(app.state, "artifact_store", None)
294
317
  if artifact_store and skill.asset_manifest:
318
+ ttl_seconds = getattr(
319
+ getattr(artifact_store, "_config", None), # noqa: SLF001
320
+ "signed_url_ttl_seconds",
321
+ None,
322
+ )
295
323
  for asset_entry in manifest["asset_manifest"]:
296
324
  ns = asset_entry.get("artifact_namespace", "skills")
297
325
  oid = asset_entry.get("artifact_object_id", "")
326
+ filename = asset_entry.get("filename", "")
298
327
  if oid:
299
328
  with contextlib.suppress(Exception):
300
- asset_entry[
301
- "signed_url"
302
- ] = await artifact_store.async_get_signed_url(ns, oid)
329
+ asset_entry["url"] = await artifact_store.async_get_public_url(
330
+ ns,
331
+ oid,
332
+ filename,
333
+ ttl_seconds=ttl_seconds,
334
+ )
303
335
  skill_manifests.append(manifest)
304
336
  except Exception:
305
337
  _logger.warning(
@@ -13,6 +13,7 @@ from cognis.api.executor_runtime import reconcile_executor
13
13
  from cognis.core.executor_policy import is_executor_type_allowed, load_executor_policy
14
14
  from cognis.logging import get_logger
15
15
  from cognis.models.tool import MCP_SERVER_IDS_KEY, ExecutorCapabilities, MCPServerConfig
16
+ from cognis.ownership import is_shared_owner_email
16
17
  from cognis.providers.executor.websocket import WebSocketExecutorProvider
17
18
  from cognis.store.queries import get_executor_row, get_mcp_server, update_executor_runtime_state
18
19
  from cognis.tools.mcp import invalid_mcp_config_reason
@@ -91,6 +92,7 @@ async def handle_executor_websocket(
91
92
  environment=params.get("environment"),
92
93
  platform=params.get("platform") or {},
93
94
  status=row.status,
95
+ owner_email=row.owner_email,
94
96
  ),
95
97
  )
96
98
 
@@ -251,11 +253,14 @@ def _executor_connection_metadata(
251
253
  environment: Any,
252
254
  platform: dict[str, Any],
253
255
  status: str,
256
+ owner_email: str | None,
254
257
  ) -> dict[str, Any]:
255
258
  metadata: dict[str, Any] = {
256
259
  "labels": labels,
257
260
  "platform": platform,
258
261
  "status": status,
262
+ "owner_email": owner_email,
263
+ "shared": is_shared_owner_email(owner_email),
259
264
  }
260
265
  if isinstance(environment, dict):
261
266
  metadata["environment"] = environment
@@ -14,7 +14,12 @@ from starlette.responses import Response
14
14
  from cognis.api.models import ErrorBody, ErrorResponse
15
15
  from cognis.runtime_context import current_user_email
16
16
  from cognis.security import parse_api_key, verify_api_key
17
- from cognis.store.queries import get_api_key, get_user, touch_api_key_last_used
17
+ from cognis.store.queries import (
18
+ get_api_key,
19
+ get_browser_session_by_token,
20
+ get_user,
21
+ touch_api_key_last_used,
22
+ )
18
23
 
19
24
  PUBLIC_ROUTES = {
20
25
  ("GET", "/api/bootstrap-status"),
@@ -177,20 +182,28 @@ class AuthenticationMiddleware(BaseHTTPMiddleware):
177
182
  finally:
178
183
  current_user_email.reset(context_token)
179
184
 
180
- # Fallback: check cognis_session cookie (cross-service SSO)
185
+ # Fallback: check opaque browser session cookie.
181
186
  if cookie_token:
182
- try:
183
- claims = auth_provider.verify_jwt(cookie_token, audience=["cognis"])
184
- except Exception:
185
- return JSONResponse(
186
- status_code=401,
187
- content=ErrorResponse(
188
- error=ErrorBody(code="unauthorized", message="Invalid session cookie")
189
- ).model_dump(),
190
- )
191
- # Check if user is disabled
192
187
  async with session_factory() as session:
193
- user_row = await get_user(session, str(claims["sub"]))
188
+ browser_session = await get_browser_session_by_token(session, cookie_token)
189
+ if browser_session is None or browser_session.revoked_at is not None:
190
+ return JSONResponse(
191
+ status_code=401,
192
+ content=ErrorResponse(
193
+ error=ErrorBody(code="unauthorized", message="Invalid session cookie")
194
+ ).model_dump(),
195
+ )
196
+ expires_at = browser_session.expires_at
197
+ if expires_at.tzinfo is None:
198
+ expires_at = expires_at.replace(tzinfo=UTC)
199
+ if expires_at < datetime.now(UTC):
200
+ return JSONResponse(
201
+ status_code=401,
202
+ content=ErrorResponse(
203
+ error=ErrorBody(code="unauthorized", message="Session expired")
204
+ ).model_dump(),
205
+ )
206
+ user_row = await get_user(session, browser_session.user_email)
194
207
  if user_row is not None and not user_row.is_active:
195
208
  return JSONResponse(
196
209
  status_code=403,
@@ -198,16 +211,23 @@ class AuthenticationMiddleware(BaseHTTPMiddleware):
198
211
  error=ErrorBody(code="account_disabled", message="Account disabled")
199
212
  ).model_dump(),
200
213
  )
201
- context_token = current_user_email.set(str(claims["sub"]))
214
+ if user_row is None:
215
+ return JSONResponse(
216
+ status_code=401,
217
+ content=ErrorResponse(
218
+ error=ErrorBody(code="unauthorized", message="Unknown session owner")
219
+ ).model_dump(),
220
+ )
221
+ context_token = current_user_email.set(user_row.email)
202
222
  request.state.user = AuthenticatedUser(
203
- email=str(claims["sub"]),
204
- role=str(claims.get("role", "user")),
205
- name=claims.get("name"),
206
- auth_type="cookie",
223
+ email=user_row.email,
224
+ role=user_row.role,
225
+ name=user_row.name,
226
+ auth_type="session",
207
227
  )
208
- request.state.claims = claims
228
+ request.state.browser_session_id = browser_session.session_id
209
229
  if api_rate_limiter is not None and not await api_rate_limiter.allow(
210
- user_key=str(claims["sub"]),
230
+ user_key=user_row.email,
211
231
  path=request.url.path,
212
232
  method=request.method,
213
233
  ):