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.
- igni_core/__init__.py +37 -0
- igni_core/__main__.py +19 -0
- igni_core/_torchvision_shim.py +67 -0
- igni_core/alembic.ini +52 -0
- igni_core/backend/__init__.py +5 -0
- igni_core/backend/__main__.py +134 -0
- igni_core/backend/activity.py +112 -0
- igni_core/backend/activity_nudge.py +43 -0
- igni_core/backend/agent_framing.py +82 -0
- igni_core/backend/agent_refresh.py +49 -0
- igni_core/backend/agno_decision_applier.py +69 -0
- igni_core/backend/agno_history_plan_scanner.py +114 -0
- igni_core/backend/app.py +321 -0
- igni_core/backend/backend_bootstrap.py +133 -0
- igni_core/backend/backend_notifications.py +71 -0
- igni_core/backend/browser_opener.py +35 -0
- igni_core/backend/browser_sign_in.py +115 -0
- igni_core/backend/builtin_command_registry.py +286 -0
- igni_core/backend/captured_shell_runner.py +129 -0
- igni_core/backend/chat_history_searcher.py +132 -0
- igni_core/backend/cloud_sign_out.py +41 -0
- igni_core/backend/cmd_agents.py +110 -0
- igni_core/backend/cmd_auth.py +123 -0
- igni_core/backend/cmd_config.py +34 -0
- igni_core/backend/cmd_context.py +181 -0
- igni_core/backend/cmd_eject.py +163 -0
- igni_core/backend/cmd_evals.py +41 -0
- igni_core/backend/cmd_help.py +72 -0
- igni_core/backend/cmd_hooks.py +54 -0
- igni_core/backend/cmd_loop.py +269 -0
- igni_core/backend/cmd_memory.py +115 -0
- igni_core/backend/cmd_misc.py +130 -0
- igni_core/backend/cmd_model.py +45 -0
- igni_core/backend/cmd_modes.py +334 -0
- igni_core/backend/cmd_plugin/__init__.py +15 -0
- igni_core/backend/cmd_plugin/bulk_refresh.py +59 -0
- igni_core/backend/cmd_plugin/commands.py +138 -0
- igni_core/backend/cmd_plugin/context.py +43 -0
- igni_core/backend/cmd_plugin/gateway.py +173 -0
- igni_core/backend/cmd_plugin/routers.py +122 -0
- igni_core/backend/cmd_plugin/verbs.py +364 -0
- igni_core/backend/cmd_schedule.py +208 -0
- igni_core/backend/cmd_session.py +202 -0
- igni_core/backend/cold_spawn_resume.py +349 -0
- igni_core/backend/command_handler.py +159 -0
- igni_core/backend/command_result.py +173 -0
- igni_core/backend/controller_registry.py +250 -0
- igni_core/backend/dir_scanner.py +60 -0
- igni_core/backend/extension_startup.py +137 -0
- igni_core/backend/extensions_runtime.py +153 -0
- igni_core/backend/file_completion_service.py +36 -0
- igni_core/backend/file_opener.py +76 -0
- igni_core/backend/first_window.py +56 -0
- igni_core/backend/folder_picker.py +117 -0
- igni_core/backend/group_pack_hydrator.py +127 -0
- igni_core/backend/group_policy_sync.py +185 -0
- igni_core/backend/headless_extensions.py +313 -0
- igni_core/backend/hitl_controller.py +317 -0
- igni_core/backend/hitl_permissions.py +110 -0
- igni_core/backend/hitl_stream_mux.py +368 -0
- igni_core/backend/hitl_tracer.py +88 -0
- igni_core/backend/host_backend.py +185 -0
- igni_core/backend/host_model_runtime.py +84 -0
- igni_core/backend/host_model_wiring.py +107 -0
- igni_core/backend/igni_server_access.py +40 -0
- igni_core/backend/in_flight_tasks.py +37 -0
- igni_core/backend/inline_think_splitter.py +75 -0
- igni_core/backend/keyboard_shortcuts_help.py +67 -0
- igni_core/backend/lockfile.py +326 -0
- igni_core/backend/logging_setup.py +134 -0
- igni_core/backend/login_coordinator.py +103 -0
- igni_core/backend/markdown_command_dispatcher.py +133 -0
- igni_core/backend/marketplace_controller.py +86 -0
- igni_core/backend/message_admission.py +92 -0
- igni_core/backend/message_dispatcher.py +432 -0
- igni_core/backend/model_http_client_manager.py +142 -0
- igni_core/backend/model_switcher.py +71 -0
- igni_core/backend/observed_transport.py +89 -0
- igni_core/backend/panels/__init__.py +30 -0
- igni_core/backend/panels/agents_panel.py +73 -0
- igni_core/backend/panels/hooks_panel.py +38 -0
- igni_core/backend/panels/output_styles_catalog.py +35 -0
- igni_core/backend/panels/skills_panel.py +49 -0
- igni_core/backend/panels/slash_commands_catalog.py +101 -0
- igni_core/backend/pause_handler.py +195 -0
- igni_core/backend/pending_message_journal.py +119 -0
- igni_core/backend/pending_requirements_store.py +204 -0
- igni_core/backend/plan_snapshot_builder.py +51 -0
- igni_core/backend/plugin_bundle_files.py +91 -0
- igni_core/backend/plugin_controller.py +355 -0
- igni_core/backend/plugin_directory_scanner.py +162 -0
- igni_core/backend/plugin_schemas.py +439 -0
- igni_core/backend/pool_directories.py +101 -0
- igni_core/backend/pool_replier.py +81 -0
- igni_core/backend/pool_rpcs/__init__.py +38 -0
- igni_core/backend/pool_rpcs/approver_tokens.py +60 -0
- igni_core/backend/pool_rpcs/attach_session.py +79 -0
- igni_core/backend/pool_rpcs/base.py +98 -0
- igni_core/backend/pool_rpcs/host_model.py +220 -0
- igni_core/backend/pool_rpcs/page_token.py +51 -0
- igni_core/backend/pool_rpcs/platform_calls.py +136 -0
- igni_core/backend/pool_rpcs/router.py +52 -0
- igni_core/backend/pool_wiring.py +97 -0
- igni_core/backend/process_environment.py +35 -0
- igni_core/backend/prompt_builder.py +235 -0
- igni_core/backend/push_bridge.py +421 -0
- igni_core/backend/push_payloads.py +178 -0
- igni_core/backend/restore_content.py +112 -0
- igni_core/backend/rpc_binding.py +191 -0
- igni_core/backend/rpc_errors.py +32 -0
- igni_core/backend/rpc_handlers/__init__.py +59 -0
- igni_core/backend/rpc_handlers/auth.py +139 -0
- igni_core/backend/rpc_handlers/base.py +97 -0
- igni_core/backend/rpc_handlers/extensions.py +110 -0
- igni_core/backend/rpc_handlers/hooks.py +34 -0
- igni_core/backend/rpc_handlers/loop.py +130 -0
- igni_core/backend/rpc_handlers/mcp.py +140 -0
- igni_core/backend/rpc_handlers/models.py +174 -0
- igni_core/backend/rpc_handlers/notifications.py +100 -0
- igni_core/backend/rpc_handlers/panel_args.py +134 -0
- igni_core/backend/rpc_handlers/panels.py +304 -0
- igni_core/backend/rpc_handlers/plan.py +78 -0
- igni_core/backend/rpc_handlers/plugins.py +269 -0
- igni_core/backend/rpc_handlers/pool_guard.py +62 -0
- igni_core/backend/rpc_handlers/scheduler.py +144 -0
- igni_core/backend/rpc_handlers/session.py +239 -0
- igni_core/backend/rpc_handlers/session_args.py +68 -0
- igni_core/backend/rpc_handlers/session_history.py +102 -0
- igni_core/backend/rpc_handlers/skills.py +49 -0
- igni_core/backend/rpc_handlers/workflows.py +92 -0
- igni_core/backend/rpc_handlers/workspace_trust.py +83 -0
- igni_core/backend/rpc_result.py +43 -0
- igni_core/backend/rpc_router.py +171 -0
- igni_core/backend/rpc_streams.py +58 -0
- igni_core/backend/rpc_watch.py +60 -0
- igni_core/backend/run_controller.py +585 -0
- igni_core/backend/run_hook_gate.py +100 -0
- igni_core/backend/schemas_agents.py +73 -0
- igni_core/backend/schemas_auth.py +158 -0
- igni_core/backend/schemas_config.py +126 -0
- igni_core/backend/schemas_context.py +267 -0
- igni_core/backend/schemas_evals.py +43 -0
- igni_core/backend/schemas_extensions.py +292 -0
- igni_core/backend/schemas_help.py +297 -0
- igni_core/backend/schemas_history.py +415 -0
- igni_core/backend/schemas_hitl.py +219 -0
- igni_core/backend/schemas_hooks.py +70 -0
- igni_core/backend/schemas_lifecycle.py +309 -0
- igni_core/backend/schemas_lockfile.py +225 -0
- igni_core/backend/schemas_loop.py +237 -0
- igni_core/backend/schemas_mcp.py +147 -0
- igni_core/backend/schemas_memory.py +193 -0
- igni_core/backend/schemas_model.py +56 -0
- igni_core/backend/schemas_panels.py +230 -0
- igni_core/backend/schemas_pause.py +192 -0
- igni_core/backend/schemas_plan.py +52 -0
- igni_core/backend/schemas_pool.py +197 -0
- igni_core/backend/schemas_processes.py +67 -0
- igni_core/backend/schemas_rpc.py +378 -0
- igni_core/backend/schemas_run.py +198 -0
- igni_core/backend/schemas_scheduler.py +194 -0
- igni_core/backend/schemas_search.py +77 -0
- igni_core/backend/schemas_sessions.py +214 -0
- igni_core/backend/schemas_visualization.py +55 -0
- igni_core/backend/schemas_workflow_events.py +325 -0
- igni_core/backend/schemas_workflows.py +319 -0
- igni_core/backend/search_cache.py +53 -0
- igni_core/backend/search_strategies.py +222 -0
- igni_core/backend/server.py +501 -0
- igni_core/backend/server_auth.py +175 -0
- igni_core/backend/server_context.py +285 -0
- igni_core/backend/server_files.py +264 -0
- igni_core/backend/server_history.py +248 -0
- igni_core/backend/server_history_walker.py +295 -0
- igni_core/backend/server_interrupted_run.py +191 -0
- igni_core/backend/server_lifecycle.py +141 -0
- igni_core/backend/server_loop.py +107 -0
- igni_core/backend/server_mcp.py +146 -0
- igni_core/backend/server_panels.py +143 -0
- igni_core/backend/server_processes.py +128 -0
- igni_core/backend/server_rehydrate.py +203 -0
- igni_core/backend/server_scheduler.py +309 -0
- igni_core/backend/server_search.py +103 -0
- igni_core/backend/server_sessions.py +145 -0
- igni_core/backend/server_shutdown.py +166 -0
- igni_core/backend/service_event_delivery.py +173 -0
- igni_core/backend/service_event_ingress.py +82 -0
- igni_core/backend/service_item_desk.py +175 -0
- igni_core/backend/serving_backend.py +95 -0
- igni_core/backend/session_checkpointer.py +101 -0
- igni_core/backend/session_orchestrator.py +195 -0
- igni_core/backend/session_pool.py +394 -0
- igni_core/backend/session_router.py +97 -0
- igni_core/backend/session_runtime_factory.py +114 -0
- igni_core/backend/session_stamping_transport.py +61 -0
- igni_core/backend/settings_loader.py +40 -0
- igni_core/backend/skill_command_dispatcher.py +47 -0
- igni_core/backend/slash_command.py +41 -0
- igni_core/backend/standing_policy.py +144 -0
- igni_core/backend/stream_event_dispatcher.py +81 -0
- igni_core/backend/supervisor.py +495 -0
- igni_core/backend/team_wiring.py +84 -0
- igni_core/backend/transport_builder.py +72 -0
- igni_core/backend/visualization_action_bus.py +44 -0
- igni_core/backend/workflow_agent_bridge.py +92 -0
- igni_core/backend/workflow_discovery.py +128 -0
- igni_core/backend/workflow_layers.py +120 -0
- igni_core/backend/workflow_run.py +184 -0
- igni_core/backend/workflow_run_registry.py +90 -0
- igni_core/backend/workflow_runner.py +114 -0
- igni_core/backend/workflow_runtime.mjs +491 -0
- igni_core/backend/workflow_runtime_process.py +212 -0
- igni_core/backend/workspace_signals.py +77 -0
- igni_core/backend/workspace_trust_controller.py +153 -0
- igni_core/backend/workspace_watch.py +271 -0
- igni_core/bundled_agents/architect.md +157 -0
- igni_core/bundled_agents/debugger.md +204 -0
- igni_core/bundled_agents/docs.md +336 -0
- igni_core/bundled_agents/editor.md +308 -0
- igni_core/bundled_agents/explorer.md +154 -0
- igni_core/bundled_agents/plan_researcher.md +96 -0
- igni_core/bundled_agents/qa.md +206 -0
- igni_core/bundled_agents/reviewer.md +163 -0
- igni_core/bundled_agents/security.md +183 -0
- igni_core/bundled_agents/simplifier.md +182 -0
- igni_core/bundled_agents/visualizer.md +245 -0
- igni_core/bundled_skills/commit/SKILL.md +55 -0
- igni_core/bundled_skills/explain/SKILL.md +67 -0
- igni_core/bundled_skills/migration/SKILL.md +80 -0
- igni_core/bundled_skills/pr/SKILL.md +81 -0
- igni_core/bundled_skills/test-plan/SKILL.md +119 -0
- igni_core/cli/__init__.py +219 -0
- igni_core/cli/context.py +27 -0
- igni_core/cli/ext.py +484 -0
- igni_core/cli/ext_doctor.py +242 -0
- igni_core/cli/ext_manifest_check.py +133 -0
- igni_core/cli/ext_scaffold.py +222 -0
- igni_core/cli/ext_scaffold_templates.py +488 -0
- igni_core/cli/headless_run.py +114 -0
- igni_core/cli/invocation.py +229 -0
- igni_core/cli/logging.py +101 -0
- igni_core/cli/login.py +92 -0
- igni_core/cli/migrate.py +108 -0
- igni_core/cli/options.py +60 -0
- igni_core/cli/resume.py +98 -0
- igni_core/cli/run_settings.py +97 -0
- igni_core/cli/trust.py +210 -0
- igni_core/contracts/__init__.py +11 -0
- igni_core/contracts/wire_schema.py +208 -0
- igni_core/core/__init__.py +0 -0
- igni_core/core/activity/__init__.py +14 -0
- igni_core/core/activity/background.py +222 -0
- igni_core/core/activity/http.py +154 -0
- igni_core/core/activity/http2.py +93 -0
- igni_core/core/activity/registry.py +270 -0
- igni_core/core/agents/__init__.py +43 -0
- igni_core/core/agents/builder.py +251 -0
- igni_core/core/agents/catalog.py +19 -0
- igni_core/core/agents/contributions.py +89 -0
- igni_core/core/agents/ephemeral.py +291 -0
- igni_core/core/agents/loader.py +161 -0
- igni_core/core/agents/markdown.py +167 -0
- igni_core/core/agents/plugin_policy.py +78 -0
- igni_core/core/agents/pool.py +309 -0
- igni_core/core/agents/schemas.py +335 -0
- igni_core/core/agents/tool_audience.py +70 -0
- igni_core/core/agents/tool_check.py +69 -0
- igni_core/core/agents/trained_layout.py +70 -0
- igni_core/core/agno_telemetry.py +122 -0
- igni_core/core/air_gap.py +43 -0
- igni_core/core/approvals/__init__.py +5 -0
- igni_core/core/approvals/declined.py +23 -0
- igni_core/core/approvals/events.py +78 -0
- igni_core/core/approvals/journal.py +240 -0
- igni_core/core/approvals/journal_table.py +58 -0
- igni_core/core/approvals/records.py +56 -0
- igni_core/core/approvals/spawn_links.py +108 -0
- igni_core/core/approvals/tables.py +75 -0
- igni_core/core/approvals/turn_results.py +65 -0
- igni_core/core/auth/__init__.py +52 -0
- igni_core/core/auth/_success_page.py +58 -0
- igni_core/core/auth/callback_server.py +287 -0
- igni_core/core/auth/credentials.py +414 -0
- igni_core/core/auth/discovery.py +195 -0
- igni_core/core/auth/discovery_schemas.py +98 -0
- igni_core/core/auth/http_auth.py +69 -0
- igni_core/core/auth/portal_client.py +306 -0
- igni_core/core/auth/schemas.py +206 -0
- igni_core/core/auth/server_url.py +28 -0
- igni_core/core/broadcast_schema.py +51 -0
- igni_core/core/config/__init__.py +1 -0
- igni_core/core/config/accumulator.py +91 -0
- igni_core/core/config/anthropic_auth.py +76 -0
- igni_core/core/config/caller_inspector.py +54 -0
- igni_core/core/config/checked_gemini.py +49 -0
- igni_core/core/config/cli_overrides.py +173 -0
- igni_core/core/config/cloud_model_migrator.py +106 -0
- igni_core/core/config/cloud_models.py +285 -0
- igni_core/core/config/config_io.py +89 -0
- igni_core/core/config/context_window.py +206 -0
- igni_core/core/config/endpoint.py +132 -0
- igni_core/core/config/group_policy/__init__.py +41 -0
- igni_core/core/config/group_policy/answers.py +54 -0
- igni_core/core/config/group_policy/cache.py +121 -0
- igni_core/core/config/group_policy/entry.py +164 -0
- igni_core/core/config/group_policy/environment.py +37 -0
- igni_core/core/config/group_policy/gate.py +58 -0
- igni_core/core/config/group_policy/hooks.py +119 -0
- igni_core/core/config/group_policy/issuer.py +45 -0
- igni_core/core/config/group_policy/jwks.py +82 -0
- igni_core/core/config/group_policy/jws.py +128 -0
- igni_core/core/config/group_policy/kinds.py +208 -0
- igni_core/core/config/group_policy/layout.py +137 -0
- igni_core/core/config/group_policy/materializer.py +104 -0
- igni_core/core/config/group_policy/meta.py +114 -0
- igni_core/core/config/group_policy/pack.py +134 -0
- igni_core/core/config/group_policy/plugins.py +155 -0
- igni_core/core/config/group_policy/policy_settings.py +43 -0
- igni_core/core/config/group_policy/refresher.py +143 -0
- igni_core/core/config/group_policy/response.py +52 -0
- igni_core/core/config/group_policy/revalidation.py +29 -0
- igni_core/core/config/group_policy/settings_fetcher.py +202 -0
- igni_core/core/config/group_policy/signature.py +202 -0
- igni_core/core/config/group_policy/signed_store.py +143 -0
- igni_core/core/config/group_policy/signing_key.py +87 -0
- igni_core/core/config/group_policy/transport.py +106 -0
- igni_core/core/config/group_policy/trust.py +90 -0
- igni_core/core/config/group_policy/verifier.py +75 -0
- igni_core/core/config/llm_call_logger.py +148 -0
- igni_core/core/config/logging_claude.py +137 -0
- igni_core/core/config/logging_model.py +158 -0
- igni_core/core/config/managed_policy.py +117 -0
- igni_core/core/config/merge_plan.py +195 -0
- igni_core/core/config/message_sanitizer.py +109 -0
- igni_core/core/config/model_entry.py +308 -0
- igni_core/core/config/model_stream.py +186 -0
- igni_core/core/config/models.py +249 -0
- igni_core/core/config/null_model.py +117 -0
- igni_core/core/config/organisation_tiers.py +116 -0
- igni_core/core/config/permission_eval/__init__.py +130 -0
- igni_core/core/config/permission_eval/catalog.py +234 -0
- igni_core/core/config/permission_eval/mode_policy.py +164 -0
- igni_core/core/config/permission_eval/pipe_filters.py +241 -0
- igni_core/core/config/permission_eval/pipeline.py +566 -0
- igni_core/core/config/permission_eval/read_only_shell.py +318 -0
- igni_core/core/config/permission_eval/resolver.py +104 -0
- igni_core/core/config/permission_eval/schemas.py +282 -0
- igni_core/core/config/permission_eval/strategies.py +300 -0
- igni_core/core/config/permissions/__init__.py +24 -0
- igni_core/core/config/permissions/schemas.py +21 -0
- igni_core/core/config/provider_builders.py +395 -0
- igni_core/core/config/provider_catalog.py +87 -0
- igni_core/core/config/reply_ending.py +269 -0
- igni_core/core/config/schemas/__init__.py +65 -0
- igni_core/core/config/schemas/display.py +48 -0
- igni_core/core/config/schemas/extensions.py +34 -0
- igni_core/core/config/schemas/llm_behavior.py +92 -0
- igni_core/core/config/schemas/models.py +63 -0
- igni_core/core/config/schemas/network.py +28 -0
- igni_core/core/config/schemas/orchestration.py +91 -0
- igni_core/core/config/schemas/permissions.py +234 -0
- igni_core/core/config/schemas/plugins.py +33 -0
- igni_core/core/config/schemas/safety.py +73 -0
- igni_core/core/config/schemas/storage_and_paths.py +114 -0
- igni_core/core/config/schemas/telemetry.py +110 -0
- igni_core/core/config/secret_scan.py +140 -0
- igni_core/core/config/settings.py +149 -0
- igni_core/core/config/settings_loader.py +114 -0
- igni_core/core/config/tiers/__init__.py +10 -0
- igni_core/core/config/tiers/base.py +17 -0
- igni_core/core/config/tiers/cli.py +78 -0
- igni_core/core/config/tiers/cloud_migration.py +35 -0
- igni_core/core/config/tiers/developer.py +80 -0
- igni_core/core/config/tiers/files.py +36 -0
- igni_core/core/config/tiers/group_policy.py +133 -0
- igni_core/core/config/tiers/managed.py +99 -0
- igni_core/core/config/tiers/organisation.py +76 -0
- igni_core/core/config/tiers/project.py +203 -0
- igni_core/core/config/tiers/raw_model_registry.py +64 -0
- igni_core/core/config/tool_names.py +267 -0
- igni_core/core/config/tool_permissions/__init__.py +110 -0
- igni_core/core/config/tool_permissions/schemas.py +444 -0
- igni_core/core/config/tool_permissions/settings_files.py +242 -0
- igni_core/core/config/tool_permissions/store.py +248 -0
- igni_core/core/config/tool_permissions/tool_invocation.py +131 -0
- igni_core/core/config/tool_permissions/tool_name_resolver.py +104 -0
- igni_core/core/config/user_config_store.py +110 -0
- igni_core/core/contributed_commands.py +95 -0
- igni_core/core/data_paths.py +214 -0
- igni_core/core/db/__init__.py +22 -0
- igni_core/core/db/agno_schema.py +130 -0
- igni_core/core/db/base.py +14 -0
- igni_core/core/db/database.py +68 -0
- igni_core/core/db/engine.py +21 -0
- igni_core/core/db/engine_registry.py +276 -0
- igni_core/core/db/locator.py +110 -0
- igni_core/core/db/migrations.py +147 -0
- igni_core/core/db/providers.py +120 -0
- igni_core/core/db/schema.py +92 -0
- igni_core/core/db/scope.py +185 -0
- igni_core/core/db/upsert.py +41 -0
- igni_core/core/db/urls.py +154 -0
- igni_core/core/decisions/__init__.py +27 -0
- igni_core/core/decisions/endpoints.py +158 -0
- igni_core/core/decisions/laya.py +160 -0
- igni_core/core/decisions/laya_wire.py +174 -0
- igni_core/core/decisions/schemas.py +198 -0
- igni_core/core/decisions/service_wire.py +53 -0
- igni_core/core/dir_migration.py +124 -0
- igni_core/core/evals/__init__.py +13 -0
- igni_core/core/evals/agno_adapter.py +227 -0
- igni_core/core/evals/assertion_runner.py +369 -0
- igni_core/core/evals/assertions.py +124 -0
- igni_core/core/evals/loader.py +203 -0
- igni_core/core/evals/reporter.py +94 -0
- igni_core/core/evals/runner.py +387 -0
- igni_core/core/evals/schemas.py +342 -0
- igni_core/core/evals/tool_names.py +121 -0
- igni_core/core/evals/workspace.py +170 -0
- igni_core/core/guardrails/__init__.py +28 -0
- igni_core/core/guardrails/base.py +88 -0
- igni_core/core/guardrails/injection.py +54 -0
- igni_core/core/guardrails/moderation.py +28 -0
- igni_core/core/guardrails/pii.py +60 -0
- igni_core/core/guardrails/runner.py +107 -0
- igni_core/core/hitl/__init__.py +13 -0
- igni_core/core/hitl/ledger.py +125 -0
- igni_core/core/hitl/models.py +169 -0
- igni_core/core/hitl/registry.py +167 -0
- igni_core/core/hitl/relay.py +33 -0
- igni_core/core/hitl/trace.py +63 -0
- igni_core/core/hitl/turns.py +70 -0
- igni_core/core/hooks/__init__.py +33 -0
- igni_core/core/hooks/agno_coroutine_marker.py +42 -0
- igni_core/core/hooks/bypass_explainer.py +139 -0
- igni_core/core/hooks/bypass_guard.py +276 -0
- igni_core/core/hooks/bypass_judge.py +98 -0
- igni_core/core/hooks/bypass_rules.py +257 -0
- igni_core/core/hooks/bypass_tool_kind.py +107 -0
- igni_core/core/hooks/envelope.py +133 -0
- igni_core/core/hooks/events.py +80 -0
- igni_core/core/hooks/executor.py +352 -0
- igni_core/core/hooks/extension_gate.py +120 -0
- igni_core/core/hooks/extension_spec.py +100 -0
- igni_core/core/hooks/extension_values.py +95 -0
- igni_core/core/hooks/group_hook_decisions.py +145 -0
- igni_core/core/hooks/group_hook_gate.py +205 -0
- igni_core/core/hooks/handlers/__init__.py +23 -0
- igni_core/core/hooks/handlers/base.py +57 -0
- igni_core/core/hooks/handlers/command.py +166 -0
- igni_core/core/hooks/handlers/http.py +81 -0
- igni_core/core/hooks/handlers/mcp_tool.py +137 -0
- igni_core/core/hooks/handlers/prompt.py +35 -0
- igni_core/core/hooks/handlers/registry.py +115 -0
- igni_core/core/hooks/hook_firer.py +76 -0
- igni_core/core/hooks/load_result.py +38 -0
- igni_core/core/hooks/loader.py +299 -0
- igni_core/core/hooks/matcher.py +80 -0
- igni_core/core/hooks/memory_sync.py +42 -0
- igni_core/core/hooks/merger.py +67 -0
- igni_core/core/hooks/payload_sanitizer.py +69 -0
- igni_core/core/hooks/permission/__init__.py +9 -0
- igni_core/core/hooks/permission/blocked_command_stage.py +56 -0
- igni_core/core/hooks/permission/bypass_guard_stage.py +26 -0
- igni_core/core/hooks/permission/context.py +66 -0
- igni_core/core/hooks/permission/denial.py +67 -0
- igni_core/core/hooks/permission/evaluator_stage.py +112 -0
- igni_core/core/hooks/permission/outcome.py +30 -0
- igni_core/core/hooks/permission/pipeline.py +63 -0
- igni_core/core/hooks/permission/pre_tool_use_stage.py +81 -0
- igni_core/core/hooks/permission/protected_path_stage.py +90 -0
- igni_core/core/hooks/permission/stage.py +20 -0
- igni_core/core/hooks/queue/__init__.py +71 -0
- igni_core/core/hooks/queue/agno_adapter.py +87 -0
- igni_core/core/hooks/queue/bridge.py +79 -0
- igni_core/core/hooks/queue/buffer.py +73 -0
- igni_core/core/hooks/queue/injector.py +145 -0
- igni_core/core/hooks/queue/persister.py +74 -0
- igni_core/core/hooks/queue/schemas.py +170 -0
- igni_core/core/hooks/registry.py +199 -0
- igni_core/core/hooks/rules_suffixer.py +134 -0
- igni_core/core/hooks/schemas.py +336 -0
- igni_core/core/hooks/tool_call_invoker.py +108 -0
- igni_core/core/hooks/tool_events.py +146 -0
- igni_core/core/hooks/tool_hook.py +233 -0
- igni_core/core/hooks/turn_results.py +55 -0
- igni_core/core/hooks/untrusted.py +206 -0
- igni_core/core/init/__init__.py +36 -0
- igni_core/core/init/checksum_store.py +171 -0
- igni_core/core/init/gitignore.py +118 -0
- igni_core/core/init/home_migrator.py +119 -0
- igni_core/core/init/hook_provisioner.py +95 -0
- igni_core/core/init/hooks_catalog.py +49 -0
- igni_core/core/init/json_file.py +106 -0
- igni_core/core/init/project_initializer.py +244 -0
- igni_core/core/init/schemas.py +430 -0
- igni_core/core/init_templates.py +179 -0
- igni_core/core/layer.py +230 -0
- igni_core/core/learn.py +174 -0
- igni_core/core/log_fields.py +48 -0
- igni_core/core/loop/__init__.py +36 -0
- igni_core/core/loop/db_models.py +75 -0
- igni_core/core/loop/limits.py +22 -0
- igni_core/core/loop/models.py +42 -0
- igni_core/core/loop/prompt.py +86 -0
- igni_core/core/loop/store.py +242 -0
- igni_core/core/loop/tool_results.py +279 -0
- igni_core/core/lsp/__init__.py +43 -0
- igni_core/core/lsp/client.py +366 -0
- igni_core/core/lsp/loader.py +252 -0
- igni_core/core/lsp/manager.py +122 -0
- igni_core/core/lsp/schemas.py +353 -0
- igni_core/core/mcp/__init__.py +27 -0
- igni_core/core/mcp/approval.py +190 -0
- igni_core/core/mcp/client.py +581 -0
- igni_core/core/mcp/config.py +254 -0
- igni_core/core/mcp/hints.py +158 -0
- igni_core/core/mcp/naming.py +64 -0
- igni_core/core/mcp/notification_tap.py +102 -0
- igni_core/core/mcp/request_meta.py +62 -0
- igni_core/core/mcp/schemas.py +165 -0
- igni_core/core/mcp/stdio_binding.py +291 -0
- igni_core/core/mcp/tool_errors.py +135 -0
- igni_core/core/mcp/tool_filter.py +199 -0
- igni_core/core/mcp/tool_state.py +72 -0
- igni_core/core/memory/__init__.py +5 -0
- igni_core/core/memory/manager.py +127 -0
- igni_core/core/monitors/__init__.py +38 -0
- igni_core/core/monitors/config.py +118 -0
- igni_core/core/monitors/handle.py +260 -0
- igni_core/core/monitors/loader.py +105 -0
- igni_core/core/monitors/manager.py +196 -0
- igni_core/core/monitors/models.py +116 -0
- igni_core/core/monitors/supervisor.py +149 -0
- igni_core/core/network_policy.py +158 -0
- igni_core/core/observability/__init__.py +26 -0
- igni_core/core/observability/content.py +142 -0
- igni_core/core/observability/pipeline.py +155 -0
- igni_core/core/observability/run_spans.py +121 -0
- igni_core/core/observability/runtime.py +112 -0
- igni_core/core/observability/target.py +66 -0
- igni_core/core/output_styles/__init__.py +24 -0
- igni_core/core/output_styles/loader.py +137 -0
- igni_core/core/paths.py +207 -0
- igni_core/core/plugins/__init__.py +77 -0
- igni_core/core/plugins/git.py +196 -0
- igni_core/core/plugins/installer.py +393 -0
- igni_core/core/plugins/loader.py +360 -0
- igni_core/core/plugins/marketplace_store.py +341 -0
- igni_core/core/plugins/models.py +588 -0
- igni_core/core/plugins/source_policy.py +131 -0
- igni_core/core/plugins/state.py +80 -0
- igni_core/core/prompts/__init__.py +25 -0
- igni_core/core/prompts/composition.py +168 -0
- igni_core/core/prompts/contribution_models.py +90 -0
- igni_core/core/prompts/contributions.py +245 -0
- igni_core/core/prompts/document.py +277 -0
- igni_core/core/prompts/fragments.py +163 -0
- igni_core/core/prompts/loader.py +56 -0
- igni_core/core/prompts/main_agent.md +548 -0
- igni_core/core/prompts/persisting.md +62 -0
- igni_core/core/prompts/plan_mode.base.md +31 -0
- igni_core/core/run_context.py +15 -0
- igni_core/core/scheduler/__init__.py +6 -0
- igni_core/core/scheduler/clause_parsers.py +134 -0
- igni_core/core/scheduler/db_models.py +112 -0
- igni_core/core/scheduler/models.py +133 -0
- igni_core/core/scheduler/parser.py +58 -0
- igni_core/core/scheduler/prompt.py +70 -0
- igni_core/core/scheduler/recurrence.py +265 -0
- igni_core/core/scheduler/runner.py +300 -0
- igni_core/core/scheduler/store.py +192 -0
- igni_core/core/session/__init__.py +149 -0
- igni_core/core/session/agent_builder/__init__.py +31 -0
- igni_core/core/session/agent_builder/agent_build_spec.py +152 -0
- igni_core/core/session/agent_builder/coordinator.py +256 -0
- igni_core/core/session/agent_builder/instructions_builder.py +136 -0
- igni_core/core/session/agent_builder/main_tools.py +46 -0
- igni_core/core/session/agent_builder/plan_mode_nudge.py +40 -0
- igni_core/core/session/agent_builder/prompt_builder.py +219 -0
- igni_core/core/session/agent_builder/tools_builder.py +177 -0
- igni_core/core/session/agent_builder/tools_builder_deps.py +185 -0
- igni_core/core/session/agent_factory.py +71 -0
- igni_core/core/session/broadcast.py +139 -0
- igni_core/core/session/client_state.py +198 -0
- igni_core/core/session/cloud_auth.py +126 -0
- igni_core/core/session/cloud_catalog.py +97 -0
- igni_core/core/session/commands.py +262 -0
- igni_core/core/session/compaction/__init__.py +37 -0
- igni_core/core/session/compaction/context_breakdown_reporter.py +73 -0
- igni_core/core/session/compaction/context_budget.py +40 -0
- igni_core/core/session/compaction/coordinator.py +353 -0
- igni_core/core/session/compaction/fallback_summariser.py +175 -0
- igni_core/core/session/compaction/team_session.py +44 -0
- igni_core/core/session/compression.py +59 -0
- igni_core/core/session/core.py +331 -0
- igni_core/core/session/event_log.py +111 -0
- igni_core/core/session/event_log_schema.py +250 -0
- igni_core/core/session/hooks.py +119 -0
- igni_core/core/session/identity.py +142 -0
- igni_core/core/session/interactive.py +36 -0
- igni_core/core/session/interactive_loop.py +297 -0
- igni_core/core/session/learning_ops.py +185 -0
- igni_core/core/session/loop_ops.py +473 -0
- igni_core/core/session/mcp_ops.py +187 -0
- igni_core/core/session/mcp_resolver.py +57 -0
- igni_core/core/session/memory_ops.py +176 -0
- igni_core/core/session/message_handler.py +376 -0
- igni_core/core/session/message_outcome.py +191 -0
- igni_core/core/session/message_pause_policy.py +120 -0
- igni_core/core/session/message_team.py +53 -0
- igni_core/core/session/output_style_selection.py +39 -0
- igni_core/core/session/parts/__init__.py +13 -0
- igni_core/core/session/parts/agents.py +130 -0
- igni_core/core/session/parts/composer.py +99 -0
- igni_core/core/session/parts/coordinators.py +84 -0
- igni_core/core/session/parts/foundation.py +109 -0
- igni_core/core/session/parts/mcp.py +62 -0
- igni_core/core/session/parts/persistence.py +52 -0
- igni_core/core/session/parts/plugins.py +136 -0
- igni_core/core/session/parts/project.py +74 -0
- igni_core/core/session/parts/runtime.py +115 -0
- igni_core/core/session/parts/stores.py +70 -0
- igni_core/core/session/parts/tooling.py +45 -0
- igni_core/core/session/pending_messages.py +377 -0
- igni_core/core/session/persistence/__init__.py +47 -0
- igni_core/core/session/persistence/data_service.py +166 -0
- igni_core/core/session/persistence/db_protocol.py +89 -0
- igni_core/core/session/persistence/event_log_store.py +77 -0
- igni_core/core/session/persistence/facade.py +260 -0
- igni_core/core/session/persistence/forker.py +89 -0
- igni_core/core/session/persistence/listing.py +76 -0
- igni_core/core/session/persistence/namer.py +176 -0
- igni_core/core/session/persistence/plan_decisions_store.py +52 -0
- igni_core/core/session/persistence/run_history.py +114 -0
- igni_core/core/session/persistence/title_asker.py +149 -0
- igni_core/core/session/persistence/todos_store.py +47 -0
- igni_core/core/session/plan_ops.py +196 -0
- igni_core/core/session/plugin_reload.py +183 -0
- igni_core/core/session/queued_messages.py +302 -0
- igni_core/core/session/reminders.py +60 -0
- igni_core/core/session/run_debug.py +92 -0
- igni_core/core/session/runner.py +33 -0
- igni_core/core/session/schemas.py +899 -0
- igni_core/core/session/session_directories.py +96 -0
- igni_core/core/session/session_preferences.py +107 -0
- igni_core/core/session/session_run.py +160 -0
- igni_core/core/session/single_message_run.py +136 -0
- igni_core/core/session/startup/__init__.py +38 -0
- igni_core/core/session/startup/base.py +75 -0
- igni_core/core/session/startup/coordinator.py +64 -0
- igni_core/core/session/startup/marketplace.py +160 -0
- igni_core/core/session/startup/mcp.py +203 -0
- igni_core/core/session/state_ops.py +245 -0
- igni_core/core/session/surface.py +170 -0
- igni_core/core/session/token_estimate.py +101 -0
- igni_core/core/session/tool_approval.py +127 -0
- igni_core/core/session/tool_hook_factory.py +131 -0
- igni_core/core/skills/__init__.py +14 -0
- igni_core/core/skills/executor.py +103 -0
- igni_core/core/skills/loader.py +226 -0
- igni_core/core/skills/parser.py +153 -0
- igni_core/core/sub_agent_hitl.py +310 -0
- igni_core/core/text_tags.py +254 -0
- igni_core/core/tools/__init__.py +5 -0
- igni_core/core/tools/async_fire_and_forget.py +62 -0
- igni_core/core/tools/custom_loader.py +330 -0
- igni_core/core/tools/custom_loader_schemas.py +161 -0
- igni_core/core/tools/edit.py +313 -0
- igni_core/core/tools/finished_process.py +153 -0
- igni_core/core/tools/http_fetcher.py +199 -0
- igni_core/core/tools/loop.py +184 -0
- igni_core/core/tools/loop_progress.py +120 -0
- igni_core/core/tools/lsp.py +94 -0
- igni_core/core/tools/managed_process.py +356 -0
- igni_core/core/tools/monitors.py +88 -0
- igni_core/core/tools/notebook/__init__.py +35 -0
- igni_core/core/tools/notebook/document.py +170 -0
- igni_core/core/tools/notebook/schemas.py +313 -0
- igni_core/core/tools/notebook/tools.py +266 -0
- igni_core/core/tools/orchestrate.py +350 -0
- igni_core/core/tools/orchestrate_agent_stream.py +371 -0
- igni_core/core/tools/orchestrate_budget.py +94 -0
- igni_core/core/tools/orchestrate_contracts.py +99 -0
- igni_core/core/tools/orchestrate_events.py +278 -0
- igni_core/core/tools/orchestrate_modes.py +85 -0
- igni_core/core/tools/orchestrate_preview.py +143 -0
- igni_core/core/tools/orchestrate_registry.py +60 -0
- igni_core/core/tools/orchestrate_resumed_agent_stream.py +48 -0
- igni_core/core/tools/orchestrate_resumed_team_stream.py +36 -0
- igni_core/core/tools/orchestrate_sandbox.py +251 -0
- igni_core/core/tools/orchestrate_spawn_agent.py +279 -0
- igni_core/core/tools/orchestrate_spawn_hooks.py +116 -0
- igni_core/core/tools/orchestrate_spawn_runner.py +241 -0
- igni_core/core/tools/orchestrate_spawn_team.py +199 -0
- igni_core/core/tools/orchestrate_spawn_types.py +397 -0
- igni_core/core/tools/orchestrate_stream_context.py +91 -0
- igni_core/core/tools/orchestrate_stream_finalize.py +145 -0
- igni_core/core/tools/orchestrate_stream_handler.py +224 -0
- igni_core/core/tools/orchestrate_stream_state.py +122 -0
- igni_core/core/tools/orchestrate_streaming.py +46 -0
- igni_core/core/tools/orchestrate_symbols.py +61 -0
- igni_core/core/tools/orchestrate_team_stream.py +357 -0
- igni_core/core/tools/orphan_process.py +297 -0
- igni_core/core/tools/orphan_rehydrator.py +210 -0
- igni_core/core/tools/orphan_schemas.py +97 -0
- igni_core/core/tools/output_tail.py +75 -0
- igni_core/core/tools/plan/__init__.py +71 -0
- igni_core/core/tools/plan/researcher.py +110 -0
- igni_core/core/tools/plan/schemas.py +304 -0
- igni_core/core/tools/plan/store.py +211 -0
- igni_core/core/tools/plan/submission.py +244 -0
- igni_core/core/tools/plan/submit_gate.py +96 -0
- igni_core/core/tools/plan/tool.py +178 -0
- igni_core/core/tools/process_bus.py +161 -0
- igni_core/core/tools/process_events.py +113 -0
- igni_core/core/tools/process_eviction.py +100 -0
- igni_core/core/tools/process_log.py +173 -0
- igni_core/core/tools/process_persistence.py +127 -0
- igni_core/core/tools/process_registry.py +348 -0
- igni_core/core/tools/process_registry_schemas.py +173 -0
- igni_core/core/tools/process_store.py +280 -0
- igni_core/core/tools/process_store_schemas.py +165 -0
- igni_core/core/tools/process_supervisor.py +295 -0
- igni_core/core/tools/process_supervisor_locator.py +51 -0
- igni_core/core/tools/registry.py +319 -0
- igni_core/core/tools/schedule.py +117 -0
- igni_core/core/tools/shell.py +408 -0
- igni_core/core/tools/shell_config.py +38 -0
- igni_core/core/tools/slash.py +170 -0
- igni_core/core/tools/sleep_blocker.py +122 -0
- igni_core/core/tools/spawn_args.py +80 -0
- igni_core/core/tools/spawn_context.py +227 -0
- igni_core/core/tools/subagent_stream.py +221 -0
- igni_core/core/tools/todo.py +316 -0
- igni_core/core/tools/tool_result.py +59 -0
- igni_core/core/tools/tool_spec.py +595 -0
- igni_core/core/tools/visualize.py +123 -0
- igni_core/core/tools/visualize_schemas.py +99 -0
- igni_core/core/tools/web.py +84 -0
- igni_core/core/tools/web_schemas.py +143 -0
- igni_core/core/utils/__init__.py +1 -0
- igni_core/core/utils/attachment_store.py +246 -0
- igni_core/core/utils/audit.py +124 -0
- igni_core/core/utils/audit_schemas.py +283 -0
- igni_core/core/utils/context.py +223 -0
- igni_core/core/utils/context_frontmatter.py +118 -0
- igni_core/core/utils/context_imports.py +181 -0
- igni_core/core/utils/context_loader.py +226 -0
- igni_core/core/utils/context_managed.py +93 -0
- igni_core/core/utils/context_memory.py +211 -0
- igni_core/core/utils/context_memory_paths.py +73 -0
- igni_core/core/utils/context_memory_prompt.py +144 -0
- igni_core/core/utils/context_project.py +156 -0
- igni_core/core/utils/context_readers.py +145 -0
- igni_core/core/utils/context_schemas.py +185 -0
- igni_core/core/utils/context_user.py +98 -0
- igni_core/core/utils/display.py +106 -0
- igni_core/core/utils/display_schemas.py +93 -0
- igni_core/core/utils/file_index.py +168 -0
- igni_core/core/utils/http_retry.py +144 -0
- igni_core/core/utils/markdown_command_frontmatter.py +130 -0
- igni_core/core/utils/markdown_command_renderer.py +232 -0
- igni_core/core/utils/markdown_commands.py +204 -0
- igni_core/core/utils/media.py +239 -0
- igni_core/core/utils/media_schemas.py +290 -0
- igni_core/core/utils/memory_files.py +243 -0
- igni_core/core/utils/mentions.py +48 -0
- igni_core/core/utils/response.py +140 -0
- igni_core/core/utils/rules_index.py +339 -0
- igni_core/core/utils/tips.py +282 -0
- igni_core/core/utils/update_checker.py +300 -0
- igni_core/core/utils/update_checker_schemas.py +205 -0
- igni_core/core/workspace.py +66 -0
- igni_core/core/workspace_trust/__init__.py +60 -0
- igni_core/core/workspace_trust/decision.py +57 -0
- igni_core/core/workspace_trust/exceptions.py +16 -0
- igni_core/core/workspace_trust/gate.py +33 -0
- igni_core/core/workspace_trust/identity.py +174 -0
- igni_core/core/workspace_trust/policy.py +80 -0
- igni_core/core/workspace_trust/process.py +55 -0
- igni_core/core/workspace_trust/run_trust.py +53 -0
- igni_core/core/workspace_trust/service.py +256 -0
- igni_core/core/workspace_trust/store.py +134 -0
- igni_core/core/worktree.py +453 -0
- igni_core/decisions_server/__init__.py +8 -0
- igni_core/decisions_server/__main__.py +122 -0
- igni_core/decisions_server/app.py +131 -0
- igni_core/decisions_server/model.py +246 -0
- igni_core/extensions/__init__.py +41 -0
- igni_core/extensions/assets.py +397 -0
- igni_core/extensions/bundle_signature.py +184 -0
- igni_core/extensions/bundle_source.py +133 -0
- igni_core/extensions/busy.py +68 -0
- igni_core/extensions/contributions.py +607 -0
- igni_core/extensions/distribution/__init__.py +63 -0
- igni_core/extensions/distribution/bundle.py +75 -0
- igni_core/extensions/distribution/client.py +139 -0
- igni_core/extensions/distribution/constants.py +24 -0
- igni_core/extensions/distribution/errors.py +12 -0
- igni_core/extensions/distribution/once.py +104 -0
- igni_core/extensions/distribution/schemas.py +144 -0
- igni_core/extensions/distribution/sync.py +305 -0
- igni_core/extensions/event_pull.py +160 -0
- igni_core/extensions/events.py +42 -0
- igni_core/extensions/extension_settings.py +72 -0
- igni_core/extensions/faults.py +116 -0
- igni_core/extensions/health.py +306 -0
- igni_core/extensions/host/__init__.py +29 -0
- igni_core/extensions/host/activity.py +87 -0
- igni_core/extensions/host/answers.py +75 -0
- igni_core/extensions/host/attachments.py +30 -0
- igni_core/extensions/host/backend.py +150 -0
- igni_core/extensions/host/backend_gateway.py +70 -0
- igni_core/extensions/host/broadcasts/__init__.py +29 -0
- igni_core/extensions/host/broadcasts/approval_signals.py +78 -0
- igni_core/extensions/host/broadcasts/chat_signals.py +178 -0
- igni_core/extensions/host/broadcasts/deferred_reads.py +60 -0
- igni_core/extensions/host/broadcasts/file_edits.py +52 -0
- igni_core/extensions/host/broadcasts/push_reads.py +88 -0
- igni_core/extensions/host/broadcasts/push_signals.py +282 -0
- igni_core/extensions/host/broadcasts/router.py +67 -0
- igni_core/extensions/host/broadcasts/rpc_writes.py +216 -0
- igni_core/extensions/host/broadcasts/run_signals.py +96 -0
- igni_core/extensions/host/broadcasts/session_values.py +72 -0
- igni_core/extensions/host/broadcasts/signal.py +49 -0
- igni_core/extensions/host/broadcasts/status.py +46 -0
- igni_core/extensions/host/broadcasts/task_signals.py +150 -0
- igni_core/extensions/host/broadcasts/translators.py +78 -0
- igni_core/extensions/host/broadcasts/views.py +65 -0
- igni_core/extensions/host/call_scope.py +84 -0
- igni_core/extensions/host/caller.py +36 -0
- igni_core/extensions/host/channel.py +293 -0
- igni_core/extensions/host/coverage.py +354 -0
- igni_core/extensions/host/definition.py +2399 -0
- igni_core/extensions/host/display.py +58 -0
- igni_core/extensions/host/errors.py +48 -0
- igni_core/extensions/host/extension_directory.py +88 -0
- igni_core/extensions/host/external_link.py +37 -0
- igni_core/extensions/host/grants.py +102 -0
- igni_core/extensions/host/hook_exchange.py +140 -0
- igni_core/extensions/host/hooks.py +287 -0
- igni_core/extensions/host/host_state.py +47 -0
- igni_core/extensions/host/local_notices.py +27 -0
- igni_core/extensions/host/member_table.py +65 -0
- igni_core/extensions/host/members/__init__.py +78 -0
- igni_core/extensions/host/members/account.py +33 -0
- igni_core/extensions/host/members/agents.py +60 -0
- igni_core/extensions/host/members/answers.py +43 -0
- igni_core/extensions/host/members/app.py +150 -0
- igni_core/extensions/host/members/approvals.py +89 -0
- igni_core/extensions/host/members/base.py +72 -0
- igni_core/extensions/host/members/call.py +88 -0
- igni_core/extensions/host/members/chat.py +155 -0
- igni_core/extensions/host/members/chat_views.py +79 -0
- igni_core/extensions/host/members/choice.py +28 -0
- igni_core/extensions/host/members/commands.py +70 -0
- igni_core/extensions/host/members/decide.py +53 -0
- igni_core/extensions/host/members/extension.py +63 -0
- igni_core/extensions/host/members/hooks.py +31 -0
- igni_core/extensions/host/members/loop.py +48 -0
- igni_core/extensions/host/members/mcp.py +68 -0
- igni_core/extensions/host/members/models.py +123 -0
- igni_core/extensions/host/members/notifications.py +59 -0
- igni_core/extensions/host/members/params.py +26 -0
- igni_core/extensions/host/members/permissions.py +51 -0
- igni_core/extensions/host/members/plan.py +43 -0
- igni_core/extensions/host/members/plugins.py +97 -0
- igni_core/extensions/host/members/policy.py +23 -0
- igni_core/extensions/host/members/processes.py +52 -0
- igni_core/extensions/host/members/reads.py +68 -0
- igni_core/extensions/host/members/scheduler.py +65 -0
- igni_core/extensions/host/members/sessions.py +97 -0
- igni_core/extensions/host/members/tag.py +68 -0
- igni_core/extensions/host/members/tasks.py +23 -0
- igni_core/extensions/host/members/ui.py +226 -0
- igni_core/extensions/host/members/ui_values.py +102 -0
- igni_core/extensions/host/members/workflows.py +49 -0
- igni_core/extensions/host/members/workspace.py +81 -0
- igni_core/extensions/host/model.py +118 -0
- igni_core/extensions/host/model_config.py +40 -0
- igni_core/extensions/host/observations.py +107 -0
- igni_core/extensions/host/page_channel.py +101 -0
- igni_core/extensions/host/plain.py +24 -0
- igni_core/extensions/host/processes.py +103 -0
- igni_core/extensions/host/project_paths.py +55 -0
- igni_core/extensions/host/published.py +35 -0
- igni_core/extensions/host/pushes.py +78 -0
- igni_core/extensions/host/request_binder.py +127 -0
- igni_core/extensions/host/rpc_wire/__init__.py +9 -0
- igni_core/extensions/host/rpc_wire/base.py +46 -0
- igni_core/extensions/host/rpc_wire/chat.py +74 -0
- igni_core/extensions/host/rpc_wire/notifications.py +57 -0
- igni_core/extensions/host/rpc_wire/sessions.py +12 -0
- igni_core/extensions/host/rpc_wire/settings.py +82 -0
- igni_core/extensions/host/rpc_wire/status.py +62 -0
- igni_core/extensions/host/rpc_wire/work.py +67 -0
- igni_core/extensions/host/rpc_wire/workspace.py +21 -0
- igni_core/extensions/host/rpc_write.py +35 -0
- igni_core/extensions/host/services.py +113 -0
- igni_core/extensions/host/session_target.py +123 -0
- igni_core/extensions/host/signal_values.py +83 -0
- igni_core/extensions/host/signals.py +256 -0
- igni_core/extensions/host/spec.py +525 -0
- igni_core/extensions/host/state/__init__.py +6 -0
- igni_core/extensions/host/state/approvals.py +103 -0
- igni_core/extensions/host/state/runs.py +35 -0
- igni_core/extensions/host/state/status.py +21 -0
- igni_core/extensions/host/tools.py +67 -0
- igni_core/extensions/host/types.py +113 -0
- igni_core/extensions/host/values.py +319 -0
- igni_core/extensions/host/window_changes.py +144 -0
- igni_core/extensions/host/window_dialogs.py +54 -0
- igni_core/extensions/host/window_errors.py +25 -0
- igni_core/extensions/host/window_field.py +121 -0
- igni_core/extensions/host/window_field_handlers.py +221 -0
- igni_core/extensions/host/window_fields.py +88 -0
- igni_core/extensions/host/window_registry.py +177 -0
- igni_core/extensions/host/window_rpc.py +213 -0
- igni_core/extensions/host/window_signals.py +250 -0
- igni_core/extensions/host/window_state.py +115 -0
- igni_core/extensions/host/window_values.py +306 -0
- igni_core/extensions/host/windows.py +278 -0
- igni_core/extensions/host/wire.py +237 -0
- igni_core/extensions/host/work.py +38 -0
- igni_core/extensions/host/workspace_scope.py +81 -0
- igni_core/extensions/impact.py +640 -0
- igni_core/extensions/install_context.py +40 -0
- igni_core/extensions/install_contributions.py +219 -0
- igni_core/extensions/install_environment.py +207 -0
- igni_core/extensions/install_errors.py +18 -0
- igni_core/extensions/install_preflight.py +194 -0
- igni_core/extensions/install_process.py +154 -0
- igni_core/extensions/install_runtime.py +189 -0
- igni_core/extensions/install_service.py +250 -0
- igni_core/extensions/installer.py +296 -0
- igni_core/extensions/launcher.py +84 -0
- igni_core/extensions/listing.py +141 -0
- igni_core/extensions/manifest.py +770 -0
- igni_core/extensions/manifest_errors.py +156 -0
- igni_core/extensions/mcp_manager.py +85 -0
- igni_core/extensions/origin.py +668 -0
- igni_core/extensions/permissions.py +499 -0
- igni_core/extensions/principal.py +134 -0
- igni_core/extensions/profile.py +98 -0
- igni_core/extensions/provenance.py +89 -0
- igni_core/extensions/python_env.py +352 -0
- igni_core/extensions/registry.py +345 -0
- igni_core/extensions/rpc.py +176 -0
- igni_core/extensions/sandbox/__init__.py +58 -0
- igni_core/extensions/sandbox/appcontainer.py +495 -0
- igni_core/extensions/sandbox/bridge.py +101 -0
- igni_core/extensions/sandbox/bubblewrap.py +172 -0
- igni_core/extensions/sandbox/launcher.py +422 -0
- igni_core/extensions/sandbox/mechanism.py +304 -0
- igni_core/extensions/sandbox/plan.py +279 -0
- igni_core/extensions/sandbox/proxy.py +489 -0
- igni_core/extensions/sandbox/seatbelt.py +241 -0
- igni_core/extensions/sandbox/settings.py +174 -0
- igni_core/extensions/sandbox/winapi.py +512 -0
- igni_core/extensions/sandbox/winbridge.py +802 -0
- igni_core/extensions/service.py +165 -0
- igni_core/extensions/service_attachments.py +81 -0
- igni_core/extensions/service_events.py +278 -0
- igni_core/extensions/service_items.py +78 -0
- igni_core/extensions/service_landing.py +230 -0
- igni_core/extensions/service_threads.py +205 -0
- igni_core/extensions/service_token.py +531 -0
- igni_core/extensions/settings_values.py +148 -0
- igni_core/extensions/store.py +283 -0
- igni_core/extensions/store_errors.py +40 -0
- igni_core/extensions/web_home.py +46 -0
- igni_core/migrations/env.py +78 -0
- igni_core/migrations/script.py.mako +28 -0
- igni_core/migrations/versions/4f7a1c2e9b3d_add_loop_tables.py +58 -0
- igni_core/migrations/versions/8c2e7b1a4f9d_loop_cap_explicit.py +38 -0
- igni_core/migrations/versions/9318ebdb0db5_initial_sqlite_schema.py +65 -0
- igni_core/migrations/versions/a1d6e3f9c2b7_queued_messages_taken_until_recorded.py +33 -0
- igni_core/migrations/versions/a9c4e2f7d1b6_delivered_events.py +42 -0
- igni_core/migrations/versions/b3a8c2e5d4f1_add_background_processes_table.py +62 -0
- igni_core/migrations/versions/b5d8e1c3a7f9_service_threads.py +61 -0
- igni_core/migrations/versions/b8e2f4a6d1c3_waiting_spawns.py +46 -0
- igni_core/migrations/versions/c4d7a2e9f5b1_turn_results.py +42 -0
- igni_core/migrations/versions/c7f1a9e2d8b4_background_process_history.py +47 -0
- igni_core/migrations/versions/d4e5f6a7b8c9_drop_code_index_tables.py +72 -0
- igni_core/migrations/versions/d6e1f3a8b2c4_extension_settings.py +41 -0
- igni_core/migrations/versions/e3b9d4a1c6f2_scope_every_table.py +303 -0
- igni_core/migrations/versions/f7c2a8e4b1d3_waiting_approvals_and_queued_messages.py +80 -0
- igni_core/notifications/__init__.py +8 -0
- igni_core/notifications/center.py +278 -0
- igni_core/notifications/extension_notices.py +141 -0
- igni_core/notifications/local_store.py +191 -0
- igni_core/notifications/schemas.py +277 -0
- igni_core/notifications/server_client.py +149 -0
- igni_core/notifications/stream.py +319 -0
- igni_core/prefetch_models.py +43 -0
- igni_core/protocol/__init__.py +8 -0
- igni_core/protocol/agno_compat.py +60 -0
- igni_core/protocol/agno_taxonomy.py +122 -0
- igni_core/protocol/agno_tool_formatter.py +349 -0
- igni_core/protocol/edit_diff_computer.py +314 -0
- igni_core/protocol/event_handlers.py +439 -0
- igni_core/protocol/json_value.py +30 -0
- igni_core/protocol/messages.py +36 -0
- igni_core/protocol/redaction.py +30 -0
- igni_core/protocol/registry.py +101 -0
- igni_core/protocol/rpc.py +459 -0
- igni_core/protocol/rpc_contract.py +436 -0
- igni_core/protocol/schemas/__init__.py +220 -0
- igni_core/protocol/schemas/be_events.py +570 -0
- igni_core/protocol/schemas/enums.py +337 -0
- igni_core/protocol/schemas/envelope.py +199 -0
- igni_core/protocol/schemas/fe_actions.py +218 -0
- igni_core/protocol/schemas/internal.py +95 -0
- igni_core/protocol/schemas/mirroring.py +109 -0
- igni_core/protocol/schemas/push.py +198 -0
- igni_core/protocol/schemas/push_payloads.py +139 -0
- igni_core/protocol/schemas/rpc.py +158 -0
- igni_core/protocol/schemas/wire.py +174 -0
- igni_core/protocol/serializer.py +191 -0
- igni_core/protocol/tool_error_conventions.py +162 -0
- igni_core/protocol/tool_friendly_names.py +97 -0
- igni_core/transport/__init__.py +11 -0
- igni_core/transport/_ws_client.py +88 -0
- igni_core/transport/base.py +103 -0
- igni_core/transport/chunk_trace.py +116 -0
- igni_core/transport/composite.py +181 -0
- igni_core/transport/in_process.py +69 -0
- igni_core/transport/ndjson_stream.py +118 -0
- igni_core/transport/unix_socket.py +124 -0
- igni_core/transport/websocket.py +400 -0
- igni_core/transport/ws_auth.py +295 -0
- igni_core-1.0.4.dist-info/METADATA +399 -0
- igni_core-1.0.4.dist-info/RECORD +1038 -0
- igni_core-1.0.4.dist-info/WHEEL +4 -0
- igni_core-1.0.4.dist-info/entry_points.txt +3 -0
- igni_core-1.0.4.dist-info/licenses/LICENSE +202 -0
- 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,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("<", 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"]
|