kolega-code 0.8.1__tar.gz → 0.8.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {kolega_code-0.8.1 → kolega_code-0.8.2}/PKG-INFO +1 -1
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/cli/overview.md +1 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/gigacode.mdx +14 -3
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/tui/interface.md +4 -3
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/__init__.py +1 -1
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/__init__.py +1 -1
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/orchestration/guide.py +20 -4
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/orchestration/journal.py +77 -7
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/orchestration/runtime.py +41 -3
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/orchestration/types.py +2 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/system/agents/coder_cli.md.j2 +4 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_compaction_tui_events.py +4 -2
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_prompts.py +8 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/test_workflow_tool.py +143 -5
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/agent_tool.py +164 -12
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/workflow_tool.py +193 -22
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tools.py +8 -4
- kolega_code-0.8.2/kolega_code/cli/app.py +1384 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/main.py +2 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/tests/test_app.py +1380 -363
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/tests/test_app_compaction_restore.py +4 -4
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/tests/test_app_image_vision_warning.py +7 -6
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/tests/test_app_model_switch_vision.py +5 -6
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/tests/test_main.py +8 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/tests/test_themes.py +4 -3
- kolega_code-0.8.2/kolega_code/cli/tui/__init__.py +1 -0
- kolega_code-0.8.2/kolega_code/cli/tui/agent_runtime.py +306 -0
- kolega_code-0.8.2/kolega_code/cli/tui/command_handlers.py +810 -0
- kolega_code-0.8.2/kolega_code/cli/tui/constants.py +24 -0
- kolega_code-0.8.2/kolega_code/cli/tui/prompt_flows.py +430 -0
- kolega_code-0.8.2/kolega_code/cli/tui/settings_panel.py +408 -0
- kolega_code-0.8.2/kolega_code/cli/tui/state.py +199 -0
- kolega_code-0.8.2/kolega_code/cli/tui/status_dashboard.py +267 -0
- kolega_code-0.8.2/kolega_code/cli/tui/styles.py +339 -0
- kolega_code-0.8.2/kolega_code/cli/tui/sub_agent_screen.py +367 -0
- kolega_code-0.8.2/kolega_code/cli/tui/transcript.py +1397 -0
- kolega_code-0.8.2/kolega_code/cli/tui/widgets.py +658 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/pyproject.toml +1 -1
- {kolega_code-0.8.1 → kolega_code-0.8.2}/uv.lock +2 -2
- kolega_code-0.8.1/kolega_code/cli/app.py +0 -6071
- {kolega_code-0.8.1 → kolega_code-0.8.2}/.env.example +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/.github/workflows/ci.yml +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/.github/workflows/docs.yml +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/.github/workflows/release.yml +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/.gitignore +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/CONTRIBUTING.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/LICENSE +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/README.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/RELEASING.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/SECURITY.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/conftest.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/.gitignore +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/README.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/astro.config.mjs +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/package-lock.json +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/package.json +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/public/favicon.svg +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/assets/demo.gif +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/assets/kolega-dark.svg +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/assets/kolega-light.svg +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/cli/ask.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/cli/doctor.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/cli/sessions.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/concepts/agents.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/concepts/how-it-works.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/concepts/tools.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/configuration/environment-variables.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/configuration/providers-and-models.mdx +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/configuration/settings-and-api-keys.mdx +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/configuration/sign-in-with-chatgpt.mdx +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/getting-started/installation.mdx +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/getting-started/quick-start.mdx +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/hooks.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/index.mdx +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/skills.mdx +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/tui/composer.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/tui/modes.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/tui/sessions-and-resume.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content/docs/tui/slash-commands.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/content.config.ts +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/src/styles/brand.css +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/docs/tsconfig.json +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/baseagent.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/browseragent.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/coder.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/common.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/compression.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/context.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/conversation.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/errors.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/generalagent.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/investigationagent.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/orchestration/__init__.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/orchestration/budget.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/orchestration/errors.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/orchestration/executor.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/orchestration/tests/__init__.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/orchestration/tests/test_orchestration.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/planningagent.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_provider.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/auxiliary/compression/summary.system.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/auxiliary/compression/summary.user.md.j2 +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/auxiliary/terminal/output_summary.system.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/auxiliary/terminal/safety.system.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/auxiliary/tools/think_hard.system.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/extensions/cli/planning_questions.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/extensions/cli/shared_task_list.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/extensions/skills/catalog.md.j2 +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/system/agents/browser.md.j2 +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/system/agents/general.md.j2 +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/system/agents/investigation.md.j2 +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/system/agents/planning.md.j2 +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/system/includes/agents_md_instructions.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/system/includes/environment_variables/workspace_env_vars.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/system/includes/frontend_guidance.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/system/includes/starter_templates/expo.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/system/includes/starter_templates/html_website.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/system/includes/starter_templates/mern_stack.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/system/includes/starter_templates/react_vite_shadcdn.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/user_tasks/cli/implement_plan.md.j2 +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompt_templates/user_tasks/cli/init_agents.md.j2 +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/prompts.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/__init__.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/compaction_helpers.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/__init__.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_anthropic_token_counting.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_billing_openai_cache.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_chatgpt_live.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_chatgpt_oauth_provider.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_client.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_dashscope_mapping.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_error_boundary.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_exceptions.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_google_thought_signature.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_google_tool_signature_live.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_instrumented_client.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_instrumented_client_integration.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_langfuse_normalization.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_live_providers.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_model_specs.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_openai_cached_tokens.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_openai_cached_tokens_stream.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_openai_message_conversion.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_openai_responses_provider.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_openai_token_counting.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_supports_vision.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_thinking_effort.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/llm/test_tool_execution_ids.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/services/__init__.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/services/test_browser.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/services/test_browser_parity.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/services/test_file_system.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/services/test_sandbox_terminal_input.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/services/test_terminal.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/services/test_terminal_buffer.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/services/test_terminal_state_serializer.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_agent_tools_inventory.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_base_agent.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_coder_attachments.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_coder_prompt_extensions.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_commands.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_compaction_integration.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_compaction_persistence.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_compaction_subagent.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_compress_command.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_compression.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_conversation_compaction.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_duplicate_tool_results.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_empty_message_handling.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_event_emitter.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_general_agent.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_gigacode_gating.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_hooks_integration.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_html.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_image_compat.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_parallel_tool_calls.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_permissions.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_planning_agent.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_prompt_provider.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_read_image_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_tool_registry.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_tools.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/__init__.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/test_agent_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/test_base_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/test_browser_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/test_build_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/test_create_file_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/test_edit_preview.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/test_glob_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/test_glob_tool_sandbox_parity.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/test_list_directory_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/test_read_file_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/test_replace_entire_file_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/test_replace_lines_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/test_search_and_replace_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/test_search_codebase_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/test_terminal_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/test_think_hard_integration.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/test_think_hard_streaming.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/test_web_fetch_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/test_web_search_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/base_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/browser_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/build_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/create_file_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/edit_preview.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/glob_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/list_directory_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/memory_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/read_file_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/read_image_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/replace_entire_file_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/replace_lines_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/search_and_replace_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/search_backends/__init__.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/search_backends/base.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/search_backends/duckduckgo.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/search_backends/errors.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/search_backends/firecrawl.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/search_backends/models.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/search_backends/searxng.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/search_backends/tavily.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/search_codebase_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/streaming_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/terminal_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/think_hard_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/web_fetch_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tool_backend/web_search_tool.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/utils/commands.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/auth/__init__.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/auth/_jwt.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/auth/chatgpt_oauth.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/auth/constants.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/auth/tests/__init__.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/auth/tests/test_chatgpt_oauth.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/auth/tests/test_tokens.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/auth/tokens.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/__init__.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/clipboard_image.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/config.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/connection.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/file_index.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/mentions.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/messages.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/provider_registry.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/session_store.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/settings.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/skills.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/slash_commands.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/tests/__init__.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/tests/test_cli_config.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/tests/test_clipboard_image.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/tests/test_connection.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/tests/test_file_index.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/tests/test_mentions.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/tests/test_provider_registry.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/tests/test_session_store.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/tests/test_settings.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/tests/test_skills.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/tests/test_slash_commands.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/tests/test_updater.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/theme.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/cli/updater.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/config.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/events.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/hooks/__init__.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/hooks/backends.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/hooks/config.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/hooks/dispatcher.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/hooks/events.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/hooks/matcher.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/hooks/outcome.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/hooks/tests/__init__.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/hooks/tests/test_hooks.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/llm/client.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/llm/exceptions.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/llm/instrumented_client.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/llm/models.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/llm/providers/__init__.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/llm/providers/anthropic.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/llm/providers/base.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/llm/providers/chatgpt_oauth.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/llm/providers/google.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/llm/providers/models.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/llm/providers/openai.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/llm/providers/openai_responses.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/llm/providers/responses_common.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/llm/ratelimit.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/llm/specs.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/llm/tool_execution_ids.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/models/__init__.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/models/sandbox_terminal_state.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/permissions.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/runtime.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/sandbox/README.md +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/sandbox/__init__.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/sandbox/async_filesystem.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/sandbox/base.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/sandbox/browser.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/sandbox/event_loop.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/sandbox/filesystem.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/sandbox/local.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/sandbox/serializer.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/sandbox/terminal.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/sandbox/utils.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/services/base.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/services/browser.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/services/file_system.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/services/html.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/services/terminal.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/services/terminal_buffer.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/tools/__init__.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/tools/core.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/tools/definitions.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/tools/registry.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/tools/tests/__init__.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/tools/tests/test_definitions.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/utils/__init__.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/utils/images.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/utils/tests/__init__.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/utils/tests/test_images.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/utils/tests/test_images_ascii.py +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/run_tests.sh +0 -0
- {kolega_code-0.8.1 → kolega_code-0.8.2}/scripts/install-kolega-code.sh +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kolega-code
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.2
|
|
4
4
|
Summary: Local-first AI coding agent for the terminal
|
|
5
5
|
Project-URL: Homepage, https://kolega-ai.github.io/kolega-code/
|
|
6
6
|
Project-URL: Documentation, https://kolega-ai.github.io/kolega-code/
|
|
@@ -39,6 +39,7 @@ kolega-code [PROJECT_PATH]
|
|
|
39
39
|
| `--new` | Start a new session (this is the default) |
|
|
40
40
|
| `--resume [THREAD_ID]` | Resume the latest saved thread, or a specific thread/session ID |
|
|
41
41
|
| `--browser-visible` | Launch visible Playwright browser windows instead of headless |
|
|
42
|
+
| `--show-logs` | Show the optional diagnostic Logs side-panel tab. Hidden by default to avoid unnecessary log rendering work |
|
|
42
43
|
| `--permission-mode <auto\|ask>` | Shell/edit permission mode. TUI sessions default to `ask` |
|
|
43
44
|
| `--session <ID>` | Legacy alias for `--resume THREAD_ID` |
|
|
44
45
|
|
|
@@ -43,6 +43,15 @@ When the agent runs a workflow, the transcript shows **phase headers** and short
|
|
|
43
43
|
[sub-agent inspector](../tui/interface/#sub-agent-inspector) — press `Ctrl+G` to
|
|
44
44
|
watch every agent's live trajectory, grouped by phase.
|
|
45
45
|
|
|
46
|
+
The `run_workflow` result is a compact artifact manifest. It includes paths like
|
|
47
|
+
`resultPath` and `transcriptPath`; the completed workflow result is written to
|
|
48
|
+
`resultPath` instead of returned inline. For normal workflow output, the agent
|
|
49
|
+
should read those main files and avoid reading individual sub-agent transcripts.
|
|
50
|
+
Raw and per-agent debug artifacts may exist under the run directory for explicit
|
|
51
|
+
workflow debugging.
|
|
52
|
+
The agent should read those paths first — not re-run the workflow just to recover
|
|
53
|
+
output text.
|
|
54
|
+
|
|
46
55
|
## How it works
|
|
47
56
|
|
|
48
57
|
Under the hood, the agent authors a short **Python script** and runs it with a
|
|
@@ -69,9 +78,11 @@ return findings
|
|
|
69
78
|
|
|
70
79
|
<Aside type="note">
|
|
71
80
|
Workflows are deterministic and **resumable**. Each run is saved under Kolega
|
|
72
|
-
Code's state directory (`workflows/<run-id>/`) with its script,
|
|
73
|
-
|
|
74
|
-
of redoing
|
|
81
|
+
Code's state directory (`workflows/<run-id>/`) with its script, full result files,
|
|
82
|
+
a readable Markdown transcript, raw JSONL, a resume journal, and debug sub-agent
|
|
83
|
+
transcripts, so an interrupted run can pick up where it left off instead of redoing
|
|
84
|
+
finished work. Use resume when intentionally iterating on the workflow; use the
|
|
85
|
+
artifact paths when you only need to inspect output.
|
|
75
86
|
</Aside>
|
|
76
87
|
|
|
77
88
|
## Behavior and safety
|
|
@@ -14,8 +14,9 @@ The screen is split into two columns:
|
|
|
14
14
|
- **Conversation panel** (left, larger) — your chat with the agent. Responses
|
|
15
15
|
stream in live, tool calls and sub-agent activity appear inline, and detailed
|
|
16
16
|
tool results are collapsed by default so you can expand only what you need.
|
|
17
|
-
- **Side panel** (right) — a set of tabs for status,
|
|
18
|
-
and settings. Toggle it with `Ctrl+O` or `/sidebar`.
|
|
17
|
+
- **Side panel** (right) — a set of tabs for status, the terminal, planning,
|
|
18
|
+
and settings. Toggle it with `Ctrl+O` or `/sidebar`. The diagnostic Logs tab is
|
|
19
|
+
opt-in; launch with `--show-logs` when you want it.
|
|
19
20
|
|
|
20
21
|
At the bottom sits the **composer** — the text box where you type prompts. See
|
|
21
22
|
[Chat Composer](../composer/) for everything it can do.
|
|
@@ -25,7 +26,7 @@ At the bottom sits the **composer** — the text box where you type prompts. See
|
|
|
25
26
|
| Tab | What it shows |
|
|
26
27
|
| --- | --- |
|
|
27
28
|
| **Status** | The active provider/model and thinking effort, the current interaction mode (Build/Plan), permission mode, the agent's turn state (idle, generating, thinking, running a tool, running sub-agents, waiting for input, …), token usage, and context warnings. |
|
|
28
|
-
| **Logs** |
|
|
29
|
+
| **Logs** | Optional. Launch with `--show-logs` to show a timestamped, color-coded diagnostic activity log. New entries preserve manual scrollback and an indicator flags unseen entries when you're on another tab. |
|
|
29
30
|
| **Terminal** | Live output from commands the agent runs. |
|
|
30
31
|
| **Planning** | The current **Plan** (markdown from the planning agent) and the shared **Task List** that both modes can edit. |
|
|
31
32
|
| **Settings** | Provider, model, thinking effort, and API-key configuration. See [Settings & API Keys](../../configuration/settings-and-api-keys/). |
|
|
@@ -134,10 +134,26 @@ After the workflow returns, integrate the results, run the full test suite yours
|
|
|
134
134
|
report. If the plan is small or its parts are tightly coupled, skip the workflow and just
|
|
135
135
|
implement it directly — orchestration is for genuinely independent fan-out.
|
|
136
136
|
|
|
137
|
+
### Artifacts and transcripts
|
|
138
|
+
|
|
139
|
+
`run_workflow` returns a concise manifest, not necessarily the full workflow output.
|
|
140
|
+
Every completed run persists full artifacts under the state directory and returns
|
|
141
|
+
paths including `resultPath` and `transcriptPath`. If the inline tool result says output was omitted, looks incomplete,
|
|
142
|
+
or would require a long transcript to understand, READ `resultPath` or `transcriptPath`
|
|
143
|
+
with the file-reading tools before deciding work is missing. For normal workflow
|
|
144
|
+
output, use only those main files; avoid reading individual sub-agent transcripts
|
|
145
|
+
unless you are explicitly debugging workflow execution.
|
|
146
|
+
|
|
147
|
+
Never re-run a completed workflow solely to recover output from an omitted/truncated
|
|
148
|
+
inline result. The workflow already ran; inspect the persisted result/transcript first.
|
|
149
|
+
Use `resume_from_run_id` only when you intentionally want to iterate on or change the
|
|
150
|
+
workflow, not as a transcript-recovery mechanism.
|
|
151
|
+
|
|
137
152
|
### Resume
|
|
138
153
|
|
|
139
|
-
Each run persists its script
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
prefix and only re-run new/changed
|
|
154
|
+
Each run persists its script, full results, a readable transcript, raw JSONL, and a
|
|
155
|
+
resume journal under the state directory and returns a `runId` plus artifact paths.
|
|
156
|
+
To iterate, edit the script and re-run with `script_path`, or pass `resume_from_run_id`
|
|
157
|
+
to replay cached `agent()` results for the unchanged prefix and only re-run new/changed
|
|
158
|
+
calls.
|
|
143
159
|
"""
|
|
@@ -4,9 +4,13 @@ Everything a run needs lives under::
|
|
|
4
4
|
|
|
5
5
|
<state-dir>/workflows/<run_id>/
|
|
6
6
|
script.py the authored source (its path is returned for edit + re-run)
|
|
7
|
-
run.json meta, args, status, timing, token totals
|
|
7
|
+
run.json meta, args, status, timing, token totals, artifact paths
|
|
8
8
|
journal.jsonl one line per completed agent() call (drives resume)
|
|
9
|
-
|
|
9
|
+
result.json full JSON-rendered workflow return value
|
|
10
|
+
result.md readable workflow return value
|
|
11
|
+
transcript.jsonl raw workflow events/call outcomes
|
|
12
|
+
transcript.md readable workflow transcript/index
|
|
13
|
+
agents/ per sub-agent raw/readable transcripts
|
|
10
14
|
|
|
11
15
|
Resume contract: scripts are deterministic (the runtime blocks ``random``/``time``
|
|
12
16
|
and ``import``), so the same source + args produce ``agent()`` calls in the same
|
|
@@ -18,6 +22,7 @@ new call onward.
|
|
|
18
22
|
from __future__ import annotations
|
|
19
23
|
|
|
20
24
|
import json
|
|
25
|
+
import re
|
|
21
26
|
from pathlib import Path
|
|
22
27
|
from typing import Any, Dict, Optional, Tuple
|
|
23
28
|
|
|
@@ -32,6 +37,15 @@ def saved_workflows_dir(state_dir: Path) -> Path:
|
|
|
32
37
|
return workflows_root(state_dir) / "_saved"
|
|
33
38
|
|
|
34
39
|
|
|
40
|
+
def _slugify(value: str, *, fallback: str = "agent", max_length: int = 64) -> str:
|
|
41
|
+
"""Return a filesystem-friendly slug for workflow artifact filenames."""
|
|
42
|
+
slug = re.sub(r"[^A-Za-z0-9._-]+", "-", str(value or "").strip().lower())
|
|
43
|
+
slug = re.sub(r"-+", "-", slug).strip("-._")
|
|
44
|
+
if not slug:
|
|
45
|
+
slug = fallback
|
|
46
|
+
return slug[:max_length].rstrip("-._") or fallback
|
|
47
|
+
|
|
48
|
+
|
|
35
49
|
class RunJournal:
|
|
36
50
|
"""Owns the on-disk artifacts for a single workflow run."""
|
|
37
51
|
|
|
@@ -40,6 +54,10 @@ class RunJournal:
|
|
|
40
54
|
self.run_id = run_id
|
|
41
55
|
self.agents_dir = self.run_dir / "agents"
|
|
42
56
|
self._journal_path = self.run_dir / "journal.jsonl"
|
|
57
|
+
self._transcript_jsonl_path = self.run_dir / "transcript.jsonl"
|
|
58
|
+
self._transcript_md_path = self.run_dir / "transcript.md"
|
|
59
|
+
self._result_json_path = self.run_dir / "result.json"
|
|
60
|
+
self._result_md_path = self.run_dir / "result.md"
|
|
43
61
|
self._script_path = self.run_dir / "script.py"
|
|
44
62
|
self._meta_path = self.run_dir / "run.json"
|
|
45
63
|
|
|
@@ -55,6 +73,33 @@ class RunJournal:
|
|
|
55
73
|
def script_path(self) -> Path:
|
|
56
74
|
return self._script_path
|
|
57
75
|
|
|
76
|
+
@property
|
|
77
|
+
def journal_path(self) -> Path:
|
|
78
|
+
return self._journal_path
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def transcript_jsonl_path(self) -> Path:
|
|
82
|
+
return self._transcript_jsonl_path
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def transcript_md_path(self) -> Path:
|
|
86
|
+
return self._transcript_md_path
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def result_json_path(self) -> Path:
|
|
90
|
+
return self._result_json_path
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def result_md_path(self) -> Path:
|
|
94
|
+
return self._result_md_path
|
|
95
|
+
|
|
96
|
+
def agent_artifact_paths(self, call_index: int, label: Optional[str] = None) -> Dict[str, Path]:
|
|
97
|
+
"""Return stable per-agent raw/readable artifact paths for a workflow call."""
|
|
98
|
+
self.ensure_dirs()
|
|
99
|
+
suffix = _slugify(label or f"call-{call_index}")
|
|
100
|
+
stem = f"agent-{call_index:03d}-{suffix}"
|
|
101
|
+
return {"markdown": self.agents_dir / f"{stem}.md", "jsonl": self.agents_dir / f"{stem}.jsonl"}
|
|
102
|
+
|
|
58
103
|
def write_script(self, source: str) -> Path:
|
|
59
104
|
self.ensure_dirs()
|
|
60
105
|
self._script_path.write_text(source, encoding="utf-8")
|
|
@@ -86,16 +131,41 @@ class RunJournal:
|
|
|
86
131
|
label: Optional[str],
|
|
87
132
|
value: Any,
|
|
88
133
|
status: str = "completed",
|
|
134
|
+
**metadata: Any,
|
|
89
135
|
) -> None:
|
|
90
|
-
"""Append one completed ``agent()`` result for resume replay.
|
|
136
|
+
"""Append one completed ``agent()`` result for resume replay.
|
|
137
|
+
|
|
138
|
+
``journal.jsonl`` is the resume contract. Extra fields are allowed and ignored
|
|
139
|
+
by ``load_cache()`` so newer artifact metadata remains backward-compatible.
|
|
140
|
+
"""
|
|
91
141
|
self.ensure_dirs()
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
)
|
|
142
|
+
payload = {"index": call_index, "key": key, "label": label, "status": status, "value": value}
|
|
143
|
+
payload.update({k: v for k, v in metadata.items() if v is not None})
|
|
144
|
+
line = json.dumps(payload, default=str)
|
|
96
145
|
with self._journal_path.open("a", encoding="utf-8") as handle:
|
|
97
146
|
handle.write(line + "\n")
|
|
98
147
|
|
|
148
|
+
def append_transcript_event(self, event: Dict[str, Any]) -> None:
|
|
149
|
+
"""Append one raw workflow transcript event as JSONL."""
|
|
150
|
+
self.ensure_dirs()
|
|
151
|
+
with self._transcript_jsonl_path.open("a", encoding="utf-8") as handle:
|
|
152
|
+
handle.write(json.dumps(event, default=str) + "\n")
|
|
153
|
+
|
|
154
|
+
def write_result_artifacts(self, result: Any, markdown: str) -> None:
|
|
155
|
+
"""Persist the full workflow return value in JSON and readable Markdown."""
|
|
156
|
+
self.ensure_dirs()
|
|
157
|
+
try:
|
|
158
|
+
rendered_json = json.dumps(result, indent=2, default=str)
|
|
159
|
+
except (TypeError, ValueError):
|
|
160
|
+
rendered_json = json.dumps(str(result), indent=2)
|
|
161
|
+
self._result_json_path.write_text(rendered_json + "\n", encoding="utf-8")
|
|
162
|
+
self._result_md_path.write_text(markdown, encoding="utf-8")
|
|
163
|
+
|
|
164
|
+
def write_transcript_markdown(self, markdown: str) -> None:
|
|
165
|
+
"""Persist the readable workflow transcript."""
|
|
166
|
+
self.ensure_dirs()
|
|
167
|
+
self._transcript_md_path.write_text(markdown, encoding="utf-8")
|
|
168
|
+
|
|
99
169
|
def load_cache(self) -> Dict[int, Tuple[str, Any]]:
|
|
100
170
|
"""Read a prior run's journal into ``{call_index: (key, value)}``.
|
|
101
171
|
|
|
@@ -150,8 +150,19 @@ class WorkflowRuntime:
|
|
|
150
150
|
|
|
151
151
|
cached = self._resume_cache.get(index)
|
|
152
152
|
if cached is not None and cached[0] == key:
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
cached_value = cached[1]
|
|
154
|
+
label = spec.label or prompt[:60]
|
|
155
|
+
self._journal.append_transcript_event(
|
|
156
|
+
{
|
|
157
|
+
"type": "agent_cached",
|
|
158
|
+
"index": index,
|
|
159
|
+
"label": label,
|
|
160
|
+
"phase": spec.phase,
|
|
161
|
+
"value": cached_value,
|
|
162
|
+
}
|
|
163
|
+
)
|
|
164
|
+
self._emit_soon("workflow_agent_cached", {"label": label, "phase": spec.phase})
|
|
165
|
+
return cached_value
|
|
155
166
|
|
|
156
167
|
self._agent_count += 1
|
|
157
168
|
if self._agent_count > self._agent_cap:
|
|
@@ -169,7 +180,34 @@ class WorkflowRuntime:
|
|
|
169
180
|
|
|
170
181
|
self.budget.add(result.tokens)
|
|
171
182
|
value = result.value
|
|
172
|
-
self._journal.record(
|
|
183
|
+
self._journal.record(
|
|
184
|
+
index,
|
|
185
|
+
key,
|
|
186
|
+
spec.label,
|
|
187
|
+
value,
|
|
188
|
+
status=result.status,
|
|
189
|
+
phase=spec.phase,
|
|
190
|
+
agent_type=spec.agent_type,
|
|
191
|
+
tokens=result.tokens,
|
|
192
|
+
error=result.error,
|
|
193
|
+
transcript_path=result.transcript_path,
|
|
194
|
+
transcript_markdown_path=result.transcript_markdown_path,
|
|
195
|
+
)
|
|
196
|
+
self._journal.append_transcript_event(
|
|
197
|
+
{
|
|
198
|
+
"type": "agent_call",
|
|
199
|
+
"index": index,
|
|
200
|
+
"label": spec.label,
|
|
201
|
+
"phase": spec.phase,
|
|
202
|
+
"agent_type": spec.agent_type,
|
|
203
|
+
"status": result.status,
|
|
204
|
+
"tokens": result.tokens,
|
|
205
|
+
"error": result.error,
|
|
206
|
+
"value": value,
|
|
207
|
+
"transcript_path": result.transcript_path,
|
|
208
|
+
"transcript_markdown_path": result.transcript_markdown_path,
|
|
209
|
+
}
|
|
210
|
+
)
|
|
173
211
|
return value
|
|
174
212
|
|
|
175
213
|
async def parallel(self, thunks: Iterable[Callable[[], Awaitable[Any]]]) -> List[Any]:
|
|
@@ -56,6 +56,8 @@ class AgentRunResult:
|
|
|
56
56
|
agent_id: Optional[str] = None
|
|
57
57
|
status: str = "completed" # completed | failed | skipped
|
|
58
58
|
error: Optional[str] = None
|
|
59
|
+
transcript_path: Optional[str] = None
|
|
60
|
+
transcript_markdown_path: Optional[str] = None
|
|
59
61
|
|
|
60
62
|
@property
|
|
61
63
|
def value(self) -> Any:
|
|
@@ -46,6 +46,10 @@ Do not run destructive commands automatically. Treat commands that delete files,
|
|
|
46
46
|
|
|
47
47
|
When running tests or builds, choose the smallest command that gives confidence first, then broaden verification when the change has a wider blast radius.
|
|
48
48
|
|
|
49
|
+
## Git Branches and Pull Requests
|
|
50
|
+
|
|
51
|
+
When creating a branch or opening a pull request, follow repository or user conventions if provided; otherwise use Conventional Commits-style names. Use lowercase kebab-case branch names with a conventional type prefix, such as `feat/add-login-rate-limit` or `fix/navbar-overlap`. Use Conventional Commit PR titles, such as `feat(auth): add session timeout` or `fix: handle empty search results`. Keep names descriptive but not overly long.
|
|
52
|
+
|
|
49
53
|
## Development Servers
|
|
50
54
|
|
|
51
55
|
When starting a local development server, use an available port and tell the user the URL. If a server is already running on the default port, use another suitable port. Stop servers you started when they are no longer needed unless the user is actively testing them.
|
{kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/test_compaction_tui_events.py
RENAMED
|
@@ -39,7 +39,8 @@ async def test_compress_history_emits_error_phase_on_failure(tmp_path):
|
|
|
39
39
|
|
|
40
40
|
def test_app_apply_compaction_status_toggles_indicator():
|
|
41
41
|
# Exercise the dashboard toggle without constructing the full Textual app.
|
|
42
|
-
from kolega_code.cli.app import KolegaCodeApp
|
|
42
|
+
from kolega_code.cli.app import KolegaCodeApp
|
|
43
|
+
from kolega_code.cli.tui.state import StatusDashboardState
|
|
43
44
|
|
|
44
45
|
refreshed = []
|
|
45
46
|
fake = SimpleNamespace(
|
|
@@ -60,7 +61,8 @@ def test_app_apply_compaction_status_toggles_indicator():
|
|
|
60
61
|
|
|
61
62
|
def test_app_apply_compaction_status_adds_summary_collapsible():
|
|
62
63
|
# On finish with a summary, a collapsible transcript entry is created.
|
|
63
|
-
from kolega_code.cli.app import
|
|
64
|
+
from kolega_code.cli.app import KolegaCodeApp
|
|
65
|
+
from kolega_code.cli.tui.state import ConversationEntry, StatusDashboardState
|
|
64
66
|
|
|
65
67
|
added = []
|
|
66
68
|
fake = SimpleNamespace(
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
|
|
3
3
|
from kolega_code.agent import prompts
|
|
4
|
+
from kolega_code.agent.orchestration.guide import GIGACODE_AUTHORING_GUIDE
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
def test_static_prompt_templates_load() -> None:
|
|
@@ -45,6 +46,13 @@ def test_implement_plan_prompt_includes_gigacode_nudge_when_enabled() -> None:
|
|
|
45
46
|
assert "- [ ] update docs" in rendered
|
|
46
47
|
|
|
47
48
|
|
|
49
|
+
def test_gigacode_guide_points_agents_to_artifact_transcripts() -> None:
|
|
50
|
+
assert "resultPath" in GIGACODE_AUTHORING_GUIDE
|
|
51
|
+
assert "transcriptPath" in GIGACODE_AUTHORING_GUIDE
|
|
52
|
+
assert "Never re-run a completed workflow solely" in GIGACODE_AUTHORING_GUIDE
|
|
53
|
+
assert "READ `resultPath` or `transcriptPath`" in GIGACODE_AUTHORING_GUIDE
|
|
54
|
+
|
|
55
|
+
|
|
48
56
|
def test_init_agents_prompt_renders_arguments() -> None:
|
|
49
57
|
rendered = prompts.build_init_agents_prompt("focus on Python packaging")
|
|
50
58
|
|
{kolega_code-0.8.1 → kolega_code-0.8.2}/kolega_code/agent/tests/tool_backend/test_workflow_tool.py
RENAMED
|
@@ -6,7 +6,7 @@ the real run_workflow code path (state-dir resolution, journal, emit, summary).
|
|
|
6
6
|
|
|
7
7
|
import json
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
from unittest.mock import AsyncMock, Mock
|
|
9
|
+
from unittest.mock import AsyncMock, Mock, patch
|
|
10
10
|
|
|
11
11
|
import pytest
|
|
12
12
|
|
|
@@ -29,6 +29,9 @@ def caller():
|
|
|
29
29
|
c.sub_agent = False
|
|
30
30
|
c.current_tool_execution_id = "exec-1"
|
|
31
31
|
c.current_tool_call_id = "exec-1"
|
|
32
|
+
c.sub_agent_recorder = None
|
|
33
|
+
c.prompt_extensions = None
|
|
34
|
+
c.tool_extensions = None
|
|
32
35
|
c.tool_collection = Mock(read_only=False) # build-mode (writable) caller by default
|
|
33
36
|
return c
|
|
34
37
|
|
|
@@ -54,8 +57,20 @@ def _stub_dispatch():
|
|
|
54
57
|
"""A dispatch_workflow_agent stub returning (recap, tokens, structured)."""
|
|
55
58
|
calls = []
|
|
56
59
|
|
|
57
|
-
async def dispatch_workflow_agent(
|
|
58
|
-
|
|
60
|
+
async def dispatch_workflow_agent(
|
|
61
|
+
agent_class,
|
|
62
|
+
task,
|
|
63
|
+
*,
|
|
64
|
+
config=None,
|
|
65
|
+
schema=None,
|
|
66
|
+
sub_agent_info_extra=None,
|
|
67
|
+
artifact_paths=None,
|
|
68
|
+
artifact_metadata=None,
|
|
69
|
+
):
|
|
70
|
+
calls.append((task, schema, sub_agent_info_extra, artifact_paths, artifact_metadata))
|
|
71
|
+
if artifact_paths:
|
|
72
|
+
artifact_paths["jsonl"].write_text(json.dumps({"role": "assistant", "content": task}) + "\n")
|
|
73
|
+
artifact_paths["markdown"].write_text(f"# Agent artifact\n\n{task}\n")
|
|
59
74
|
if schema:
|
|
60
75
|
return (f"recap:{task}", 7, {"task": task})
|
|
61
76
|
return (f"recap:{task}", 3, None)
|
|
@@ -85,14 +100,21 @@ async def test_run_workflow_writes_artifacts_and_summary(workflow_tool):
|
|
|
85
100
|
assert len(calls) == 4
|
|
86
101
|
assert "Workflow 'demo' completed." in summary
|
|
87
102
|
assert "runId:" in summary and "scriptPath:" in summary
|
|
103
|
+
assert "resultPath:" in summary
|
|
104
|
+
assert "transcriptPath:" in summary
|
|
88
105
|
|
|
89
106
|
# Artifacts under <state_dir>/workflows/<run_id>/
|
|
90
107
|
run_id = next(line.split("runId:")[1].strip() for line in summary.splitlines() if "runId:" in line)
|
|
91
108
|
run_dir = Path(state_dir) / "workflows" / run_id
|
|
92
109
|
assert (run_dir / "script.py").read_text() == SCRIPT
|
|
110
|
+
assert (run_dir / "result.md").is_file()
|
|
111
|
+
assert (run_dir / "result.json").is_file()
|
|
112
|
+
assert (run_dir / "transcript.md").is_file()
|
|
113
|
+
assert (run_dir / "transcript.jsonl").is_file()
|
|
93
114
|
meta = json.loads((run_dir / "run.json").read_text())
|
|
94
115
|
assert meta["status"] == "completed"
|
|
95
116
|
assert meta["name"] == "demo"
|
|
117
|
+
assert meta["artifacts"]["resultPath"] == str(run_dir / "result.md")
|
|
96
118
|
# token total = 3*3 (parallel) + 7 (schema) = 16
|
|
97
119
|
assert meta["total_tokens"] == 16
|
|
98
120
|
journal_lines = (run_dir / "journal.jsonl").read_text().splitlines()
|
|
@@ -122,6 +144,78 @@ async def test_run_workflow_writes_artifacts_and_summary(workflow_tool):
|
|
|
122
144
|
assert end["status"] == "completed"
|
|
123
145
|
|
|
124
146
|
|
|
147
|
+
@pytest.mark.asyncio
|
|
148
|
+
async def test_long_result_is_persisted_not_truncated_inline(workflow_tool):
|
|
149
|
+
tool, state_dir = workflow_tool
|
|
150
|
+
script = 'meta = {"name": "big", "description": "big result"}\nreturn {"blob": "x" * 5001}\n'
|
|
151
|
+
|
|
152
|
+
summary = await tool.run_workflow(script=script)
|
|
153
|
+
|
|
154
|
+
assert "resultPath:" in summary
|
|
155
|
+
assert "transcriptPath:" in summary
|
|
156
|
+
assert "result: written to resultPath" in summary
|
|
157
|
+
assert "IMPORTANT: The workflow already ran" in summary
|
|
158
|
+
assert "resultPreview:" not in summary
|
|
159
|
+
assert "… (truncated)" not in summary
|
|
160
|
+
assert len(summary) < 100_000
|
|
161
|
+
|
|
162
|
+
run_id = next(line.split("runId:")[1].strip() for line in summary.splitlines() if "runId:" in line)
|
|
163
|
+
run_dir = Path(state_dir) / "workflows" / run_id
|
|
164
|
+
result_json = json.loads((run_dir / "result.json").read_text())
|
|
165
|
+
assert result_json["blob"] == "x" * 5001
|
|
166
|
+
assert "x" * 5001 in (run_dir / "result.md").read_text()
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
@pytest.mark.asyncio
|
|
170
|
+
async def test_readable_transcript_indexes_agent_calls(workflow_tool):
|
|
171
|
+
tool, state_dir = workflow_tool
|
|
172
|
+
stub, calls = _stub_dispatch()
|
|
173
|
+
tool._agent_tool.dispatch_workflow_agent = stub
|
|
174
|
+
script = (
|
|
175
|
+
'meta = {"name": "transcript", "description": "d", "phases": [{"title": "Find"}]}\n'
|
|
176
|
+
'phase("Find")\n'
|
|
177
|
+
'await agent("alpha", label="alpha-label")\n'
|
|
178
|
+
'await agent("beta", label="beta-label", phase="Check")\n'
|
|
179
|
+
'return "done"\n'
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
summary = await tool.run_workflow(script=script)
|
|
183
|
+
|
|
184
|
+
assert len(calls) == 2
|
|
185
|
+
run_id = next(line.split("runId:")[1].strip() for line in summary.splitlines() if "runId:" in line)
|
|
186
|
+
run_dir = Path(state_dir) / "workflows" / run_id
|
|
187
|
+
transcript = (run_dir / "transcript.md").read_text()
|
|
188
|
+
assert "# Workflow transcript: transcript" in transcript
|
|
189
|
+
assert "alpha-label" in transcript
|
|
190
|
+
assert "beta-label" in transcript
|
|
191
|
+
assert "Find" in transcript
|
|
192
|
+
assert "Check" in transcript
|
|
193
|
+
# Main workflow transcript should not advertise per-agent transcript paths;
|
|
194
|
+
# agents should use the main result/transcript and avoid individual sub-agent transcripts.
|
|
195
|
+
assert "agent-000-alpha-label.md" not in transcript
|
|
196
|
+
raw_events = [json.loads(line) for line in (run_dir / "transcript.jsonl").read_text().splitlines() if line]
|
|
197
|
+
assert any(event["type"] == "agent_call" for event in raw_events)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
@pytest.mark.asyncio
|
|
201
|
+
async def test_failed_agent_call_is_recorded_in_transcript(workflow_tool):
|
|
202
|
+
tool, state_dir = workflow_tool
|
|
203
|
+
|
|
204
|
+
async def failing_dispatch(*args, **kwargs):
|
|
205
|
+
raise RuntimeError("agent exploded")
|
|
206
|
+
|
|
207
|
+
tool._agent_tool.dispatch_workflow_agent = failing_dispatch
|
|
208
|
+
script = 'meta = {"name": "failure", "description": "d"}\nvalue = await agent("boom", label="boom")\nreturn {"value": value}\n'
|
|
209
|
+
|
|
210
|
+
summary = await tool.run_workflow(script=script)
|
|
211
|
+
|
|
212
|
+
assert "transcriptPath:" in summary
|
|
213
|
+
run_id = next(line.split("runId:")[1].strip() for line in summary.splitlines() if "runId:" in line)
|
|
214
|
+
transcript = (Path(state_dir) / "workflows" / run_id / "transcript.md").read_text()
|
|
215
|
+
assert "failed" in transcript
|
|
216
|
+
assert "agent exploded" in transcript
|
|
217
|
+
|
|
218
|
+
|
|
125
219
|
@pytest.mark.asyncio
|
|
126
220
|
async def test_run_workflow_carries_phase_and_label_to_dispatch(workflow_tool):
|
|
127
221
|
tool, _ = workflow_tool
|
|
@@ -135,12 +229,52 @@ async def test_run_workflow_carries_phase_and_label_to_dispatch(workflow_tool):
|
|
|
135
229
|
"return 1\n"
|
|
136
230
|
)
|
|
137
231
|
await tool.run_workflow(script=script)
|
|
138
|
-
_task, _schema, extra = calls[0]
|
|
232
|
+
_task, _schema, extra, _artifact_paths, _artifact_metadata = calls[0]
|
|
139
233
|
assert extra["phase"] == "Build"
|
|
140
234
|
assert extra["label"] == "my-label"
|
|
141
235
|
assert "workflow_run_id" in extra
|
|
142
236
|
|
|
143
237
|
|
|
238
|
+
@pytest.mark.asyncio
|
|
239
|
+
async def test_per_agent_markdown_and_jsonl_are_written(workflow_tool):
|
|
240
|
+
tool, state_dir = workflow_tool
|
|
241
|
+
|
|
242
|
+
class ArtifactAgent:
|
|
243
|
+
agent_name = "artifact-agent"
|
|
244
|
+
|
|
245
|
+
def __init__(self, **kwargs):
|
|
246
|
+
self.total_tokens_used = 11
|
|
247
|
+
self._history = [
|
|
248
|
+
{"role": "user", "content": [{"type": "text", "text": "artifact task"}]},
|
|
249
|
+
{"role": "assistant", "content": [{"type": "text", "text": "artifact answer"}]},
|
|
250
|
+
]
|
|
251
|
+
|
|
252
|
+
async def process_message_stream(self, task):
|
|
253
|
+
yield {"type": "response", "content": "artifact answer", "complete": True, "uuid": "u1"}
|
|
254
|
+
|
|
255
|
+
def dump_message_history(self):
|
|
256
|
+
return self._history
|
|
257
|
+
|
|
258
|
+
async def recap_agent_outcome(self):
|
|
259
|
+
return "final artifact recap"
|
|
260
|
+
|
|
261
|
+
script = 'meta = {"name": "agent-artifacts", "description": "d"}\nreturn await agent("artifact task", label="artifact")\n'
|
|
262
|
+
|
|
263
|
+
with patch("kolega_code.agent.generalagent.GeneralAgent", ArtifactAgent):
|
|
264
|
+
summary = await tool.run_workflow(script=script)
|
|
265
|
+
|
|
266
|
+
run_id = next(line.split("runId:")[1].strip() for line in summary.splitlines() if "runId:" in line)
|
|
267
|
+
agents_dir = Path(state_dir) / "workflows" / run_id / "agents"
|
|
268
|
+
markdown = agents_dir / "agent-000-artifact.md"
|
|
269
|
+
raw = agents_dir / "agent-000-artifact.jsonl"
|
|
270
|
+
assert markdown.is_file()
|
|
271
|
+
assert raw.is_file()
|
|
272
|
+
markdown_text = markdown.read_text()
|
|
273
|
+
assert "artifact task" in markdown_text
|
|
274
|
+
assert "final artifact recap" in markdown_text
|
|
275
|
+
assert "artifact answer" in raw.read_text()
|
|
276
|
+
|
|
277
|
+
|
|
144
278
|
@pytest.mark.asyncio
|
|
145
279
|
async def test_resume_replays_without_redispatch(workflow_tool):
|
|
146
280
|
tool, state_dir = workflow_tool
|
|
@@ -155,6 +289,10 @@ async def test_resume_replays_without_redispatch(workflow_tool):
|
|
|
155
289
|
summary2 = await tool.run_workflow(script=SCRIPT, resume_from_run_id=run_id)
|
|
156
290
|
assert len(calls) == 0 # fully replayed from journal
|
|
157
291
|
assert "completed" in summary2
|
|
292
|
+
run_id2 = next(line.split("runId:")[1].strip() for line in summary2.splitlines() if "runId:" in line)
|
|
293
|
+
transcript2 = (Path(state_dir) / "workflows" / run_id2 / "transcript.md").read_text()
|
|
294
|
+
assert "Cached resume calls" in transcript2
|
|
295
|
+
assert "served from resume cache" in transcript2
|
|
158
296
|
|
|
159
297
|
|
|
160
298
|
@pytest.mark.asyncio
|
|
@@ -166,7 +304,7 @@ async def test_read_only_caller_forces_investigation_agents(workflow_tool, calle
|
|
|
166
304
|
|
|
167
305
|
seen = []
|
|
168
306
|
|
|
169
|
-
async def stub(agent_class, task, *, config=None, schema=None, sub_agent_info_extra=None):
|
|
307
|
+
async def stub(agent_class, task, *, config=None, schema=None, sub_agent_info_extra=None, **kwargs):
|
|
170
308
|
seen.append(agent_class.__name__)
|
|
171
309
|
return (f"recap:{task}", 1, None)
|
|
172
310
|
|