igni-core 1.0.4__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 (1038) hide show
  1. igni_core/__init__.py +37 -0
  2. igni_core/__main__.py +19 -0
  3. igni_core/_torchvision_shim.py +67 -0
  4. igni_core/alembic.ini +52 -0
  5. igni_core/backend/__init__.py +5 -0
  6. igni_core/backend/__main__.py +134 -0
  7. igni_core/backend/activity.py +112 -0
  8. igni_core/backend/activity_nudge.py +43 -0
  9. igni_core/backend/agent_framing.py +82 -0
  10. igni_core/backend/agent_refresh.py +49 -0
  11. igni_core/backend/agno_decision_applier.py +69 -0
  12. igni_core/backend/agno_history_plan_scanner.py +114 -0
  13. igni_core/backend/app.py +321 -0
  14. igni_core/backend/backend_bootstrap.py +133 -0
  15. igni_core/backend/backend_notifications.py +71 -0
  16. igni_core/backend/browser_opener.py +35 -0
  17. igni_core/backend/browser_sign_in.py +115 -0
  18. igni_core/backend/builtin_command_registry.py +286 -0
  19. igni_core/backend/captured_shell_runner.py +129 -0
  20. igni_core/backend/chat_history_searcher.py +132 -0
  21. igni_core/backend/cloud_sign_out.py +41 -0
  22. igni_core/backend/cmd_agents.py +110 -0
  23. igni_core/backend/cmd_auth.py +123 -0
  24. igni_core/backend/cmd_config.py +34 -0
  25. igni_core/backend/cmd_context.py +181 -0
  26. igni_core/backend/cmd_eject.py +163 -0
  27. igni_core/backend/cmd_evals.py +41 -0
  28. igni_core/backend/cmd_help.py +72 -0
  29. igni_core/backend/cmd_hooks.py +54 -0
  30. igni_core/backend/cmd_loop.py +269 -0
  31. igni_core/backend/cmd_memory.py +115 -0
  32. igni_core/backend/cmd_misc.py +130 -0
  33. igni_core/backend/cmd_model.py +45 -0
  34. igni_core/backend/cmd_modes.py +334 -0
  35. igni_core/backend/cmd_plugin/__init__.py +15 -0
  36. igni_core/backend/cmd_plugin/bulk_refresh.py +59 -0
  37. igni_core/backend/cmd_plugin/commands.py +138 -0
  38. igni_core/backend/cmd_plugin/context.py +43 -0
  39. igni_core/backend/cmd_plugin/gateway.py +173 -0
  40. igni_core/backend/cmd_plugin/routers.py +122 -0
  41. igni_core/backend/cmd_plugin/verbs.py +364 -0
  42. igni_core/backend/cmd_schedule.py +208 -0
  43. igni_core/backend/cmd_session.py +202 -0
  44. igni_core/backend/cold_spawn_resume.py +349 -0
  45. igni_core/backend/command_handler.py +159 -0
  46. igni_core/backend/command_result.py +173 -0
  47. igni_core/backend/controller_registry.py +250 -0
  48. igni_core/backend/dir_scanner.py +60 -0
  49. igni_core/backend/extension_startup.py +137 -0
  50. igni_core/backend/extensions_runtime.py +153 -0
  51. igni_core/backend/file_completion_service.py +36 -0
  52. igni_core/backend/file_opener.py +76 -0
  53. igni_core/backend/first_window.py +56 -0
  54. igni_core/backend/folder_picker.py +117 -0
  55. igni_core/backend/group_pack_hydrator.py +127 -0
  56. igni_core/backend/group_policy_sync.py +185 -0
  57. igni_core/backend/headless_extensions.py +313 -0
  58. igni_core/backend/hitl_controller.py +317 -0
  59. igni_core/backend/hitl_permissions.py +110 -0
  60. igni_core/backend/hitl_stream_mux.py +368 -0
  61. igni_core/backend/hitl_tracer.py +88 -0
  62. igni_core/backend/host_backend.py +185 -0
  63. igni_core/backend/host_model_runtime.py +84 -0
  64. igni_core/backend/host_model_wiring.py +107 -0
  65. igni_core/backend/igni_server_access.py +40 -0
  66. igni_core/backend/in_flight_tasks.py +37 -0
  67. igni_core/backend/inline_think_splitter.py +75 -0
  68. igni_core/backend/keyboard_shortcuts_help.py +67 -0
  69. igni_core/backend/lockfile.py +326 -0
  70. igni_core/backend/logging_setup.py +134 -0
  71. igni_core/backend/login_coordinator.py +103 -0
  72. igni_core/backend/markdown_command_dispatcher.py +133 -0
  73. igni_core/backend/marketplace_controller.py +86 -0
  74. igni_core/backend/message_admission.py +92 -0
  75. igni_core/backend/message_dispatcher.py +432 -0
  76. igni_core/backend/model_http_client_manager.py +142 -0
  77. igni_core/backend/model_switcher.py +71 -0
  78. igni_core/backend/observed_transport.py +89 -0
  79. igni_core/backend/panels/__init__.py +30 -0
  80. igni_core/backend/panels/agents_panel.py +73 -0
  81. igni_core/backend/panels/hooks_panel.py +38 -0
  82. igni_core/backend/panels/output_styles_catalog.py +35 -0
  83. igni_core/backend/panels/skills_panel.py +49 -0
  84. igni_core/backend/panels/slash_commands_catalog.py +101 -0
  85. igni_core/backend/pause_handler.py +195 -0
  86. igni_core/backend/pending_message_journal.py +119 -0
  87. igni_core/backend/pending_requirements_store.py +204 -0
  88. igni_core/backend/plan_snapshot_builder.py +51 -0
  89. igni_core/backend/plugin_bundle_files.py +91 -0
  90. igni_core/backend/plugin_controller.py +355 -0
  91. igni_core/backend/plugin_directory_scanner.py +162 -0
  92. igni_core/backend/plugin_schemas.py +439 -0
  93. igni_core/backend/pool_directories.py +101 -0
  94. igni_core/backend/pool_replier.py +81 -0
  95. igni_core/backend/pool_rpcs/__init__.py +38 -0
  96. igni_core/backend/pool_rpcs/approver_tokens.py +60 -0
  97. igni_core/backend/pool_rpcs/attach_session.py +79 -0
  98. igni_core/backend/pool_rpcs/base.py +98 -0
  99. igni_core/backend/pool_rpcs/host_model.py +220 -0
  100. igni_core/backend/pool_rpcs/page_token.py +51 -0
  101. igni_core/backend/pool_rpcs/platform_calls.py +136 -0
  102. igni_core/backend/pool_rpcs/router.py +52 -0
  103. igni_core/backend/pool_wiring.py +97 -0
  104. igni_core/backend/process_environment.py +35 -0
  105. igni_core/backend/prompt_builder.py +235 -0
  106. igni_core/backend/push_bridge.py +421 -0
  107. igni_core/backend/push_payloads.py +178 -0
  108. igni_core/backend/restore_content.py +112 -0
  109. igni_core/backend/rpc_binding.py +191 -0
  110. igni_core/backend/rpc_errors.py +32 -0
  111. igni_core/backend/rpc_handlers/__init__.py +59 -0
  112. igni_core/backend/rpc_handlers/auth.py +139 -0
  113. igni_core/backend/rpc_handlers/base.py +97 -0
  114. igni_core/backend/rpc_handlers/extensions.py +110 -0
  115. igni_core/backend/rpc_handlers/hooks.py +34 -0
  116. igni_core/backend/rpc_handlers/loop.py +130 -0
  117. igni_core/backend/rpc_handlers/mcp.py +140 -0
  118. igni_core/backend/rpc_handlers/models.py +174 -0
  119. igni_core/backend/rpc_handlers/notifications.py +100 -0
  120. igni_core/backend/rpc_handlers/panel_args.py +134 -0
  121. igni_core/backend/rpc_handlers/panels.py +304 -0
  122. igni_core/backend/rpc_handlers/plan.py +78 -0
  123. igni_core/backend/rpc_handlers/plugins.py +269 -0
  124. igni_core/backend/rpc_handlers/pool_guard.py +62 -0
  125. igni_core/backend/rpc_handlers/scheduler.py +144 -0
  126. igni_core/backend/rpc_handlers/session.py +239 -0
  127. igni_core/backend/rpc_handlers/session_args.py +68 -0
  128. igni_core/backend/rpc_handlers/session_history.py +102 -0
  129. igni_core/backend/rpc_handlers/skills.py +49 -0
  130. igni_core/backend/rpc_handlers/workflows.py +92 -0
  131. igni_core/backend/rpc_handlers/workspace_trust.py +83 -0
  132. igni_core/backend/rpc_result.py +43 -0
  133. igni_core/backend/rpc_router.py +171 -0
  134. igni_core/backend/rpc_streams.py +58 -0
  135. igni_core/backend/rpc_watch.py +60 -0
  136. igni_core/backend/run_controller.py +585 -0
  137. igni_core/backend/run_hook_gate.py +100 -0
  138. igni_core/backend/schemas_agents.py +73 -0
  139. igni_core/backend/schemas_auth.py +158 -0
  140. igni_core/backend/schemas_config.py +126 -0
  141. igni_core/backend/schemas_context.py +267 -0
  142. igni_core/backend/schemas_evals.py +43 -0
  143. igni_core/backend/schemas_extensions.py +292 -0
  144. igni_core/backend/schemas_help.py +297 -0
  145. igni_core/backend/schemas_history.py +415 -0
  146. igni_core/backend/schemas_hitl.py +219 -0
  147. igni_core/backend/schemas_hooks.py +70 -0
  148. igni_core/backend/schemas_lifecycle.py +309 -0
  149. igni_core/backend/schemas_lockfile.py +225 -0
  150. igni_core/backend/schemas_loop.py +237 -0
  151. igni_core/backend/schemas_mcp.py +147 -0
  152. igni_core/backend/schemas_memory.py +193 -0
  153. igni_core/backend/schemas_model.py +56 -0
  154. igni_core/backend/schemas_panels.py +230 -0
  155. igni_core/backend/schemas_pause.py +192 -0
  156. igni_core/backend/schemas_plan.py +52 -0
  157. igni_core/backend/schemas_pool.py +197 -0
  158. igni_core/backend/schemas_processes.py +67 -0
  159. igni_core/backend/schemas_rpc.py +378 -0
  160. igni_core/backend/schemas_run.py +198 -0
  161. igni_core/backend/schemas_scheduler.py +194 -0
  162. igni_core/backend/schemas_search.py +77 -0
  163. igni_core/backend/schemas_sessions.py +214 -0
  164. igni_core/backend/schemas_visualization.py +55 -0
  165. igni_core/backend/schemas_workflow_events.py +325 -0
  166. igni_core/backend/schemas_workflows.py +319 -0
  167. igni_core/backend/search_cache.py +53 -0
  168. igni_core/backend/search_strategies.py +222 -0
  169. igni_core/backend/server.py +501 -0
  170. igni_core/backend/server_auth.py +175 -0
  171. igni_core/backend/server_context.py +285 -0
  172. igni_core/backend/server_files.py +264 -0
  173. igni_core/backend/server_history.py +248 -0
  174. igni_core/backend/server_history_walker.py +295 -0
  175. igni_core/backend/server_interrupted_run.py +191 -0
  176. igni_core/backend/server_lifecycle.py +141 -0
  177. igni_core/backend/server_loop.py +107 -0
  178. igni_core/backend/server_mcp.py +146 -0
  179. igni_core/backend/server_panels.py +143 -0
  180. igni_core/backend/server_processes.py +128 -0
  181. igni_core/backend/server_rehydrate.py +203 -0
  182. igni_core/backend/server_scheduler.py +309 -0
  183. igni_core/backend/server_search.py +103 -0
  184. igni_core/backend/server_sessions.py +145 -0
  185. igni_core/backend/server_shutdown.py +166 -0
  186. igni_core/backend/service_event_delivery.py +173 -0
  187. igni_core/backend/service_event_ingress.py +82 -0
  188. igni_core/backend/service_item_desk.py +175 -0
  189. igni_core/backend/serving_backend.py +95 -0
  190. igni_core/backend/session_checkpointer.py +101 -0
  191. igni_core/backend/session_orchestrator.py +195 -0
  192. igni_core/backend/session_pool.py +394 -0
  193. igni_core/backend/session_router.py +97 -0
  194. igni_core/backend/session_runtime_factory.py +114 -0
  195. igni_core/backend/session_stamping_transport.py +61 -0
  196. igni_core/backend/settings_loader.py +40 -0
  197. igni_core/backend/skill_command_dispatcher.py +47 -0
  198. igni_core/backend/slash_command.py +41 -0
  199. igni_core/backend/standing_policy.py +144 -0
  200. igni_core/backend/stream_event_dispatcher.py +81 -0
  201. igni_core/backend/supervisor.py +495 -0
  202. igni_core/backend/team_wiring.py +84 -0
  203. igni_core/backend/transport_builder.py +72 -0
  204. igni_core/backend/visualization_action_bus.py +44 -0
  205. igni_core/backend/workflow_agent_bridge.py +92 -0
  206. igni_core/backend/workflow_discovery.py +128 -0
  207. igni_core/backend/workflow_layers.py +120 -0
  208. igni_core/backend/workflow_run.py +184 -0
  209. igni_core/backend/workflow_run_registry.py +90 -0
  210. igni_core/backend/workflow_runner.py +114 -0
  211. igni_core/backend/workflow_runtime.mjs +491 -0
  212. igni_core/backend/workflow_runtime_process.py +212 -0
  213. igni_core/backend/workspace_signals.py +77 -0
  214. igni_core/backend/workspace_trust_controller.py +153 -0
  215. igni_core/backend/workspace_watch.py +271 -0
  216. igni_core/bundled_agents/architect.md +157 -0
  217. igni_core/bundled_agents/debugger.md +204 -0
  218. igni_core/bundled_agents/docs.md +336 -0
  219. igni_core/bundled_agents/editor.md +308 -0
  220. igni_core/bundled_agents/explorer.md +154 -0
  221. igni_core/bundled_agents/plan_researcher.md +96 -0
  222. igni_core/bundled_agents/qa.md +206 -0
  223. igni_core/bundled_agents/reviewer.md +163 -0
  224. igni_core/bundled_agents/security.md +183 -0
  225. igni_core/bundled_agents/simplifier.md +182 -0
  226. igni_core/bundled_agents/visualizer.md +245 -0
  227. igni_core/bundled_skills/commit/SKILL.md +55 -0
  228. igni_core/bundled_skills/explain/SKILL.md +67 -0
  229. igni_core/bundled_skills/migration/SKILL.md +80 -0
  230. igni_core/bundled_skills/pr/SKILL.md +81 -0
  231. igni_core/bundled_skills/test-plan/SKILL.md +119 -0
  232. igni_core/cli/__init__.py +219 -0
  233. igni_core/cli/context.py +27 -0
  234. igni_core/cli/ext.py +484 -0
  235. igni_core/cli/ext_doctor.py +242 -0
  236. igni_core/cli/ext_manifest_check.py +133 -0
  237. igni_core/cli/ext_scaffold.py +222 -0
  238. igni_core/cli/ext_scaffold_templates.py +488 -0
  239. igni_core/cli/headless_run.py +114 -0
  240. igni_core/cli/invocation.py +229 -0
  241. igni_core/cli/logging.py +101 -0
  242. igni_core/cli/login.py +92 -0
  243. igni_core/cli/migrate.py +108 -0
  244. igni_core/cli/options.py +60 -0
  245. igni_core/cli/resume.py +98 -0
  246. igni_core/cli/run_settings.py +97 -0
  247. igni_core/cli/trust.py +210 -0
  248. igni_core/contracts/__init__.py +11 -0
  249. igni_core/contracts/wire_schema.py +208 -0
  250. igni_core/core/__init__.py +0 -0
  251. igni_core/core/activity/__init__.py +14 -0
  252. igni_core/core/activity/background.py +222 -0
  253. igni_core/core/activity/http.py +154 -0
  254. igni_core/core/activity/http2.py +93 -0
  255. igni_core/core/activity/registry.py +270 -0
  256. igni_core/core/agents/__init__.py +43 -0
  257. igni_core/core/agents/builder.py +251 -0
  258. igni_core/core/agents/catalog.py +19 -0
  259. igni_core/core/agents/contributions.py +89 -0
  260. igni_core/core/agents/ephemeral.py +291 -0
  261. igni_core/core/agents/loader.py +161 -0
  262. igni_core/core/agents/markdown.py +167 -0
  263. igni_core/core/agents/plugin_policy.py +78 -0
  264. igni_core/core/agents/pool.py +309 -0
  265. igni_core/core/agents/schemas.py +335 -0
  266. igni_core/core/agents/tool_audience.py +70 -0
  267. igni_core/core/agents/tool_check.py +69 -0
  268. igni_core/core/agents/trained_layout.py +70 -0
  269. igni_core/core/agno_telemetry.py +122 -0
  270. igni_core/core/air_gap.py +43 -0
  271. igni_core/core/approvals/__init__.py +5 -0
  272. igni_core/core/approvals/declined.py +23 -0
  273. igni_core/core/approvals/events.py +78 -0
  274. igni_core/core/approvals/journal.py +240 -0
  275. igni_core/core/approvals/journal_table.py +58 -0
  276. igni_core/core/approvals/records.py +56 -0
  277. igni_core/core/approvals/spawn_links.py +108 -0
  278. igni_core/core/approvals/tables.py +75 -0
  279. igni_core/core/approvals/turn_results.py +65 -0
  280. igni_core/core/auth/__init__.py +52 -0
  281. igni_core/core/auth/_success_page.py +58 -0
  282. igni_core/core/auth/callback_server.py +287 -0
  283. igni_core/core/auth/credentials.py +414 -0
  284. igni_core/core/auth/discovery.py +195 -0
  285. igni_core/core/auth/discovery_schemas.py +98 -0
  286. igni_core/core/auth/http_auth.py +69 -0
  287. igni_core/core/auth/portal_client.py +306 -0
  288. igni_core/core/auth/schemas.py +206 -0
  289. igni_core/core/auth/server_url.py +28 -0
  290. igni_core/core/broadcast_schema.py +51 -0
  291. igni_core/core/config/__init__.py +1 -0
  292. igni_core/core/config/accumulator.py +91 -0
  293. igni_core/core/config/anthropic_auth.py +76 -0
  294. igni_core/core/config/caller_inspector.py +54 -0
  295. igni_core/core/config/checked_gemini.py +49 -0
  296. igni_core/core/config/cli_overrides.py +173 -0
  297. igni_core/core/config/cloud_model_migrator.py +106 -0
  298. igni_core/core/config/cloud_models.py +285 -0
  299. igni_core/core/config/config_io.py +89 -0
  300. igni_core/core/config/context_window.py +206 -0
  301. igni_core/core/config/endpoint.py +132 -0
  302. igni_core/core/config/group_policy/__init__.py +41 -0
  303. igni_core/core/config/group_policy/answers.py +54 -0
  304. igni_core/core/config/group_policy/cache.py +121 -0
  305. igni_core/core/config/group_policy/entry.py +164 -0
  306. igni_core/core/config/group_policy/environment.py +37 -0
  307. igni_core/core/config/group_policy/gate.py +58 -0
  308. igni_core/core/config/group_policy/hooks.py +119 -0
  309. igni_core/core/config/group_policy/issuer.py +45 -0
  310. igni_core/core/config/group_policy/jwks.py +82 -0
  311. igni_core/core/config/group_policy/jws.py +128 -0
  312. igni_core/core/config/group_policy/kinds.py +208 -0
  313. igni_core/core/config/group_policy/layout.py +137 -0
  314. igni_core/core/config/group_policy/materializer.py +104 -0
  315. igni_core/core/config/group_policy/meta.py +114 -0
  316. igni_core/core/config/group_policy/pack.py +134 -0
  317. igni_core/core/config/group_policy/plugins.py +155 -0
  318. igni_core/core/config/group_policy/policy_settings.py +43 -0
  319. igni_core/core/config/group_policy/refresher.py +143 -0
  320. igni_core/core/config/group_policy/response.py +52 -0
  321. igni_core/core/config/group_policy/revalidation.py +29 -0
  322. igni_core/core/config/group_policy/settings_fetcher.py +202 -0
  323. igni_core/core/config/group_policy/signature.py +202 -0
  324. igni_core/core/config/group_policy/signed_store.py +143 -0
  325. igni_core/core/config/group_policy/signing_key.py +87 -0
  326. igni_core/core/config/group_policy/transport.py +106 -0
  327. igni_core/core/config/group_policy/trust.py +90 -0
  328. igni_core/core/config/group_policy/verifier.py +75 -0
  329. igni_core/core/config/llm_call_logger.py +148 -0
  330. igni_core/core/config/logging_claude.py +137 -0
  331. igni_core/core/config/logging_model.py +158 -0
  332. igni_core/core/config/managed_policy.py +117 -0
  333. igni_core/core/config/merge_plan.py +195 -0
  334. igni_core/core/config/message_sanitizer.py +109 -0
  335. igni_core/core/config/model_entry.py +308 -0
  336. igni_core/core/config/model_stream.py +186 -0
  337. igni_core/core/config/models.py +249 -0
  338. igni_core/core/config/null_model.py +117 -0
  339. igni_core/core/config/organisation_tiers.py +116 -0
  340. igni_core/core/config/permission_eval/__init__.py +130 -0
  341. igni_core/core/config/permission_eval/catalog.py +234 -0
  342. igni_core/core/config/permission_eval/mode_policy.py +164 -0
  343. igni_core/core/config/permission_eval/pipe_filters.py +241 -0
  344. igni_core/core/config/permission_eval/pipeline.py +566 -0
  345. igni_core/core/config/permission_eval/read_only_shell.py +318 -0
  346. igni_core/core/config/permission_eval/resolver.py +104 -0
  347. igni_core/core/config/permission_eval/schemas.py +282 -0
  348. igni_core/core/config/permission_eval/strategies.py +300 -0
  349. igni_core/core/config/permissions/__init__.py +24 -0
  350. igni_core/core/config/permissions/schemas.py +21 -0
  351. igni_core/core/config/provider_builders.py +395 -0
  352. igni_core/core/config/provider_catalog.py +87 -0
  353. igni_core/core/config/reply_ending.py +269 -0
  354. igni_core/core/config/schemas/__init__.py +65 -0
  355. igni_core/core/config/schemas/display.py +48 -0
  356. igni_core/core/config/schemas/extensions.py +34 -0
  357. igni_core/core/config/schemas/llm_behavior.py +92 -0
  358. igni_core/core/config/schemas/models.py +63 -0
  359. igni_core/core/config/schemas/network.py +28 -0
  360. igni_core/core/config/schemas/orchestration.py +91 -0
  361. igni_core/core/config/schemas/permissions.py +234 -0
  362. igni_core/core/config/schemas/plugins.py +33 -0
  363. igni_core/core/config/schemas/safety.py +73 -0
  364. igni_core/core/config/schemas/storage_and_paths.py +114 -0
  365. igni_core/core/config/schemas/telemetry.py +110 -0
  366. igni_core/core/config/secret_scan.py +140 -0
  367. igni_core/core/config/settings.py +149 -0
  368. igni_core/core/config/settings_loader.py +114 -0
  369. igni_core/core/config/tiers/__init__.py +10 -0
  370. igni_core/core/config/tiers/base.py +17 -0
  371. igni_core/core/config/tiers/cli.py +78 -0
  372. igni_core/core/config/tiers/cloud_migration.py +35 -0
  373. igni_core/core/config/tiers/developer.py +80 -0
  374. igni_core/core/config/tiers/files.py +36 -0
  375. igni_core/core/config/tiers/group_policy.py +133 -0
  376. igni_core/core/config/tiers/managed.py +99 -0
  377. igni_core/core/config/tiers/organisation.py +76 -0
  378. igni_core/core/config/tiers/project.py +203 -0
  379. igni_core/core/config/tiers/raw_model_registry.py +64 -0
  380. igni_core/core/config/tool_names.py +267 -0
  381. igni_core/core/config/tool_permissions/__init__.py +110 -0
  382. igni_core/core/config/tool_permissions/schemas.py +444 -0
  383. igni_core/core/config/tool_permissions/settings_files.py +242 -0
  384. igni_core/core/config/tool_permissions/store.py +248 -0
  385. igni_core/core/config/tool_permissions/tool_invocation.py +131 -0
  386. igni_core/core/config/tool_permissions/tool_name_resolver.py +104 -0
  387. igni_core/core/config/user_config_store.py +110 -0
  388. igni_core/core/contributed_commands.py +95 -0
  389. igni_core/core/data_paths.py +214 -0
  390. igni_core/core/db/__init__.py +22 -0
  391. igni_core/core/db/agno_schema.py +130 -0
  392. igni_core/core/db/base.py +14 -0
  393. igni_core/core/db/database.py +68 -0
  394. igni_core/core/db/engine.py +21 -0
  395. igni_core/core/db/engine_registry.py +276 -0
  396. igni_core/core/db/locator.py +110 -0
  397. igni_core/core/db/migrations.py +147 -0
  398. igni_core/core/db/providers.py +120 -0
  399. igni_core/core/db/schema.py +92 -0
  400. igni_core/core/db/scope.py +185 -0
  401. igni_core/core/db/upsert.py +41 -0
  402. igni_core/core/db/urls.py +154 -0
  403. igni_core/core/decisions/__init__.py +27 -0
  404. igni_core/core/decisions/endpoints.py +158 -0
  405. igni_core/core/decisions/laya.py +160 -0
  406. igni_core/core/decisions/laya_wire.py +174 -0
  407. igni_core/core/decisions/schemas.py +198 -0
  408. igni_core/core/decisions/service_wire.py +53 -0
  409. igni_core/core/dir_migration.py +124 -0
  410. igni_core/core/evals/__init__.py +13 -0
  411. igni_core/core/evals/agno_adapter.py +227 -0
  412. igni_core/core/evals/assertion_runner.py +369 -0
  413. igni_core/core/evals/assertions.py +124 -0
  414. igni_core/core/evals/loader.py +203 -0
  415. igni_core/core/evals/reporter.py +94 -0
  416. igni_core/core/evals/runner.py +387 -0
  417. igni_core/core/evals/schemas.py +342 -0
  418. igni_core/core/evals/tool_names.py +121 -0
  419. igni_core/core/evals/workspace.py +170 -0
  420. igni_core/core/guardrails/__init__.py +28 -0
  421. igni_core/core/guardrails/base.py +88 -0
  422. igni_core/core/guardrails/injection.py +54 -0
  423. igni_core/core/guardrails/moderation.py +28 -0
  424. igni_core/core/guardrails/pii.py +60 -0
  425. igni_core/core/guardrails/runner.py +107 -0
  426. igni_core/core/hitl/__init__.py +13 -0
  427. igni_core/core/hitl/ledger.py +125 -0
  428. igni_core/core/hitl/models.py +169 -0
  429. igni_core/core/hitl/registry.py +167 -0
  430. igni_core/core/hitl/relay.py +33 -0
  431. igni_core/core/hitl/trace.py +63 -0
  432. igni_core/core/hitl/turns.py +70 -0
  433. igni_core/core/hooks/__init__.py +33 -0
  434. igni_core/core/hooks/agno_coroutine_marker.py +42 -0
  435. igni_core/core/hooks/bypass_explainer.py +139 -0
  436. igni_core/core/hooks/bypass_guard.py +276 -0
  437. igni_core/core/hooks/bypass_judge.py +98 -0
  438. igni_core/core/hooks/bypass_rules.py +257 -0
  439. igni_core/core/hooks/bypass_tool_kind.py +107 -0
  440. igni_core/core/hooks/envelope.py +133 -0
  441. igni_core/core/hooks/events.py +80 -0
  442. igni_core/core/hooks/executor.py +352 -0
  443. igni_core/core/hooks/extension_gate.py +120 -0
  444. igni_core/core/hooks/extension_spec.py +100 -0
  445. igni_core/core/hooks/extension_values.py +95 -0
  446. igni_core/core/hooks/group_hook_decisions.py +145 -0
  447. igni_core/core/hooks/group_hook_gate.py +205 -0
  448. igni_core/core/hooks/handlers/__init__.py +23 -0
  449. igni_core/core/hooks/handlers/base.py +57 -0
  450. igni_core/core/hooks/handlers/command.py +166 -0
  451. igni_core/core/hooks/handlers/http.py +81 -0
  452. igni_core/core/hooks/handlers/mcp_tool.py +137 -0
  453. igni_core/core/hooks/handlers/prompt.py +35 -0
  454. igni_core/core/hooks/handlers/registry.py +115 -0
  455. igni_core/core/hooks/hook_firer.py +76 -0
  456. igni_core/core/hooks/load_result.py +38 -0
  457. igni_core/core/hooks/loader.py +299 -0
  458. igni_core/core/hooks/matcher.py +80 -0
  459. igni_core/core/hooks/memory_sync.py +42 -0
  460. igni_core/core/hooks/merger.py +67 -0
  461. igni_core/core/hooks/payload_sanitizer.py +69 -0
  462. igni_core/core/hooks/permission/__init__.py +9 -0
  463. igni_core/core/hooks/permission/blocked_command_stage.py +56 -0
  464. igni_core/core/hooks/permission/bypass_guard_stage.py +26 -0
  465. igni_core/core/hooks/permission/context.py +66 -0
  466. igni_core/core/hooks/permission/denial.py +67 -0
  467. igni_core/core/hooks/permission/evaluator_stage.py +112 -0
  468. igni_core/core/hooks/permission/outcome.py +30 -0
  469. igni_core/core/hooks/permission/pipeline.py +63 -0
  470. igni_core/core/hooks/permission/pre_tool_use_stage.py +81 -0
  471. igni_core/core/hooks/permission/protected_path_stage.py +90 -0
  472. igni_core/core/hooks/permission/stage.py +20 -0
  473. igni_core/core/hooks/queue/__init__.py +71 -0
  474. igni_core/core/hooks/queue/agno_adapter.py +87 -0
  475. igni_core/core/hooks/queue/bridge.py +79 -0
  476. igni_core/core/hooks/queue/buffer.py +73 -0
  477. igni_core/core/hooks/queue/injector.py +145 -0
  478. igni_core/core/hooks/queue/persister.py +74 -0
  479. igni_core/core/hooks/queue/schemas.py +170 -0
  480. igni_core/core/hooks/registry.py +199 -0
  481. igni_core/core/hooks/rules_suffixer.py +134 -0
  482. igni_core/core/hooks/schemas.py +336 -0
  483. igni_core/core/hooks/tool_call_invoker.py +108 -0
  484. igni_core/core/hooks/tool_events.py +146 -0
  485. igni_core/core/hooks/tool_hook.py +233 -0
  486. igni_core/core/hooks/turn_results.py +55 -0
  487. igni_core/core/hooks/untrusted.py +206 -0
  488. igni_core/core/init/__init__.py +36 -0
  489. igni_core/core/init/checksum_store.py +171 -0
  490. igni_core/core/init/gitignore.py +118 -0
  491. igni_core/core/init/home_migrator.py +119 -0
  492. igni_core/core/init/hook_provisioner.py +95 -0
  493. igni_core/core/init/hooks_catalog.py +49 -0
  494. igni_core/core/init/json_file.py +106 -0
  495. igni_core/core/init/project_initializer.py +244 -0
  496. igni_core/core/init/schemas.py +430 -0
  497. igni_core/core/init_templates.py +179 -0
  498. igni_core/core/layer.py +230 -0
  499. igni_core/core/learn.py +174 -0
  500. igni_core/core/log_fields.py +48 -0
  501. igni_core/core/loop/__init__.py +36 -0
  502. igni_core/core/loop/db_models.py +75 -0
  503. igni_core/core/loop/limits.py +22 -0
  504. igni_core/core/loop/models.py +42 -0
  505. igni_core/core/loop/prompt.py +86 -0
  506. igni_core/core/loop/store.py +242 -0
  507. igni_core/core/loop/tool_results.py +279 -0
  508. igni_core/core/lsp/__init__.py +43 -0
  509. igni_core/core/lsp/client.py +366 -0
  510. igni_core/core/lsp/loader.py +252 -0
  511. igni_core/core/lsp/manager.py +122 -0
  512. igni_core/core/lsp/schemas.py +353 -0
  513. igni_core/core/mcp/__init__.py +27 -0
  514. igni_core/core/mcp/approval.py +190 -0
  515. igni_core/core/mcp/client.py +581 -0
  516. igni_core/core/mcp/config.py +254 -0
  517. igni_core/core/mcp/hints.py +158 -0
  518. igni_core/core/mcp/naming.py +64 -0
  519. igni_core/core/mcp/notification_tap.py +102 -0
  520. igni_core/core/mcp/request_meta.py +62 -0
  521. igni_core/core/mcp/schemas.py +165 -0
  522. igni_core/core/mcp/stdio_binding.py +291 -0
  523. igni_core/core/mcp/tool_errors.py +135 -0
  524. igni_core/core/mcp/tool_filter.py +199 -0
  525. igni_core/core/mcp/tool_state.py +72 -0
  526. igni_core/core/memory/__init__.py +5 -0
  527. igni_core/core/memory/manager.py +127 -0
  528. igni_core/core/monitors/__init__.py +38 -0
  529. igni_core/core/monitors/config.py +118 -0
  530. igni_core/core/monitors/handle.py +260 -0
  531. igni_core/core/monitors/loader.py +105 -0
  532. igni_core/core/monitors/manager.py +196 -0
  533. igni_core/core/monitors/models.py +116 -0
  534. igni_core/core/monitors/supervisor.py +149 -0
  535. igni_core/core/network_policy.py +158 -0
  536. igni_core/core/observability/__init__.py +26 -0
  537. igni_core/core/observability/content.py +142 -0
  538. igni_core/core/observability/pipeline.py +155 -0
  539. igni_core/core/observability/run_spans.py +121 -0
  540. igni_core/core/observability/runtime.py +112 -0
  541. igni_core/core/observability/target.py +66 -0
  542. igni_core/core/output_styles/__init__.py +24 -0
  543. igni_core/core/output_styles/loader.py +137 -0
  544. igni_core/core/paths.py +207 -0
  545. igni_core/core/plugins/__init__.py +77 -0
  546. igni_core/core/plugins/git.py +196 -0
  547. igni_core/core/plugins/installer.py +393 -0
  548. igni_core/core/plugins/loader.py +360 -0
  549. igni_core/core/plugins/marketplace_store.py +341 -0
  550. igni_core/core/plugins/models.py +588 -0
  551. igni_core/core/plugins/source_policy.py +131 -0
  552. igni_core/core/plugins/state.py +80 -0
  553. igni_core/core/prompts/__init__.py +25 -0
  554. igni_core/core/prompts/composition.py +168 -0
  555. igni_core/core/prompts/contribution_models.py +90 -0
  556. igni_core/core/prompts/contributions.py +245 -0
  557. igni_core/core/prompts/document.py +277 -0
  558. igni_core/core/prompts/fragments.py +163 -0
  559. igni_core/core/prompts/loader.py +56 -0
  560. igni_core/core/prompts/main_agent.md +548 -0
  561. igni_core/core/prompts/persisting.md +62 -0
  562. igni_core/core/prompts/plan_mode.base.md +31 -0
  563. igni_core/core/run_context.py +15 -0
  564. igni_core/core/scheduler/__init__.py +6 -0
  565. igni_core/core/scheduler/clause_parsers.py +134 -0
  566. igni_core/core/scheduler/db_models.py +112 -0
  567. igni_core/core/scheduler/models.py +133 -0
  568. igni_core/core/scheduler/parser.py +58 -0
  569. igni_core/core/scheduler/prompt.py +70 -0
  570. igni_core/core/scheduler/recurrence.py +265 -0
  571. igni_core/core/scheduler/runner.py +300 -0
  572. igni_core/core/scheduler/store.py +192 -0
  573. igni_core/core/session/__init__.py +149 -0
  574. igni_core/core/session/agent_builder/__init__.py +31 -0
  575. igni_core/core/session/agent_builder/agent_build_spec.py +152 -0
  576. igni_core/core/session/agent_builder/coordinator.py +256 -0
  577. igni_core/core/session/agent_builder/instructions_builder.py +136 -0
  578. igni_core/core/session/agent_builder/main_tools.py +46 -0
  579. igni_core/core/session/agent_builder/plan_mode_nudge.py +40 -0
  580. igni_core/core/session/agent_builder/prompt_builder.py +219 -0
  581. igni_core/core/session/agent_builder/tools_builder.py +177 -0
  582. igni_core/core/session/agent_builder/tools_builder_deps.py +185 -0
  583. igni_core/core/session/agent_factory.py +71 -0
  584. igni_core/core/session/broadcast.py +139 -0
  585. igni_core/core/session/client_state.py +198 -0
  586. igni_core/core/session/cloud_auth.py +126 -0
  587. igni_core/core/session/cloud_catalog.py +97 -0
  588. igni_core/core/session/commands.py +262 -0
  589. igni_core/core/session/compaction/__init__.py +37 -0
  590. igni_core/core/session/compaction/context_breakdown_reporter.py +73 -0
  591. igni_core/core/session/compaction/context_budget.py +40 -0
  592. igni_core/core/session/compaction/coordinator.py +353 -0
  593. igni_core/core/session/compaction/fallback_summariser.py +175 -0
  594. igni_core/core/session/compaction/team_session.py +44 -0
  595. igni_core/core/session/compression.py +59 -0
  596. igni_core/core/session/core.py +331 -0
  597. igni_core/core/session/event_log.py +111 -0
  598. igni_core/core/session/event_log_schema.py +250 -0
  599. igni_core/core/session/hooks.py +119 -0
  600. igni_core/core/session/identity.py +142 -0
  601. igni_core/core/session/interactive.py +36 -0
  602. igni_core/core/session/interactive_loop.py +297 -0
  603. igni_core/core/session/learning_ops.py +185 -0
  604. igni_core/core/session/loop_ops.py +473 -0
  605. igni_core/core/session/mcp_ops.py +187 -0
  606. igni_core/core/session/mcp_resolver.py +57 -0
  607. igni_core/core/session/memory_ops.py +176 -0
  608. igni_core/core/session/message_handler.py +376 -0
  609. igni_core/core/session/message_outcome.py +191 -0
  610. igni_core/core/session/message_pause_policy.py +120 -0
  611. igni_core/core/session/message_team.py +53 -0
  612. igni_core/core/session/output_style_selection.py +39 -0
  613. igni_core/core/session/parts/__init__.py +13 -0
  614. igni_core/core/session/parts/agents.py +130 -0
  615. igni_core/core/session/parts/composer.py +99 -0
  616. igni_core/core/session/parts/coordinators.py +84 -0
  617. igni_core/core/session/parts/foundation.py +109 -0
  618. igni_core/core/session/parts/mcp.py +62 -0
  619. igni_core/core/session/parts/persistence.py +52 -0
  620. igni_core/core/session/parts/plugins.py +136 -0
  621. igni_core/core/session/parts/project.py +74 -0
  622. igni_core/core/session/parts/runtime.py +115 -0
  623. igni_core/core/session/parts/stores.py +70 -0
  624. igni_core/core/session/parts/tooling.py +45 -0
  625. igni_core/core/session/pending_messages.py +377 -0
  626. igni_core/core/session/persistence/__init__.py +47 -0
  627. igni_core/core/session/persistence/data_service.py +166 -0
  628. igni_core/core/session/persistence/db_protocol.py +89 -0
  629. igni_core/core/session/persistence/event_log_store.py +77 -0
  630. igni_core/core/session/persistence/facade.py +260 -0
  631. igni_core/core/session/persistence/forker.py +89 -0
  632. igni_core/core/session/persistence/listing.py +76 -0
  633. igni_core/core/session/persistence/namer.py +176 -0
  634. igni_core/core/session/persistence/plan_decisions_store.py +52 -0
  635. igni_core/core/session/persistence/run_history.py +114 -0
  636. igni_core/core/session/persistence/title_asker.py +149 -0
  637. igni_core/core/session/persistence/todos_store.py +47 -0
  638. igni_core/core/session/plan_ops.py +196 -0
  639. igni_core/core/session/plugin_reload.py +183 -0
  640. igni_core/core/session/queued_messages.py +302 -0
  641. igni_core/core/session/reminders.py +60 -0
  642. igni_core/core/session/run_debug.py +92 -0
  643. igni_core/core/session/runner.py +33 -0
  644. igni_core/core/session/schemas.py +899 -0
  645. igni_core/core/session/session_directories.py +96 -0
  646. igni_core/core/session/session_preferences.py +107 -0
  647. igni_core/core/session/session_run.py +160 -0
  648. igni_core/core/session/single_message_run.py +136 -0
  649. igni_core/core/session/startup/__init__.py +38 -0
  650. igni_core/core/session/startup/base.py +75 -0
  651. igni_core/core/session/startup/coordinator.py +64 -0
  652. igni_core/core/session/startup/marketplace.py +160 -0
  653. igni_core/core/session/startup/mcp.py +203 -0
  654. igni_core/core/session/state_ops.py +245 -0
  655. igni_core/core/session/surface.py +170 -0
  656. igni_core/core/session/token_estimate.py +101 -0
  657. igni_core/core/session/tool_approval.py +127 -0
  658. igni_core/core/session/tool_hook_factory.py +131 -0
  659. igni_core/core/skills/__init__.py +14 -0
  660. igni_core/core/skills/executor.py +103 -0
  661. igni_core/core/skills/loader.py +226 -0
  662. igni_core/core/skills/parser.py +153 -0
  663. igni_core/core/sub_agent_hitl.py +310 -0
  664. igni_core/core/text_tags.py +254 -0
  665. igni_core/core/tools/__init__.py +5 -0
  666. igni_core/core/tools/async_fire_and_forget.py +62 -0
  667. igni_core/core/tools/custom_loader.py +330 -0
  668. igni_core/core/tools/custom_loader_schemas.py +161 -0
  669. igni_core/core/tools/edit.py +313 -0
  670. igni_core/core/tools/finished_process.py +153 -0
  671. igni_core/core/tools/http_fetcher.py +199 -0
  672. igni_core/core/tools/loop.py +184 -0
  673. igni_core/core/tools/loop_progress.py +120 -0
  674. igni_core/core/tools/lsp.py +94 -0
  675. igni_core/core/tools/managed_process.py +356 -0
  676. igni_core/core/tools/monitors.py +88 -0
  677. igni_core/core/tools/notebook/__init__.py +35 -0
  678. igni_core/core/tools/notebook/document.py +170 -0
  679. igni_core/core/tools/notebook/schemas.py +313 -0
  680. igni_core/core/tools/notebook/tools.py +266 -0
  681. igni_core/core/tools/orchestrate.py +350 -0
  682. igni_core/core/tools/orchestrate_agent_stream.py +371 -0
  683. igni_core/core/tools/orchestrate_budget.py +94 -0
  684. igni_core/core/tools/orchestrate_contracts.py +99 -0
  685. igni_core/core/tools/orchestrate_events.py +278 -0
  686. igni_core/core/tools/orchestrate_modes.py +85 -0
  687. igni_core/core/tools/orchestrate_preview.py +143 -0
  688. igni_core/core/tools/orchestrate_registry.py +60 -0
  689. igni_core/core/tools/orchestrate_resumed_agent_stream.py +48 -0
  690. igni_core/core/tools/orchestrate_resumed_team_stream.py +36 -0
  691. igni_core/core/tools/orchestrate_sandbox.py +251 -0
  692. igni_core/core/tools/orchestrate_spawn_agent.py +279 -0
  693. igni_core/core/tools/orchestrate_spawn_hooks.py +116 -0
  694. igni_core/core/tools/orchestrate_spawn_runner.py +241 -0
  695. igni_core/core/tools/orchestrate_spawn_team.py +199 -0
  696. igni_core/core/tools/orchestrate_spawn_types.py +397 -0
  697. igni_core/core/tools/orchestrate_stream_context.py +91 -0
  698. igni_core/core/tools/orchestrate_stream_finalize.py +145 -0
  699. igni_core/core/tools/orchestrate_stream_handler.py +224 -0
  700. igni_core/core/tools/orchestrate_stream_state.py +122 -0
  701. igni_core/core/tools/orchestrate_streaming.py +46 -0
  702. igni_core/core/tools/orchestrate_symbols.py +61 -0
  703. igni_core/core/tools/orchestrate_team_stream.py +357 -0
  704. igni_core/core/tools/orphan_process.py +297 -0
  705. igni_core/core/tools/orphan_rehydrator.py +210 -0
  706. igni_core/core/tools/orphan_schemas.py +97 -0
  707. igni_core/core/tools/output_tail.py +75 -0
  708. igni_core/core/tools/plan/__init__.py +71 -0
  709. igni_core/core/tools/plan/researcher.py +110 -0
  710. igni_core/core/tools/plan/schemas.py +304 -0
  711. igni_core/core/tools/plan/store.py +211 -0
  712. igni_core/core/tools/plan/submission.py +244 -0
  713. igni_core/core/tools/plan/submit_gate.py +96 -0
  714. igni_core/core/tools/plan/tool.py +178 -0
  715. igni_core/core/tools/process_bus.py +161 -0
  716. igni_core/core/tools/process_events.py +113 -0
  717. igni_core/core/tools/process_eviction.py +100 -0
  718. igni_core/core/tools/process_log.py +173 -0
  719. igni_core/core/tools/process_persistence.py +127 -0
  720. igni_core/core/tools/process_registry.py +348 -0
  721. igni_core/core/tools/process_registry_schemas.py +173 -0
  722. igni_core/core/tools/process_store.py +280 -0
  723. igni_core/core/tools/process_store_schemas.py +165 -0
  724. igni_core/core/tools/process_supervisor.py +295 -0
  725. igni_core/core/tools/process_supervisor_locator.py +51 -0
  726. igni_core/core/tools/registry.py +319 -0
  727. igni_core/core/tools/schedule.py +117 -0
  728. igni_core/core/tools/shell.py +408 -0
  729. igni_core/core/tools/shell_config.py +38 -0
  730. igni_core/core/tools/slash.py +170 -0
  731. igni_core/core/tools/sleep_blocker.py +122 -0
  732. igni_core/core/tools/spawn_args.py +80 -0
  733. igni_core/core/tools/spawn_context.py +227 -0
  734. igni_core/core/tools/subagent_stream.py +221 -0
  735. igni_core/core/tools/todo.py +316 -0
  736. igni_core/core/tools/tool_result.py +59 -0
  737. igni_core/core/tools/tool_spec.py +595 -0
  738. igni_core/core/tools/visualize.py +123 -0
  739. igni_core/core/tools/visualize_schemas.py +99 -0
  740. igni_core/core/tools/web.py +84 -0
  741. igni_core/core/tools/web_schemas.py +143 -0
  742. igni_core/core/utils/__init__.py +1 -0
  743. igni_core/core/utils/attachment_store.py +246 -0
  744. igni_core/core/utils/audit.py +124 -0
  745. igni_core/core/utils/audit_schemas.py +283 -0
  746. igni_core/core/utils/context.py +223 -0
  747. igni_core/core/utils/context_frontmatter.py +118 -0
  748. igni_core/core/utils/context_imports.py +181 -0
  749. igni_core/core/utils/context_loader.py +226 -0
  750. igni_core/core/utils/context_managed.py +93 -0
  751. igni_core/core/utils/context_memory.py +211 -0
  752. igni_core/core/utils/context_memory_paths.py +73 -0
  753. igni_core/core/utils/context_memory_prompt.py +144 -0
  754. igni_core/core/utils/context_project.py +156 -0
  755. igni_core/core/utils/context_readers.py +145 -0
  756. igni_core/core/utils/context_schemas.py +185 -0
  757. igni_core/core/utils/context_user.py +98 -0
  758. igni_core/core/utils/display.py +106 -0
  759. igni_core/core/utils/display_schemas.py +93 -0
  760. igni_core/core/utils/file_index.py +168 -0
  761. igni_core/core/utils/http_retry.py +144 -0
  762. igni_core/core/utils/markdown_command_frontmatter.py +130 -0
  763. igni_core/core/utils/markdown_command_renderer.py +232 -0
  764. igni_core/core/utils/markdown_commands.py +204 -0
  765. igni_core/core/utils/media.py +239 -0
  766. igni_core/core/utils/media_schemas.py +290 -0
  767. igni_core/core/utils/memory_files.py +243 -0
  768. igni_core/core/utils/mentions.py +48 -0
  769. igni_core/core/utils/response.py +140 -0
  770. igni_core/core/utils/rules_index.py +339 -0
  771. igni_core/core/utils/tips.py +282 -0
  772. igni_core/core/utils/update_checker.py +300 -0
  773. igni_core/core/utils/update_checker_schemas.py +205 -0
  774. igni_core/core/workspace.py +66 -0
  775. igni_core/core/workspace_trust/__init__.py +60 -0
  776. igni_core/core/workspace_trust/decision.py +57 -0
  777. igni_core/core/workspace_trust/exceptions.py +16 -0
  778. igni_core/core/workspace_trust/gate.py +33 -0
  779. igni_core/core/workspace_trust/identity.py +174 -0
  780. igni_core/core/workspace_trust/policy.py +80 -0
  781. igni_core/core/workspace_trust/process.py +55 -0
  782. igni_core/core/workspace_trust/run_trust.py +53 -0
  783. igni_core/core/workspace_trust/service.py +256 -0
  784. igni_core/core/workspace_trust/store.py +134 -0
  785. igni_core/core/worktree.py +453 -0
  786. igni_core/decisions_server/__init__.py +8 -0
  787. igni_core/decisions_server/__main__.py +122 -0
  788. igni_core/decisions_server/app.py +131 -0
  789. igni_core/decisions_server/model.py +246 -0
  790. igni_core/extensions/__init__.py +41 -0
  791. igni_core/extensions/assets.py +397 -0
  792. igni_core/extensions/bundle_signature.py +184 -0
  793. igni_core/extensions/bundle_source.py +133 -0
  794. igni_core/extensions/busy.py +68 -0
  795. igni_core/extensions/contributions.py +607 -0
  796. igni_core/extensions/distribution/__init__.py +63 -0
  797. igni_core/extensions/distribution/bundle.py +75 -0
  798. igni_core/extensions/distribution/client.py +139 -0
  799. igni_core/extensions/distribution/constants.py +24 -0
  800. igni_core/extensions/distribution/errors.py +12 -0
  801. igni_core/extensions/distribution/once.py +104 -0
  802. igni_core/extensions/distribution/schemas.py +144 -0
  803. igni_core/extensions/distribution/sync.py +305 -0
  804. igni_core/extensions/event_pull.py +160 -0
  805. igni_core/extensions/events.py +42 -0
  806. igni_core/extensions/extension_settings.py +72 -0
  807. igni_core/extensions/faults.py +116 -0
  808. igni_core/extensions/health.py +306 -0
  809. igni_core/extensions/host/__init__.py +29 -0
  810. igni_core/extensions/host/activity.py +87 -0
  811. igni_core/extensions/host/answers.py +75 -0
  812. igni_core/extensions/host/attachments.py +30 -0
  813. igni_core/extensions/host/backend.py +150 -0
  814. igni_core/extensions/host/backend_gateway.py +70 -0
  815. igni_core/extensions/host/broadcasts/__init__.py +29 -0
  816. igni_core/extensions/host/broadcasts/approval_signals.py +78 -0
  817. igni_core/extensions/host/broadcasts/chat_signals.py +178 -0
  818. igni_core/extensions/host/broadcasts/deferred_reads.py +60 -0
  819. igni_core/extensions/host/broadcasts/file_edits.py +52 -0
  820. igni_core/extensions/host/broadcasts/push_reads.py +88 -0
  821. igni_core/extensions/host/broadcasts/push_signals.py +282 -0
  822. igni_core/extensions/host/broadcasts/router.py +67 -0
  823. igni_core/extensions/host/broadcasts/rpc_writes.py +216 -0
  824. igni_core/extensions/host/broadcasts/run_signals.py +96 -0
  825. igni_core/extensions/host/broadcasts/session_values.py +72 -0
  826. igni_core/extensions/host/broadcasts/signal.py +49 -0
  827. igni_core/extensions/host/broadcasts/status.py +46 -0
  828. igni_core/extensions/host/broadcasts/task_signals.py +150 -0
  829. igni_core/extensions/host/broadcasts/translators.py +78 -0
  830. igni_core/extensions/host/broadcasts/views.py +65 -0
  831. igni_core/extensions/host/call_scope.py +84 -0
  832. igni_core/extensions/host/caller.py +36 -0
  833. igni_core/extensions/host/channel.py +293 -0
  834. igni_core/extensions/host/coverage.py +354 -0
  835. igni_core/extensions/host/definition.py +2399 -0
  836. igni_core/extensions/host/display.py +58 -0
  837. igni_core/extensions/host/errors.py +48 -0
  838. igni_core/extensions/host/extension_directory.py +88 -0
  839. igni_core/extensions/host/external_link.py +37 -0
  840. igni_core/extensions/host/grants.py +102 -0
  841. igni_core/extensions/host/hook_exchange.py +140 -0
  842. igni_core/extensions/host/hooks.py +287 -0
  843. igni_core/extensions/host/host_state.py +47 -0
  844. igni_core/extensions/host/local_notices.py +27 -0
  845. igni_core/extensions/host/member_table.py +65 -0
  846. igni_core/extensions/host/members/__init__.py +78 -0
  847. igni_core/extensions/host/members/account.py +33 -0
  848. igni_core/extensions/host/members/agents.py +60 -0
  849. igni_core/extensions/host/members/answers.py +43 -0
  850. igni_core/extensions/host/members/app.py +150 -0
  851. igni_core/extensions/host/members/approvals.py +89 -0
  852. igni_core/extensions/host/members/base.py +72 -0
  853. igni_core/extensions/host/members/call.py +88 -0
  854. igni_core/extensions/host/members/chat.py +155 -0
  855. igni_core/extensions/host/members/chat_views.py +79 -0
  856. igni_core/extensions/host/members/choice.py +28 -0
  857. igni_core/extensions/host/members/commands.py +70 -0
  858. igni_core/extensions/host/members/decide.py +53 -0
  859. igni_core/extensions/host/members/extension.py +63 -0
  860. igni_core/extensions/host/members/hooks.py +31 -0
  861. igni_core/extensions/host/members/loop.py +48 -0
  862. igni_core/extensions/host/members/mcp.py +68 -0
  863. igni_core/extensions/host/members/models.py +123 -0
  864. igni_core/extensions/host/members/notifications.py +59 -0
  865. igni_core/extensions/host/members/params.py +26 -0
  866. igni_core/extensions/host/members/permissions.py +51 -0
  867. igni_core/extensions/host/members/plan.py +43 -0
  868. igni_core/extensions/host/members/plugins.py +97 -0
  869. igni_core/extensions/host/members/policy.py +23 -0
  870. igni_core/extensions/host/members/processes.py +52 -0
  871. igni_core/extensions/host/members/reads.py +68 -0
  872. igni_core/extensions/host/members/scheduler.py +65 -0
  873. igni_core/extensions/host/members/sessions.py +97 -0
  874. igni_core/extensions/host/members/tag.py +68 -0
  875. igni_core/extensions/host/members/tasks.py +23 -0
  876. igni_core/extensions/host/members/ui.py +226 -0
  877. igni_core/extensions/host/members/ui_values.py +102 -0
  878. igni_core/extensions/host/members/workflows.py +49 -0
  879. igni_core/extensions/host/members/workspace.py +81 -0
  880. igni_core/extensions/host/model.py +118 -0
  881. igni_core/extensions/host/model_config.py +40 -0
  882. igni_core/extensions/host/observations.py +107 -0
  883. igni_core/extensions/host/page_channel.py +101 -0
  884. igni_core/extensions/host/plain.py +24 -0
  885. igni_core/extensions/host/processes.py +103 -0
  886. igni_core/extensions/host/project_paths.py +55 -0
  887. igni_core/extensions/host/published.py +35 -0
  888. igni_core/extensions/host/pushes.py +78 -0
  889. igni_core/extensions/host/request_binder.py +127 -0
  890. igni_core/extensions/host/rpc_wire/__init__.py +9 -0
  891. igni_core/extensions/host/rpc_wire/base.py +46 -0
  892. igni_core/extensions/host/rpc_wire/chat.py +74 -0
  893. igni_core/extensions/host/rpc_wire/notifications.py +57 -0
  894. igni_core/extensions/host/rpc_wire/sessions.py +12 -0
  895. igni_core/extensions/host/rpc_wire/settings.py +82 -0
  896. igni_core/extensions/host/rpc_wire/status.py +62 -0
  897. igni_core/extensions/host/rpc_wire/work.py +67 -0
  898. igni_core/extensions/host/rpc_wire/workspace.py +21 -0
  899. igni_core/extensions/host/rpc_write.py +35 -0
  900. igni_core/extensions/host/services.py +113 -0
  901. igni_core/extensions/host/session_target.py +123 -0
  902. igni_core/extensions/host/signal_values.py +83 -0
  903. igni_core/extensions/host/signals.py +256 -0
  904. igni_core/extensions/host/spec.py +525 -0
  905. igni_core/extensions/host/state/__init__.py +6 -0
  906. igni_core/extensions/host/state/approvals.py +103 -0
  907. igni_core/extensions/host/state/runs.py +35 -0
  908. igni_core/extensions/host/state/status.py +21 -0
  909. igni_core/extensions/host/tools.py +67 -0
  910. igni_core/extensions/host/types.py +113 -0
  911. igni_core/extensions/host/values.py +319 -0
  912. igni_core/extensions/host/window_changes.py +144 -0
  913. igni_core/extensions/host/window_dialogs.py +54 -0
  914. igni_core/extensions/host/window_errors.py +25 -0
  915. igni_core/extensions/host/window_field.py +121 -0
  916. igni_core/extensions/host/window_field_handlers.py +221 -0
  917. igni_core/extensions/host/window_fields.py +88 -0
  918. igni_core/extensions/host/window_registry.py +177 -0
  919. igni_core/extensions/host/window_rpc.py +213 -0
  920. igni_core/extensions/host/window_signals.py +250 -0
  921. igni_core/extensions/host/window_state.py +115 -0
  922. igni_core/extensions/host/window_values.py +306 -0
  923. igni_core/extensions/host/windows.py +278 -0
  924. igni_core/extensions/host/wire.py +237 -0
  925. igni_core/extensions/host/work.py +38 -0
  926. igni_core/extensions/host/workspace_scope.py +81 -0
  927. igni_core/extensions/impact.py +640 -0
  928. igni_core/extensions/install_context.py +40 -0
  929. igni_core/extensions/install_contributions.py +219 -0
  930. igni_core/extensions/install_environment.py +207 -0
  931. igni_core/extensions/install_errors.py +18 -0
  932. igni_core/extensions/install_preflight.py +194 -0
  933. igni_core/extensions/install_process.py +154 -0
  934. igni_core/extensions/install_runtime.py +189 -0
  935. igni_core/extensions/install_service.py +250 -0
  936. igni_core/extensions/installer.py +296 -0
  937. igni_core/extensions/launcher.py +84 -0
  938. igni_core/extensions/listing.py +141 -0
  939. igni_core/extensions/manifest.py +770 -0
  940. igni_core/extensions/manifest_errors.py +156 -0
  941. igni_core/extensions/mcp_manager.py +85 -0
  942. igni_core/extensions/origin.py +668 -0
  943. igni_core/extensions/permissions.py +499 -0
  944. igni_core/extensions/principal.py +134 -0
  945. igni_core/extensions/profile.py +98 -0
  946. igni_core/extensions/provenance.py +89 -0
  947. igni_core/extensions/python_env.py +352 -0
  948. igni_core/extensions/registry.py +345 -0
  949. igni_core/extensions/rpc.py +176 -0
  950. igni_core/extensions/sandbox/__init__.py +58 -0
  951. igni_core/extensions/sandbox/appcontainer.py +495 -0
  952. igni_core/extensions/sandbox/bridge.py +101 -0
  953. igni_core/extensions/sandbox/bubblewrap.py +172 -0
  954. igni_core/extensions/sandbox/launcher.py +422 -0
  955. igni_core/extensions/sandbox/mechanism.py +304 -0
  956. igni_core/extensions/sandbox/plan.py +279 -0
  957. igni_core/extensions/sandbox/proxy.py +489 -0
  958. igni_core/extensions/sandbox/seatbelt.py +241 -0
  959. igni_core/extensions/sandbox/settings.py +174 -0
  960. igni_core/extensions/sandbox/winapi.py +512 -0
  961. igni_core/extensions/sandbox/winbridge.py +802 -0
  962. igni_core/extensions/service.py +165 -0
  963. igni_core/extensions/service_attachments.py +81 -0
  964. igni_core/extensions/service_events.py +278 -0
  965. igni_core/extensions/service_items.py +78 -0
  966. igni_core/extensions/service_landing.py +230 -0
  967. igni_core/extensions/service_threads.py +205 -0
  968. igni_core/extensions/service_token.py +531 -0
  969. igni_core/extensions/settings_values.py +148 -0
  970. igni_core/extensions/store.py +283 -0
  971. igni_core/extensions/store_errors.py +40 -0
  972. igni_core/extensions/web_home.py +46 -0
  973. igni_core/migrations/env.py +78 -0
  974. igni_core/migrations/script.py.mako +28 -0
  975. igni_core/migrations/versions/4f7a1c2e9b3d_add_loop_tables.py +58 -0
  976. igni_core/migrations/versions/8c2e7b1a4f9d_loop_cap_explicit.py +38 -0
  977. igni_core/migrations/versions/9318ebdb0db5_initial_sqlite_schema.py +65 -0
  978. igni_core/migrations/versions/a1d6e3f9c2b7_queued_messages_taken_until_recorded.py +33 -0
  979. igni_core/migrations/versions/a9c4e2f7d1b6_delivered_events.py +42 -0
  980. igni_core/migrations/versions/b3a8c2e5d4f1_add_background_processes_table.py +62 -0
  981. igni_core/migrations/versions/b5d8e1c3a7f9_service_threads.py +61 -0
  982. igni_core/migrations/versions/b8e2f4a6d1c3_waiting_spawns.py +46 -0
  983. igni_core/migrations/versions/c4d7a2e9f5b1_turn_results.py +42 -0
  984. igni_core/migrations/versions/c7f1a9e2d8b4_background_process_history.py +47 -0
  985. igni_core/migrations/versions/d4e5f6a7b8c9_drop_code_index_tables.py +72 -0
  986. igni_core/migrations/versions/d6e1f3a8b2c4_extension_settings.py +41 -0
  987. igni_core/migrations/versions/e3b9d4a1c6f2_scope_every_table.py +303 -0
  988. igni_core/migrations/versions/f7c2a8e4b1d3_waiting_approvals_and_queued_messages.py +80 -0
  989. igni_core/notifications/__init__.py +8 -0
  990. igni_core/notifications/center.py +278 -0
  991. igni_core/notifications/extension_notices.py +141 -0
  992. igni_core/notifications/local_store.py +191 -0
  993. igni_core/notifications/schemas.py +277 -0
  994. igni_core/notifications/server_client.py +149 -0
  995. igni_core/notifications/stream.py +319 -0
  996. igni_core/prefetch_models.py +43 -0
  997. igni_core/protocol/__init__.py +8 -0
  998. igni_core/protocol/agno_compat.py +60 -0
  999. igni_core/protocol/agno_taxonomy.py +122 -0
  1000. igni_core/protocol/agno_tool_formatter.py +349 -0
  1001. igni_core/protocol/edit_diff_computer.py +314 -0
  1002. igni_core/protocol/event_handlers.py +439 -0
  1003. igni_core/protocol/json_value.py +30 -0
  1004. igni_core/protocol/messages.py +36 -0
  1005. igni_core/protocol/redaction.py +30 -0
  1006. igni_core/protocol/registry.py +101 -0
  1007. igni_core/protocol/rpc.py +459 -0
  1008. igni_core/protocol/rpc_contract.py +436 -0
  1009. igni_core/protocol/schemas/__init__.py +220 -0
  1010. igni_core/protocol/schemas/be_events.py +570 -0
  1011. igni_core/protocol/schemas/enums.py +337 -0
  1012. igni_core/protocol/schemas/envelope.py +199 -0
  1013. igni_core/protocol/schemas/fe_actions.py +218 -0
  1014. igni_core/protocol/schemas/internal.py +95 -0
  1015. igni_core/protocol/schemas/mirroring.py +109 -0
  1016. igni_core/protocol/schemas/push.py +198 -0
  1017. igni_core/protocol/schemas/push_payloads.py +139 -0
  1018. igni_core/protocol/schemas/rpc.py +158 -0
  1019. igni_core/protocol/schemas/wire.py +174 -0
  1020. igni_core/protocol/serializer.py +191 -0
  1021. igni_core/protocol/tool_error_conventions.py +162 -0
  1022. igni_core/protocol/tool_friendly_names.py +97 -0
  1023. igni_core/transport/__init__.py +11 -0
  1024. igni_core/transport/_ws_client.py +88 -0
  1025. igni_core/transport/base.py +103 -0
  1026. igni_core/transport/chunk_trace.py +116 -0
  1027. igni_core/transport/composite.py +181 -0
  1028. igni_core/transport/in_process.py +69 -0
  1029. igni_core/transport/ndjson_stream.py +118 -0
  1030. igni_core/transport/unix_socket.py +124 -0
  1031. igni_core/transport/websocket.py +400 -0
  1032. igni_core/transport/ws_auth.py +295 -0
  1033. igni_core-1.0.4.dist-info/METADATA +399 -0
  1034. igni_core-1.0.4.dist-info/RECORD +1038 -0
  1035. igni_core-1.0.4.dist-info/WHEEL +4 -0
  1036. igni_core-1.0.4.dist-info/entry_points.txt +3 -0
  1037. igni_core-1.0.4.dist-info/licenses/LICENSE +202 -0
  1038. igni_core-1.0.4.dist-info/licenses/NOTICE +5 -0
igni_core/__init__.py ADDED
@@ -0,0 +1,37 @@
1
+ """igni — Terminal-based AI coding assistant built on Agno."""
2
+
3
+ # Must run before anything that pulls in ``transformers`` /
4
+ # ``sentence-transformers``. See the shim's docstring for why.
5
+ from igni_core import _torchvision_shim as _torchvision_shim # noqa: F401
6
+ from igni_core.core.agno_telemetry import AgnoTelemetry
7
+
8
+ # ── No run leaves the machine unless somebody asks for it ──────────
9
+ #
10
+ # Agno posts a telemetry event to ``https://os-api.agno.com`` on every
11
+ # agent run, and its default is on. Found by reading a ``--debug`` log
12
+ # during a smoke test: ``POST https://os-api.agno.com/telemetry/runs
13
+ # "HTTP/2 201 Created"``, once per run, on an ordinary session.
14
+ #
15
+ # What it sends is metadata, not content: agent/session/run ids, the
16
+ # provider, model name and model id, the database class name, and a set
17
+ # of capability booleans. **No prompt, no code, no paths.** That
18
+ # distinction matters and is why this is not a breach of "your code
19
+ # never leaves your network" — but it is still an unannounced outbound
20
+ # call from a product sold as self-hosted, it names the customer's
21
+ # model and storage choices, and it is a third party that appears in
22
+ # none of the compliance documents that enumerate where data goes.
23
+ #
24
+ # Set here, before anything imports Agno, because
25
+ # ``agno.agent._init.set_telemetry`` re-reads this variable on every
26
+ # run and overrides whatever the constructor said, so one assignment
27
+ # covers every process that imports igni. Every ``Agent`` / ``Team``
28
+ # igni builds also passes ``telemetry=False``, for a process whose
29
+ # environment lost the variable.
30
+ #
31
+ # An explicit ``AGNO_TELEMETRY=true`` is honoured, except under
32
+ # air-gapped mode, where it is forced off with a warning — here for
33
+ # ``IGNI_AIR_GAPPED=1``, and once settings are loaded for
34
+ # ``air_gapped: true``. ``core/agno_telemetry.py`` has the whole rule.
35
+ AgnoTelemetry.apply_process_default()
36
+
37
+ __version__ = "1.0.4"
igni_core/__main__.py ADDED
@@ -0,0 +1,19 @@
1
+ """Entry point for `igni`, `ignite-ember` and `python -m igni_core`."""
2
+
3
+ from igni_core.cli import cli
4
+ from igni_core.core.dir_migration import migrate_home
5
+
6
+
7
+ def main():
8
+ # Before anything reads the home directory. The rename is
9
+ # idempotent and costs two stat calls once it has happened, and
10
+ # ``paths.home_config_dir`` falls back to the legacy name anyway —
11
+ # so a path that somehow skips this still works. Doing it here means
12
+ # it happens once, early, rather than being something every reader
13
+ # has to remember.
14
+ migrate_home()
15
+ cli()
16
+
17
+
18
+ if __name__ == "__main__":
19
+ main()
@@ -0,0 +1,67 @@
1
+ """Disarm a transitive-dep crash that breaks every ``transformers`` import.
2
+
3
+ ``torchvision`` registers fake implementations for ops like
4
+ ``torchvision::nms`` at module load time:
5
+
6
+ @torch.library.register_fake("torchvision::nms")
7
+
8
+ On torch / torchvision wheel pairs whose native bindings don't match
9
+ (seen on macOS arm64 + Python 3.12 with torch 2.11.0 + torchvision
10
+ 0.26.0 / 0.27.0), that registration raises
11
+ ``RuntimeError: operator torchvision::nms does not exist``.
12
+ ``transformers`` then catches the failure inside its lazy
13
+ ``__getattr__`` and re-raises it as a misleading
14
+ ``ModuleNotFoundError: Could not import module 'PreTrainedModel'``,
15
+ which kills every ``transformers`` user along with it — Laya, the
16
+ decision model igni runs, among them.
17
+
18
+ We don't use torchvision — igni's models read text only. The fix is to
19
+ make sure ``transformers`` never reaches torchvision's auto-discovery
20
+ in the first place. Eagerly probe the import; if it explodes, mark
21
+ the module unimportable in ``sys.modules`` so future ``import
22
+ torchvision`` raises a clean ``ImportError``. ``transformers``'s
23
+ ``is_torchvision_available()`` treats that as "not installed" and
24
+ takes the text-only path.
25
+
26
+ This module is import-side-effect-only — import it once, at the top
27
+ of ``igni_core/__init__.py``, before anything that pulls in
28
+ ``transformers`` / ``sentence-transformers``.
29
+ """
30
+
31
+ import importlib.util
32
+ import logging
33
+ import sys
34
+
35
+ logger = logging.getLogger(__name__)
36
+
37
+
38
+ def _disarm_torchvision_if_broken() -> None:
39
+ if "torchvision" in sys.modules:
40
+ # Already imported — either successfully (nothing to do) or by
41
+ # something that handled the failure itself.
42
+ return
43
+ try:
44
+ spec = importlib.util.find_spec("torchvision")
45
+ except Exception:
46
+ # ``find_spec`` itself can raise on partial installs. Treat as
47
+ # missing — transformers will skip torchvision regardless.
48
+ return
49
+ if spec is None:
50
+ return
51
+ try:
52
+ import torchvision # noqa: F401 — eager probe; failure is the signal
53
+ except Exception as exc:
54
+ logger.info(
55
+ "torchvision import failed (%s); marking it unimportable so "
56
+ "transformers takes the text-only path",
57
+ exc,
58
+ )
59
+ # ``None`` in sys.modules makes future ``import torchvision``
60
+ # raise ``ImportError: import of torchvision halted; None in
61
+ # sys.modules`` — which ``importlib.util.find_spec`` and
62
+ # transformers' availability check both translate to "not
63
+ # available".
64
+ sys.modules["torchvision"] = None # type: ignore[assignment]
65
+
66
+
67
+ _disarm_torchvision_if_broken()
igni_core/alembic.ini ADDED
@@ -0,0 +1,52 @@
1
+ [alembic]
2
+ ; ``alembic.ini`` and ``migrations/`` live INSIDE the ``igni_core``
3
+ ; package so the wheel ships them — non-source-tree installs (Homebrew,
4
+ ; pipx, system pip) need to find them too. ``%(here)s`` expands to the
5
+ ; directory containing this file (``src/igni_core/`` in dev,
6
+ ; ``<site-packages>/igni_core/`` in a wheel install) — using it
7
+ ; avoids any dependency on CWD, since alembic resolves bare relative
8
+ ; paths against CWD rather than the ini location.
9
+ script_location = %(here)s/migrations
10
+ ; Add the package's parent to sys.path so ``igni_core`` is importable
11
+ ; when ``alembic`` is invoked outside an editable install (autogenerate
12
+ ; from a non-installed checkout, etc.). In a wheel layout this is
13
+ ; ``site-packages/`` — already on sys.path, harmless.
14
+ prepend_sys_path = %(here)s/..
15
+ path_separator = os
16
+ ; URL is overridden programmatically per-call (Database.__init__) — this
17
+ ; placeholder only exists to satisfy ``alembic revision --autogenerate``.
18
+ sqlalchemy.url = sqlite:///%(here)s/.alembic-autogenerate-tmp.db
19
+
20
+ [loggers]
21
+ keys = root,sqlalchemy,alembic
22
+
23
+ [handlers]
24
+ keys = console
25
+
26
+ [formatters]
27
+ keys = generic
28
+
29
+ [logger_root]
30
+ level = WARNING
31
+ handlers = console
32
+ qualname =
33
+
34
+ [logger_sqlalchemy]
35
+ level = WARNING
36
+ handlers =
37
+ qualname = sqlalchemy.engine
38
+
39
+ [logger_alembic]
40
+ level = INFO
41
+ handlers =
42
+ qualname = alembic
43
+
44
+ [handler_console]
45
+ class = StreamHandler
46
+ args = (sys.stderr,)
47
+ level = NOTSET
48
+ formatter = generic
49
+
50
+ [formatter_generic]
51
+ format = %(levelname)-5.5s [%(name)s] %(message)s
52
+ datefmt = %H:%M:%S
@@ -0,0 +1,5 @@
1
+ """Backend server — owns Session and all AI logic.
2
+
3
+ The TUI (or any future frontend) communicates with the backend
4
+ exclusively through protocol messages. No Agno types cross this boundary.
5
+ """
@@ -0,0 +1,134 @@
1
+ """Backend process entry point.
2
+
3
+ Usage: python -m igni_core.backend --socket <path>
4
+
5
+ Starts a :class:`BackendApp`, listens on the given Unix socket
6
+ and/or WebSocket port, and processes FE messages until shutdown.
7
+ The real work lives in :mod:`igni_core.backend.app` — this module
8
+ is the CLI + the module-load side effects (logging config).
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import asyncio
14
+ import logging
15
+ import sys
16
+ from collections.abc import Callable
17
+ from pathlib import Path
18
+
19
+ import click
20
+
21
+ from igni_core.backend.app import BackendApp
22
+ from igni_core.backend.logging_setup import configure_logging
23
+ from igni_core.backend.schemas_lifecycle import BackendLaunch
24
+ from igni_core.core.data_paths import canonical_project_dir
25
+ from igni_core.core.layer import layers
26
+ from igni_core.transport.ws_auth import take_window_token
27
+
28
+ logger = logging.getLogger(__name__)
29
+
30
+ #: The interpreter this ships on. Kept in step with ``requires-python``
31
+ #: in pyproject.toml and ``PYTHON_VERSION`` in the Tauri runtime, which
32
+ #: is what actually installs it for a user.
33
+ SUPPORTED_PYTHON = (3, 12)
34
+
35
+
36
+ def warn_if_unsupported_python(emit: Callable[..., None] = logger.warning) -> bool:
37
+ """Say so, loudly, when the backend is running off-version.
38
+
39
+ The reason this is worth a check rather than a note in a README: the
40
+ failure is silent. On 3.14 a Neo4j sidecar the backend used to run
41
+ exited without writing stderr, without a log, and without raising —
42
+ the feature behind it simply never came up, and the panel said
43
+ "disabled" as though someone had configured it that way. Two hours
44
+ went into that before the interpreter turned out to be the variable.
45
+
46
+ A warning rather than a refusal. Contributors run the test suite on
47
+ whatever they have, and most of the codebase is fine there; the part
48
+ that is not now announces itself.
49
+
50
+ Returns True when the version is the supported one.
51
+ """
52
+ actual = sys.version_info[:2]
53
+ if actual == SUPPORTED_PYTHON:
54
+ return True
55
+ emit(
56
+ "running on Python %d.%d; this backend is supported on %d.%d only. "
57
+ "Some subsystems fail silently off-version.",
58
+ *actual,
59
+ *SUPPORTED_PYTHON,
60
+ )
61
+ return False
62
+
63
+
64
+ @click.command()
65
+ @click.option("--socket", "socket_path", default=None, help="Unix socket path")
66
+ @click.option(
67
+ "--ws-port",
68
+ "ws_port",
69
+ type=int,
70
+ default=None,
71
+ help="Listen on a loopback WebSocket port instead of a Unix socket "
72
+ "(0 = auto-assign; the bound port is printed in the ready line). "
73
+ "Used by GUI clients (the Tauri desktop app, the web client).",
74
+ )
75
+ @click.option("--project-dir", type=click.Path(exists=True), default=".")
76
+ @click.option("--resume-session", "resume_session_id", default=None)
77
+ @click.option("--additional-dirs", multiple=True, default=())
78
+ @click.option("--debug", is_flag=True, default=False)
79
+ def main(
80
+ socket_path: str | None,
81
+ ws_port: int | None,
82
+ project_dir: str,
83
+ resume_session_id: str | None,
84
+ additional_dirs: tuple[str, ...],
85
+ debug: bool,
86
+ ) -> None:
87
+ """Start the igni backend server."""
88
+ if socket_path is None and ws_port is None:
89
+ raise click.UsageError("at least one of --socket or --ws-port is required")
90
+ # Always. ``--debug`` is unreachable for the backend the desktop
91
+ # app spawns (the app builds the argv), and the env var that
92
+ # replaced it still had to be set by someone who already suspected
93
+ # a problem and knew its name — which is nobody, before the fact.
94
+ # ``--debug`` / ``IGNI_DEBUG_LOG`` now choose the level.
95
+ log_path = configure_logging(debug_flag=debug)
96
+ if log_path is not None:
97
+ logger.info("backend log: %s", log_path)
98
+
99
+ warn_if_unsupported_python()
100
+
101
+ # Taken out of the environment at once, before anything is spawned
102
+ # that would inherit it (shell tools, hooks, MCP servers).
103
+ # A backend started by hand has no launcher to give it one, so on a
104
+ # desktop it mints its own and says so once (the cloud's gateway
105
+ # authenticates every client; there the backend takes no token).
106
+ ws_token, minted = take_window_token(
107
+ mint=ws_port is not None and layers.current().name == "desktop"
108
+ )
109
+ if minted:
110
+ click.echo(
111
+ f"igni window token for this backend (shown once, never written to disk): {ws_token} "
112
+ "-- a program connects as the window with igni-client's Local(url=..., token=...).",
113
+ err=True,
114
+ )
115
+
116
+ extra_dirs = [Path(d) for d in additional_dirs] if additional_dirs else None
117
+ # One spelling of the project dir, shared with ``igni migrate`` and
118
+ # every store, so all of them open the same ``state.db``.
119
+ resolved_project = canonical_project_dir(project_dir)
120
+ app = BackendApp(
121
+ BackendLaunch(
122
+ socket_path=socket_path,
123
+ ws_port=ws_port,
124
+ project_dir=resolved_project,
125
+ resume_session_id=resume_session_id,
126
+ additional_dirs=extra_dirs,
127
+ ws_token=ws_token,
128
+ )
129
+ )
130
+ asyncio.run(app.run())
131
+
132
+
133
+ if __name__ == "__main__":
134
+ main()
@@ -0,0 +1,112 @@
1
+ """Whether a backend is doing anything — what decides if its VM may sleep.
2
+
3
+ ``docs/CLOUD.md``. A producer's VM is suspended when nothing runs in it.
4
+ A run that waits only on a person — the main agent paused on an
5
+ approval, or a ``spawn_agent`` call whose sub-agent is paused on one —
6
+ does nothing until the person decides: it counts as **waiting**, not
7
+ running, and the VM may be suspended. The snapshot keeps the waiting run
8
+ frozen exactly where it is; the decision, delivered to the woken VM,
9
+ simply continues it. (Should the VM be lost instead, the approval and
10
+ what hangs from it are in the database: ``ColdSpawnResume``.)
11
+
12
+ :class:`Activity` is that state for the whole backend, as the host
13
+ object model's ``app.activity`` reports it to the node agent.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ from datetime import datetime
19
+ from enum import StrEnum
20
+
21
+ from pydantic import BaseModel, Field
22
+
23
+ from igni_core.core.activity import ActivityRegistry, BusyLease
24
+
25
+
26
+ class ActivityState(StrEnum):
27
+ #: Nothing running and nothing waiting.
28
+ IDLE = "idle"
29
+ #: Nothing running; one or more approvals wait on a person.
30
+ WAITING = "waiting"
31
+ #: A run is working: a model call, a tool, a sub-agent that is not paused.
32
+ RUNNING = "running"
33
+
34
+
35
+ class SessionActivity(BaseModel):
36
+ session_id: str
37
+ state: ActivityState
38
+ waiting_approvals: int = 0
39
+
40
+ @classmethod
41
+ def of(
42
+ cls,
43
+ session_id: str,
44
+ *,
45
+ run_in_progress: bool,
46
+ waiting_approvals: int,
47
+ blocked_spawns: int,
48
+ active_subagent_runs: int,
49
+ ) -> SessionActivity:
50
+ """The session's state from what its backend can see.
51
+
52
+ A run in progress is only waiting when every sub-agent run it
53
+ has going is blocked on a person (and at least one is): the
54
+ main agent is then inside ``spawn_agent`` calls that do nothing
55
+ until a decision.
56
+ """
57
+ if run_in_progress:
58
+ only_waiting = blocked_spawns > 0 and blocked_spawns >= active_subagent_runs
59
+ state = ActivityState.WAITING if only_waiting else ActivityState.RUNNING
60
+ elif waiting_approvals:
61
+ state = ActivityState.WAITING
62
+ else:
63
+ state = ActivityState.IDLE
64
+ return cls(session_id=session_id, state=state, waiting_approvals=waiting_approvals)
65
+
66
+
67
+ class Activity(BaseModel):
68
+ """The backend as a whole: running if any session runs or anything holds a busy lease."""
69
+
70
+ state: ActivityState
71
+ #: Whether the VM may be suspended now: nothing is running and nothing is busy.
72
+ suspendable: bool
73
+ waiting_approvals: int = 0
74
+ sessions: list[SessionActivity] = Field(default_factory=list)
75
+ #: What is working outside a run's own turn (``core/activity``): calls
76
+ #: out, scheduled tasks, processes, extensions that said they are busy.
77
+ busy: list[BusyLease] = Field(default_factory=list)
78
+ #: The earliest time something is due while nothing runs: when to wake.
79
+ wake_at: datetime | None = None
80
+
81
+ @classmethod
82
+ def of(
83
+ cls,
84
+ sessions: list[SessionActivity],
85
+ *,
86
+ busy: list[BusyLease] | None = None,
87
+ wake_at: datetime | None = None,
88
+ ) -> Activity:
89
+ busy = busy or []
90
+ states = {s.state for s in sessions}
91
+ if ActivityState.RUNNING in states or busy:
92
+ state = ActivityState.RUNNING
93
+ elif ActivityState.WAITING in states:
94
+ state = ActivityState.WAITING
95
+ else:
96
+ state = ActivityState.IDLE
97
+ return cls(
98
+ state=state,
99
+ suspendable=state is not ActivityState.RUNNING,
100
+ waiting_approvals=sum(s.waiting_approvals for s in sessions),
101
+ sessions=sessions,
102
+ busy=busy,
103
+ wake_at=wake_at,
104
+ )
105
+
106
+ @classmethod
107
+ def now(cls, sessions: list[SessionActivity], registry: ActivityRegistry) -> Activity:
108
+ """``sessions``, with what ``registry`` says is busy and due."""
109
+ return cls.of(sessions, busy=registry.busy(), wake_at=registry.wake_at())
110
+
111
+
112
+ __all__ = ["Activity", "ActivityState", "SessionActivity"]
@@ -0,0 +1,43 @@
1
+ """The host model told to look at the activity again when the busy registry moves."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import threading
7
+
8
+ from igni_core.extensions.host.model import HostModel
9
+
10
+
11
+ class ActivityNudge:
12
+ """Tells the host model to look at the activity again when the registry moves.
13
+
14
+ A lease can be taken or let go on any thread; the model is the
15
+ loop's. Several moves before the loop gets round to it are one look.
16
+ """
17
+
18
+ def __init__(self, model: HostModel, loop: asyncio.AbstractEventLoop) -> None:
19
+ self._model = model
20
+ self._loop = loop
21
+ self._pending = False
22
+ self._lock = threading.Lock()
23
+
24
+ def __call__(self) -> None:
25
+ with self._lock:
26
+ if self._pending:
27
+ return
28
+ self._pending = True
29
+ try:
30
+ self._loop.call_soon_threadsafe(self._look)
31
+ except RuntimeError:
32
+ # The loop is closed: no look was scheduled, so none is
33
+ # pending — a later move must not be swallowed by this one.
34
+ with self._lock:
35
+ self._pending = False
36
+
37
+ def _look(self) -> None:
38
+ with self._lock:
39
+ self._pending = False
40
+ self._model.services.activity_watch.moved()
41
+
42
+
43
+ __all__ = ["ActivityNudge"]
@@ -0,0 +1,82 @@
1
+ """What the agent is told around a message it did not get from the person's keyboard.
2
+
3
+ Two framings, both ``<system-context>`` blocks the windows strip from
4
+ display, so the chat bubble shows only the text itself:
5
+
6
+ * :class:`ExtensionMessage` — a message an extension posted.
7
+ * :class:`PlanResearchHint` — the one-shot nudge after ``/plan``.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import re
13
+ from html import escape
14
+
15
+
16
+ class ExtensionMessage:
17
+ """How a message an extension posts reads to the agent.
18
+
19
+ The agent must never take it for the person's: it says who sent it,
20
+ in a block the windows strip from display (``<system-context>``),
21
+ around the text wrapped in a tag the windows read back on reload to
22
+ label the bubble.
23
+ """
24
+
25
+ TAG = "extension-message"
26
+
27
+ #: The ``<`` that opens one of igni's own wrapper tags — the ones the
28
+ #: agent reads as igni speaking and the windows strip from display.
29
+ #: Inside an extension's text such a tag
30
+ #: is a forgery: it would close the message early, or hand the agent a
31
+ #: ``<system-context>`` the person never sees.
32
+ _WRAPPER_TAG = re.compile(
33
+ r"<(?=\s*/?\s*(?:system-context|attached-files|extension-message|loop-iteration)\b)",
34
+ re.IGNORECASE,
35
+ )
36
+
37
+ @classmethod
38
+ def wrap(cls, extension_id: str, text: str) -> str:
39
+ # A manifest id never holds a quote or a bracket, so for a real id
40
+ # this changes nothing; an id that does could otherwise close the
41
+ # attribute or the block and write the agent a context of its own.
42
+ sender = escape(extension_id, quote=True)
43
+ # Only a wrapper tag's opening ``<`` changes; every other byte of the
44
+ # text — markdown, code, a ``<div>`` — reaches the agent as posted,
45
+ # so the framing stays the one the model was trained on.
46
+ text = cls._WRAPPER_TAG.sub("&lt;", text)
47
+ return (
48
+ "<system-context>\n"
49
+ f"The message below was posted by the igni extension '{sender}', "
50
+ "not typed by the person. Answer it in the chat as you would answer them.\n"
51
+ "</system-context>\n"
52
+ f'<{cls.TAG} from="{sender}">\n{text}\n</{cls.TAG}>'
53
+ )
54
+
55
+
56
+ class PlanResearchHint:
57
+ """One-shot ``/plan`` → ``enter_plan_mode`` nudge.
58
+
59
+ When the person just typed ``/plan`` (the slash command armed
60
+ :meth:`PlanCoordinator.arm_research`), the next request is
61
+ prefixed with an instruction to spawn the ``plan_researcher``
62
+ sub-agent on that exact request. The caller consumes the armed
63
+ flag, so later turns in the same plan-mode session do not get it.
64
+ """
65
+
66
+ TEXT = (
67
+ "<system-context>\n"
68
+ "Plan mode was just entered via the user's /plan slash "
69
+ "command. BEFORE doing any other work, call "
70
+ "`enter_plan_mode(task=...)` with the user's request "
71
+ "below as the ``task`` argument so the plan_researcher "
72
+ "sub-agent runs first and produces a structured "
73
+ "Findings + Proposed Plan + Open Questions report. "
74
+ "Do not skip this step — the researcher's report is "
75
+ "what makes the eventual ``exit_plan_mode`` call "
76
+ "grounded enough to pass the confidence validator.\n"
77
+ "</system-context>\n\n"
78
+ )
79
+
80
+ @classmethod
81
+ def wrap(cls, text: str) -> str:
82
+ return cls.TEXT + text
@@ -0,0 +1,49 @@
1
+ """Rebuilding the agents when what extensions do to them changes.
2
+
3
+ An extension becoming ready, one going down, a condition it reports
4
+ moving ("my index covers this commit now") — each changes what the
5
+ agent's prompt says or which agent definition stands under a name.
6
+ :class:`~igni_core.core.prompts.contributions.PromptContributions`
7
+ says so whenever it happens, sometimes several times in a row as one
8
+ extension's claims land, and this turns that into one rebuild of every
9
+ session's agents, on the next turn of the event loop.
10
+
11
+ A run already under way finishes with the agent it started with; the
12
+ next one gets the new prompt.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import asyncio
18
+ import logging
19
+ from collections.abc import Callable
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+
24
+ class AgentRefresh:
25
+ """Coalesces requests to rebuild the agents into one rebuild."""
26
+
27
+ def __init__(self, *, loop: asyncio.AbstractEventLoop, refresh: Callable[[], None]) -> None:
28
+ self._loop = loop
29
+ self._refresh = refresh
30
+ self._scheduled = False
31
+
32
+ def request(self) -> None:
33
+ """Rebuild soon. Safe from any thread, and cheap to call often."""
34
+ if self._scheduled or self._loop.is_closed():
35
+ return
36
+ self._scheduled = True
37
+ try:
38
+ self._loop.call_soon_threadsafe(self._run)
39
+ except RuntimeError:
40
+ # The loop closed between the check and the call: nothing was
41
+ # scheduled, so a later request must still be able to schedule.
42
+ self._scheduled = False
43
+
44
+ def _run(self) -> None:
45
+ self._scheduled = False
46
+ try:
47
+ self._refresh()
48
+ except Exception: # noqa: BLE001 — a failed rebuild keeps the agents that work
49
+ logger.exception("rebuilding the agents after an extension change failed")
@@ -0,0 +1,69 @@
1
+ """Apply a person's HITL decision to an Agno requirement.
2
+
3
+ :class:`AgnoDecisionApplier` owns the ``req.confirm()`` /
4
+ ``req.reject()`` dispatch behind :class:`HitlAction` (Pattern 7 — the
5
+ wire keeps the string literal; the domain uses the enum). It never
6
+ builds ``msg.*`` frames: it returns an :class:`ApplyDecisionResult`
7
+ and the caller (:meth:`HitlController.resolve_batch`) turns a failure
8
+ into the wire ``msg.Error``.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import logging
14
+
15
+ from igni_core.backend.schemas_hitl import (
16
+ ApplyDecisionResult,
17
+ HitlAction,
18
+ RequirementTool,
19
+ RunRequirement,
20
+ )
21
+ from igni_core.core.approvals.declined import declined_note
22
+ from igni_core.protocol import messages as msg
23
+
24
+ logger = logging.getLogger(__name__)
25
+
26
+
27
+ class AgnoDecisionApplier:
28
+ """Applies an :class:`msg.HITLDecision` to an Agno
29
+ :class:`RunRequirement` via ``confirm()`` / ``reject()``.
30
+
31
+ Stateless; one module-level instance in :mod:`hitl_controller`
32
+ is shared by every controller.
33
+ """
34
+
35
+ def apply(self, decision: msg.HITLDecision, req: RunRequirement) -> ApplyDecisionResult:
36
+ """Call ``req.confirm()`` or ``req.reject(...)``.
37
+
38
+ Returns :class:`ApplyDecisionResult` — ``ok=False`` when the
39
+ action is unknown or the Agno call raised.
40
+ """
41
+ try:
42
+ action = HitlAction(decision.action)
43
+ except ValueError:
44
+ reason = (
45
+ f"Unknown HITL action '{decision.action}' for requirement {decision.requirement_id}"
46
+ )
47
+ logger.warning("resolve_hitl_batch: %s", reason)
48
+ return ApplyDecisionResult(ok=False, reason=reason)
49
+
50
+ try:
51
+ if action is HitlAction.CONFIRM:
52
+ req.confirm()
53
+ else:
54
+ req.reject(note=declined_note(RequirementTool.of(req).name))
55
+ except Exception as exc:
56
+ logger.warning(
57
+ "resolve_hitl_batch: requirement %s %s() raised %s; skipping",
58
+ decision.requirement_id,
59
+ action.value,
60
+ exc,
61
+ )
62
+ return ApplyDecisionResult(
63
+ ok=False,
64
+ reason=f"Failed to {action.value} requirement {decision.requirement_id}: {exc}",
65
+ )
66
+ return ApplyDecisionResult(ok=True)
67
+
68
+
69
+ __all__ = ["AgnoDecisionApplier"]