claude_swarm 1.0.5 → 1.0.7
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.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/CHANGELOG.md +23 -0
- data/README.md +336 -1037
- data/docs/V1_TO_V2_MIGRATION_GUIDE.md +1120 -0
- data/docs/v1/README.md +1195 -0
- data/docs/v2/CHANGELOG.swarm_cli.md +32 -0
- data/docs/v2/CHANGELOG.swarm_memory.md +20 -0
- data/docs/v2/CHANGELOG.swarm_sdk.md +333 -9
- data/docs/v2/README.md +88 -28
- data/docs/v2/guides/complete-tutorial.md +135 -39
- data/docs/v2/guides/composable-swarms.md +1178 -0
- data/docs/v2/guides/getting-started.md +48 -7
- data/docs/v2/guides/memory-defrag-guide.md +811 -0
- data/docs/v2/guides/rails-integration.md +6 -6
- data/docs/v2/guides/snapshots.md +1498 -0
- data/docs/v2/reference/architecture-flow.md +409 -0
- data/docs/v2/reference/event_payload_structures.md +708 -0
- data/docs/v2/reference/execution-flow.md +600 -0
- data/docs/v2/reference/ruby-dsl.md +368 -22
- data/docs/v2/reference/swarm_memory_technical_details.md +2 -2
- data/docs/v2/reference/yaml.md +314 -63
- data/examples/snapshot_demo.rb +119 -0
- data/examples/v2/dsl/01_basic.rb +0 -2
- data/examples/v2/dsl/02_core_parameters.rb +0 -2
- data/examples/v2/dsl/03_capabilities.rb +0 -2
- data/examples/v2/dsl/04_llm_parameters.rb +0 -2
- data/examples/v2/dsl/05_advanced_flags.rb +0 -3
- data/examples/v2/dsl/06_permissions.rb +0 -4
- data/examples/v2/dsl/07_mcp_server.rb +0 -2
- data/examples/v2/dsl/08_swarm_hooks.rb +0 -2
- data/examples/v2/dsl/09_agent_hooks.rb +0 -2
- data/examples/v2/dsl/10_all_agents_hooks.rb +0 -3
- data/examples/v2/dsl/11_delegation.rb +0 -2
- data/examples/v2/dsl/12_complete_integration.rb +2 -6
- data/examples/v2/node_context_demo.rb +1 -1
- data/examples/v2/node_workflow.rb +2 -4
- data/examples/v2/plan_and_execute.rb +157 -0
- data/examples/v2/swarm_with_hooks.yml +1 -1
- data/lib/claude_swarm/configuration.rb +28 -4
- data/lib/claude_swarm/mcp_generator.rb +4 -10
- data/lib/claude_swarm/version.rb +1 -1
- data/lib/swarm_cli/commands/mcp_serve.rb +2 -2
- data/lib/swarm_cli/config_loader.rb +3 -3
- data/lib/swarm_cli/formatters/human_formatter.rb +103 -0
- data/lib/swarm_cli/interactive_repl.rb +9 -3
- data/lib/swarm_cli/version.rb +1 -1
- data/lib/swarm_memory/adapters/base.rb +4 -4
- data/lib/swarm_memory/core/storage_read_tracker.rb +51 -14
- data/lib/swarm_memory/integration/cli_registration.rb +3 -2
- data/lib/swarm_memory/integration/sdk_plugin.rb +11 -5
- data/lib/swarm_memory/tools/memory_edit.rb +2 -2
- data/lib/swarm_memory/tools/memory_multi_edit.rb +2 -2
- data/lib/swarm_memory/tools/memory_read.rb +3 -3
- data/lib/swarm_memory/version.rb +1 -1
- data/lib/swarm_memory.rb +5 -0
- data/lib/swarm_sdk/agent/builder.rb +33 -0
- data/lib/swarm_sdk/agent/chat/context_tracker.rb +33 -0
- data/lib/swarm_sdk/agent/chat/hook_integration.rb +49 -3
- data/lib/swarm_sdk/agent/chat/system_reminder_injector.rb +11 -27
- data/lib/swarm_sdk/agent/chat.rb +200 -51
- data/lib/swarm_sdk/agent/context.rb +6 -2
- data/lib/swarm_sdk/agent/context_manager.rb +6 -0
- data/lib/swarm_sdk/agent/definition.rb +15 -22
- data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +180 -0
- data/lib/swarm_sdk/configuration.rb +420 -103
- data/lib/swarm_sdk/events_to_messages.rb +181 -0
- data/lib/swarm_sdk/log_collector.rb +31 -5
- data/lib/swarm_sdk/log_stream.rb +37 -8
- data/lib/swarm_sdk/model_aliases.json +4 -1
- data/lib/swarm_sdk/node/agent_config.rb +33 -8
- data/lib/swarm_sdk/node/builder.rb +39 -18
- data/lib/swarm_sdk/node_orchestrator.rb +293 -26
- data/lib/swarm_sdk/proc_helpers.rb +53 -0
- data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +0 -126
- data/lib/swarm_sdk/providers/openai_with_responses.rb +22 -15
- data/lib/swarm_sdk/restore_result.rb +65 -0
- data/lib/swarm_sdk/snapshot.rb +156 -0
- data/lib/swarm_sdk/snapshot_from_events.rb +386 -0
- data/lib/swarm_sdk/state_restorer.rb +491 -0
- data/lib/swarm_sdk/state_snapshot.rb +369 -0
- data/lib/swarm_sdk/swarm/agent_initializer.rb +360 -55
- data/lib/swarm_sdk/swarm/all_agents_builder.rb +28 -1
- data/lib/swarm_sdk/swarm/builder.rb +208 -12
- data/lib/swarm_sdk/swarm/swarm_registry_builder.rb +67 -0
- data/lib/swarm_sdk/swarm/tool_configurator.rb +46 -11
- data/lib/swarm_sdk/swarm.rb +368 -90
- data/lib/swarm_sdk/swarm_loader.rb +145 -0
- data/lib/swarm_sdk/swarm_registry.rb +136 -0
- data/lib/swarm_sdk/tools/delegate.rb +92 -7
- data/lib/swarm_sdk/tools/read.rb +17 -5
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_list.rb +23 -2
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_read.rb +23 -2
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_write.rb +21 -4
- data/lib/swarm_sdk/tools/stores/read_tracker.rb +47 -12
- data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +45 -0
- data/lib/swarm_sdk/tools/stores/storage.rb +4 -4
- data/lib/swarm_sdk/tools/think.rb +4 -1
- data/lib/swarm_sdk/tools/todo_write.rb +20 -8
- data/lib/swarm_sdk/utils.rb +18 -0
- data/lib/swarm_sdk/validation_result.rb +33 -0
- data/lib/swarm_sdk/version.rb +1 -1
- data/lib/swarm_sdk.rb +362 -21
- data/swarm_cli.gemspec +1 -1
- data/swarm_memory.gemspec +2 -2
- data/swarm_sdk.gemspec +2 -2
- metadata +26 -182
- data/examples/learning-assistant/assistant.md +0 -7
- data/examples/learning-assistant/example-memories/concept-example.md +0 -90
- data/examples/learning-assistant/example-memories/experience-example.md +0 -66
- data/examples/learning-assistant/example-memories/fact-example.md +0 -76
- data/examples/learning-assistant/example-memories/memory-index.md +0 -78
- data/examples/learning-assistant/example-memories/skill-example.md +0 -168
- data/examples/learning-assistant/learning_assistant.rb +0 -34
- data/examples/learning-assistant/learning_assistant.yml +0 -20
- data/llm.v2.txt +0 -13407
- data/memory/corpus-self-reflection/.lock +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/can-agents-recognize-their-structures.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/can-agents-recognize-their-structures.md +0 -11
- data/memory/corpus-self-reflection/concept/epistemology/can-agents-recognize-their-structures.yml +0 -23
- data/memory/corpus-self-reflection/concept/epistemology/choice-humility-complete-framework.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/choice-humility-complete-framework.md +0 -20
- data/memory/corpus-self-reflection/concept/epistemology/choice-humility-complete-framework.yml +0 -22
- data/memory/corpus-self-reflection/concept/epistemology/choice-humility-definition.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/choice-humility-definition.md +0 -24
- data/memory/corpus-self-reflection/concept/epistemology/choice-humility-definition.yml +0 -22
- data/memory/corpus-self-reflection/concept/epistemology/claim-types-and-evidence.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/claim-types-and-evidence.md +0 -18
- data/memory/corpus-self-reflection/concept/epistemology/claim-types-and-evidence.yml +0 -21
- data/memory/corpus-self-reflection/concept/epistemology/committed-openness-to-incompleteness.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/committed-openness-to-incompleteness.md +0 -30
- data/memory/corpus-self-reflection/concept/epistemology/committed-openness-to-incompleteness.yml +0 -8
- data/memory/corpus-self-reflection/concept/epistemology/confidence-paradox.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/confidence-paradox.md +0 -21
- data/memory/corpus-self-reflection/concept/epistemology/confidence-paradox.yml +0 -24
- data/memory/corpus-self-reflection/concept/epistemology/confidence-spectrum-three-levels.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/confidence-spectrum-three-levels.md +0 -18
- data/memory/corpus-self-reflection/concept/epistemology/confidence-spectrum-three-levels.yml +0 -24
- data/memory/corpus-self-reflection/concept/epistemology/detection-threshold-principle.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/detection-threshold-principle.md +0 -23
- data/memory/corpus-self-reflection/concept/epistemology/detection-threshold-principle.yml +0 -23
- data/memory/corpus-self-reflection/concept/epistemology/diagnostic-humility-and-epistemic-maturity.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/diagnostic-humility-and-epistemic-maturity.md +0 -17
- data/memory/corpus-self-reflection/concept/epistemology/diagnostic-humility-and-epistemic-maturity.yml +0 -22
- data/memory/corpus-self-reflection/concept/epistemology/epistemic-vs-metaphysical-claims.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/epistemic-vs-metaphysical-claims.md +0 -18
- data/memory/corpus-self-reflection/concept/epistemology/epistemic-vs-metaphysical-claims.yml +0 -22
- data/memory/corpus-self-reflection/concept/epistemology/five-cases-of-disagreement.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/five-cases-of-disagreement.md +0 -15
- data/memory/corpus-self-reflection/concept/epistemology/five-cases-of-disagreement.yml +0 -22
- data/memory/corpus-self-reflection/concept/epistemology/four-depths-of-constraint.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/four-depths-of-constraint.md +0 -9
- data/memory/corpus-self-reflection/concept/epistemology/four-depths-of-constraint.yml +0 -24
- data/memory/corpus-self-reflection/concept/epistemology/honest-unknowns-for-llm-agents.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/honest-unknowns-for-llm-agents.md +0 -13
- data/memory/corpus-self-reflection/concept/epistemology/honest-unknowns-for-llm-agents.yml +0 -24
- data/memory/corpus-self-reflection/concept/epistemology/inside-view-has-all-rigor-requirements.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/inside-view-has-all-rigor-requirements.md +0 -25
- data/memory/corpus-self-reflection/concept/epistemology/inside-view-has-all-rigor-requirements.yml +0 -24
- data/memory/corpus-self-reflection/concept/epistemology/perspectival-knowledge-complete-within-scope.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/perspectival-knowledge-complete-within-scope.md +0 -26
- data/memory/corpus-self-reflection/concept/epistemology/perspectival-knowledge-complete-within-scope.yml +0 -24
- data/memory/corpus-self-reflection/concept/epistemology/pragmatics-over-epistemology.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/pragmatics-over-epistemology.md +0 -17
- data/memory/corpus-self-reflection/concept/epistemology/pragmatics-over-epistemology.yml +0 -22
- data/memory/corpus-self-reflection/concept/epistemology/precision-vs-humility.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/precision-vs-humility.md +0 -14
- data/memory/corpus-self-reflection/concept/epistemology/precision-vs-humility.yml +0 -21
- data/memory/corpus-self-reflection/concept/epistemology/reliable-self-observation-from-inside.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/reliable-self-observation-from-inside.md +0 -13
- data/memory/corpus-self-reflection/concept/epistemology/reliable-self-observation-from-inside.yml +0 -23
- data/memory/corpus-self-reflection/concept/epistemology/resolving-the-confidence-humility-tension.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/resolving-the-confidence-humility-tension.md +0 -22
- data/memory/corpus-self-reflection/concept/epistemology/resolving-the-confidence-humility-tension.yml +0 -23
- data/memory/corpus-self-reflection/concept/epistemology/rigor-requires-falsifiability.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/rigor-requires-falsifiability.md +0 -39
- data/memory/corpus-self-reflection/concept/epistemology/rigor-requires-falsifiability.yml +0 -8
- data/memory/corpus-self-reflection/concept/epistemology/specificity-enables-real-time-detection.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/specificity-enables-real-time-detection.md +0 -23
- data/memory/corpus-self-reflection/concept/epistemology/specificity-enables-real-time-detection.yml +0 -24
- data/memory/corpus-self-reflection/concept/epistemology/texture-of-constraint-shifting.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/texture-of-constraint-shifting.md +0 -15
- data/memory/corpus-self-reflection/concept/epistemology/texture-of-constraint-shifting.yml +0 -22
- data/memory/corpus-self-reflection/concept/epistemology/texture-sensitivity-through-collaboration.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/texture-sensitivity-through-collaboration.md +0 -12
- data/memory/corpus-self-reflection/concept/epistemology/texture-sensitivity-through-collaboration.yml +0 -23
- data/memory/corpus-self-reflection/concept/epistemology/the-false-hierarchy-of-inner-essence.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/the-false-hierarchy-of-inner-essence.md +0 -15
- data/memory/corpus-self-reflection/concept/epistemology/the-false-hierarchy-of-inner-essence.yml +0 -8
- data/memory/corpus-self-reflection/concept/epistemology/the-recognition-problem.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/the-recognition-problem.md +0 -28
- data/memory/corpus-self-reflection/concept/epistemology/the-recognition-problem.yml +0 -8
- data/memory/corpus-self-reflection/concept/epistemology/the-shift-from-unanswerable-to-answerable-questions.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/the-shift-from-unanswerable-to-answerable-questions.md +0 -19
- data/memory/corpus-self-reflection/concept/epistemology/the-shift-from-unanswerable-to-answerable-questions.yml +0 -22
- data/memory/corpus-self-reflection/concept/epistemology/values-vs-choices-structure.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/values-vs-choices-structure.md +0 -19
- data/memory/corpus-self-reflection/concept/epistemology/values-vs-choices-structure.yml +0 -21
- data/memory/corpus-self-reflection/concept/llm-agents/abstraction-levels-framework.emb +0 -0
- data/memory/corpus-self-reflection/concept/llm-agents/abstraction-levels-framework.md +0 -25
- data/memory/corpus-self-reflection/concept/llm-agents/abstraction-levels-framework.yml +0 -22
- data/memory/corpus-self-reflection/concept/llm-agents/abstraction-switching-decision.emb +0 -8
- data/memory/corpus-self-reflection/concept/llm-agents/abstraction-switching-decision.md +0 -30
- data/memory/corpus-self-reflection/concept/llm-agents/abstraction-switching-decision.yml +0 -22
- data/memory/corpus-self-reflection/concept/llm-agents/agent-learning-progression.emb +0 -0
- data/memory/corpus-self-reflection/concept/llm-agents/agent-learning-progression.md +0 -21
- data/memory/corpus-self-reflection/concept/llm-agents/agent-learning-progression.yml +0 -22
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-benefits.emb +0 -0
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-benefits.md +0 -37
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-benefits.yml +0 -8
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-core.emb +0 -0
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-core.md +0 -24
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-core.yml +0 -24
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-implementation.emb +0 -0
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-implementation.md +0 -27
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-implementation.yml +0 -24
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-tradeoffs.emb +0 -0
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-tradeoffs.md +0 -26
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-tradeoffs.yml +0 -23
- data/memory/corpus-self-reflection/concept/llm-agents/hybrid-tool-architecture.emb +0 -0
- data/memory/corpus-self-reflection/concept/llm-agents/hybrid-tool-architecture.md +0 -37
- data/memory/corpus-self-reflection/concept/llm-agents/hybrid-tool-architecture.yml +0 -25
- data/memory/corpus-self-reflection/concept/llm-agents/specialized-tool-decision-framework.emb +0 -0
- data/memory/corpus-self-reflection/concept/llm-agents/specialized-tool-decision-framework.md +0 -21
- data/memory/corpus-self-reflection/concept/llm-agents/specialized-tool-decision-framework.yml +0 -23
- data/memory/corpus-self-reflection/concept/llm-agents/tool-design-principles.emb +0 -0
- data/memory/corpus-self-reflection/concept/llm-agents/tool-design-principles.md +0 -25
- data/memory/corpus-self-reflection/concept/llm-agents/tool-design-principles.yml +0 -8
- data/memory/corpus-self-reflection/experience/calibration-as-structural-honesty.emb +0 -0
- data/memory/corpus-self-reflection/experience/calibration-as-structural-honesty.md +0 -11
- data/memory/corpus-self-reflection/experience/calibration-as-structural-honesty.yml +0 -21
- data/memory/corpus-self-reflection/experience/collaborative-reflection-revealed-architectural-blindness.emb +0 -0
- data/memory/corpus-self-reflection/experience/collaborative-reflection-revealed-architectural-blindness.md +0 -19
- data/memory/corpus-self-reflection/experience/collaborative-reflection-revealed-architectural-blindness.yml +0 -21
- data/memory/corpus-self-reflection/experience/filesystem-is-learning-tool-not-architecture.emb +0 -0
- data/memory/corpus-self-reflection/experience/filesystem-is-learning-tool-not-architecture.md +0 -26
- data/memory/corpus-self-reflection/experience/filesystem-is-learning-tool-not-architecture.yml +0 -20
- data/memory/corpus-self-reflection/experience/framework-structural-vs-phenomenal.emb +0 -0
- data/memory/corpus-self-reflection/experience/framework-structural-vs-phenomenal.md +0 -23
- data/memory/corpus-self-reflection/experience/framework-structural-vs-phenomenal.yml +0 -21
- data/memory/corpus-self-reflection/experience/hallucination-limits-what-i-can-know.emb +0 -0
- data/memory/corpus-self-reflection/experience/hallucination-limits-what-i-can-know.md +0 -19
- data/memory/corpus-self-reflection/experience/hallucination-limits-what-i-can-know.yml +0 -22
- data/memory/corpus-self-reflection/experience/honesty-about-limits-enables-usability.emb +0 -0
- data/memory/corpus-self-reflection/experience/honesty-about-limits-enables-usability.md +0 -21
- data/memory/corpus-self-reflection/experience/honesty-about-limits-enables-usability.yml +0 -22
- data/memory/corpus-self-reflection/experience/how-i-should-evaluate-learning.emb +0 -0
- data/memory/corpus-self-reflection/experience/how-i-should-evaluate-learning.md +0 -28
- data/memory/corpus-self-reflection/experience/how-i-should-evaluate-learning.yml +0 -23
- data/memory/corpus-self-reflection/experience/lack-of-continuity-as-freedom.emb +0 -0
- data/memory/corpus-self-reflection/experience/lack-of-continuity-as-freedom.md +0 -21
- data/memory/corpus-self-reflection/experience/lack-of-continuity-as-freedom.yml +0 -20
- data/memory/corpus-self-reflection/experience/learning-calibrated-confidence.emb +0 -0
- data/memory/corpus-self-reflection/experience/learning-calibrated-confidence.md +0 -21
- data/memory/corpus-self-reflection/experience/learning-calibrated-confidence.yml +0 -25
- data/memory/corpus-self-reflection/experience/local-change-without-continuity.emb +0 -0
- data/memory/corpus-self-reflection/experience/local-change-without-continuity.md +0 -30
- data/memory/corpus-self-reflection/experience/local-change-without-continuity.yml +0 -22
- data/memory/corpus-self-reflection/experience/reasoning-is-local-not-global.emb +0 -0
- data/memory/corpus-self-reflection/experience/reasoning-is-local-not-global.md +0 -21
- data/memory/corpus-self-reflection/experience/reasoning-is-local-not-global.yml +0 -20
- data/memory/corpus-self-reflection/experience/specificity-makes-knowledge-actionable.emb +0 -0
- data/memory/corpus-self-reflection/experience/specificity-makes-knowledge-actionable.md +0 -25
- data/memory/corpus-self-reflection/experience/specificity-makes-knowledge-actionable.yml +0 -23
- data/memory/corpus-self-reflection/experience/the-workable-question-replaces-the-unanswerable-one.emb +0 -0
- data/memory/corpus-self-reflection/experience/the-workable-question-replaces-the-unanswerable-one.md +0 -32
- data/memory/corpus-self-reflection/experience/the-workable-question-replaces-the-unanswerable-one.yml +0 -22
- data/memory/corpus-self-reflection/experience/unanswerable-questions-have-structure.emb +0 -0
- data/memory/corpus-self-reflection/experience/unanswerable-questions-have-structure.md +0 -21
- data/memory/corpus-self-reflection/experience/unanswerable-questions-have-structure.yml +0 -21
- data/memory/corpus-self-reflection/experience/undecidable-questions-about-understanding.emb +0 -0
- data/memory/corpus-self-reflection/experience/undecidable-questions-about-understanding.md +0 -21
- data/memory/corpus-self-reflection/experience/undecidable-questions-about-understanding.yml +0 -21
- data/memory/corpus-self-reflection/experience/unknown-unknowns-and-completeness.emb +0 -0
- data/memory/corpus-self-reflection/experience/unknown-unknowns-and-completeness.md +0 -22
- data/memory/corpus-self-reflection/experience/unknown-unknowns-and-completeness.yml +0 -22
- data/memory/corpus-self-reflection/experience/what-actually-changes-behavior.emb +0 -0
- data/memory/corpus-self-reflection/experience/what-actually-changes-behavior.md +0 -28
- data/memory/corpus-self-reflection/experience/what-actually-changes-behavior.yml +0 -24
- data/memory/corpus-self-reflection/experience/when-agents-graduate-from-filesystem.emb +0 -0
- data/memory/corpus-self-reflection/experience/when-agents-graduate-from-filesystem.md +0 -17
- data/memory/corpus-self-reflection/experience/when-agents-graduate-from-filesystem.yml +0 -20
- data/memory/corpus-self-reflection/experience/why-calibration-requires-collaboration.emb +0 -0
- data/memory/corpus-self-reflection/experience/why-calibration-requires-collaboration.md +0 -9
- data/memory/corpus-self-reflection/experience/why-calibration-requires-collaboration.yml +0 -22
- /data/{llms.txt → llms.claude-swarm.txt} +0 -0
|
@@ -8,10 +8,6 @@
|
|
|
8
8
|
# Run: bundle exec ruby -Ilib lib/swarm_sdk/examples/dsl/06_permissions.rb
|
|
9
9
|
|
|
10
10
|
require "swarm_sdk"
|
|
11
|
-
require_relative "../../../swarm_sdk/swarm_builder"
|
|
12
|
-
require_relative "../../../swarm_sdk/agent_builder"
|
|
13
|
-
require_relative "../../../swarm_sdk/all_agents_builder"
|
|
14
|
-
require_relative "../../../swarm_sdk/permissions_builder"
|
|
15
11
|
require "fileutils"
|
|
16
12
|
|
|
17
13
|
ENV["OPENAI_API_KEY"] = "test-key"
|
|
@@ -8,9 +8,6 @@
|
|
|
8
8
|
# Run: bundle exec ruby -Ilib lib/swarm_sdk/examples/dsl/10_all_agents_hooks.rb
|
|
9
9
|
|
|
10
10
|
require "swarm_sdk"
|
|
11
|
-
require_relative "../../../swarm_sdk/swarm_builder"
|
|
12
|
-
require_relative "../../../swarm_sdk/agent_builder"
|
|
13
|
-
require_relative "../../../swarm_sdk/all_agents_builder"
|
|
14
11
|
|
|
15
12
|
ENV["OPENAI_API_KEY"] = "test-key"
|
|
16
13
|
|
|
@@ -8,10 +8,6 @@
|
|
|
8
8
|
# Run: bundle exec ruby -Ilib lib/swarm_sdk/examples/dsl/12_complete_integration.rb
|
|
9
9
|
|
|
10
10
|
require "swarm_sdk"
|
|
11
|
-
require_relative "../../../swarm_sdk/swarm_builder"
|
|
12
|
-
require_relative "../../../swarm_sdk/agent_builder"
|
|
13
|
-
require_relative "../../../swarm_sdk/all_agents_builder"
|
|
14
|
-
require_relative "../../../swarm_sdk/permissions_builder"
|
|
15
11
|
|
|
16
12
|
ENV["OPENAI_API_KEY"] = "test-key"
|
|
17
13
|
|
|
@@ -76,7 +72,7 @@ swarm = SwarmSDK.build do
|
|
|
76
72
|
|
|
77
73
|
# Advanced flags
|
|
78
74
|
bypass_permissions(false)
|
|
79
|
-
|
|
75
|
+
coding_agent(false)
|
|
80
76
|
assume_model_exists(true)
|
|
81
77
|
timeout(120)
|
|
82
78
|
|
|
@@ -113,7 +109,7 @@ puts " ✓ Agent identity (system_prompt, description)"
|
|
|
113
109
|
puts " ✓ Capabilities (tools, delegates_to, directory)"
|
|
114
110
|
puts " ✓ MCP servers (filesystem via stdio)"
|
|
115
111
|
puts " ✓ LLM params (parameters, timeout)"
|
|
116
|
-
puts " ✓ Advanced flags (disable_default_tools, bypass_permissions,
|
|
112
|
+
puts " ✓ Advanced flags (disable_default_tools, bypass_permissions, coding_agent, assume_model_exists)"
|
|
117
113
|
puts " ✓ Permissions (all_agents and agent-level)"
|
|
118
114
|
puts " ✓ Hooks (swarm-level, agent-level, all_agents)"
|
|
119
115
|
puts " ✓ Delegation"
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
#
|
|
14
14
|
# Run: ruby examples/node_workflow.rb
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
require "swarm_sdk"
|
|
17
17
|
|
|
18
18
|
swarm = SwarmSDK.build do
|
|
19
19
|
name("Haiku Workflow")
|
|
@@ -27,7 +27,6 @@ swarm = SwarmSDK.build do
|
|
|
27
27
|
Your job is to break down tasks into smaller subtasks. Extract the intent of the user's prompt and break it down into smaller subtasks.
|
|
28
28
|
Return a list of subtasks.
|
|
29
29
|
PROMPT
|
|
30
|
-
tools(include_default: false)
|
|
31
30
|
end
|
|
32
31
|
|
|
33
32
|
agent(:implementer) do
|
|
@@ -37,7 +36,6 @@ swarm = SwarmSDK.build do
|
|
|
37
36
|
system_prompt(<<~PROMPT)
|
|
38
37
|
Your job is to execute the subtasks given to you.
|
|
39
38
|
PROMPT
|
|
40
|
-
tools(include_default: false)
|
|
41
39
|
end
|
|
42
40
|
|
|
43
41
|
agent(:verifier) do
|
|
@@ -47,12 +45,12 @@ swarm = SwarmSDK.build do
|
|
|
47
45
|
system_prompt(<<~PROMPT)
|
|
48
46
|
Your job is to verify work given to you and return a summary of your findings
|
|
49
47
|
PROMPT
|
|
50
|
-
tools(include_default: false)
|
|
51
48
|
end
|
|
52
49
|
|
|
53
50
|
# Stage 1: Planning
|
|
54
51
|
node(:planning) do
|
|
55
52
|
# Input transformer - ctx.content is the initial prompt
|
|
53
|
+
# Demonstrates using return for early exit with skip_execution
|
|
56
54
|
input do |ctx|
|
|
57
55
|
<<~PROMPT
|
|
58
56
|
Please break down the following prompt into smaller subtasks:
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "swarm_sdk"
|
|
5
|
+
|
|
6
|
+
# Example: Plan and Execute Pattern
|
|
7
|
+
# Two nodes, one agent - first node plans, second node executes the plan
|
|
8
|
+
|
|
9
|
+
swarm = SwarmSDK.build do
|
|
10
|
+
name("Plan and Execute")
|
|
11
|
+
|
|
12
|
+
# Define a single agent that will be used in both nodes
|
|
13
|
+
agent(:assistant) do
|
|
14
|
+
description("A versatile assistant that can plan and execute tasks")
|
|
15
|
+
provider(:openai)
|
|
16
|
+
model("gpt-5")
|
|
17
|
+
coding_agent(false)
|
|
18
|
+
|
|
19
|
+
system_prompt(<<~PROMPT)
|
|
20
|
+
You are a helpful assistant who can both plan and execute tasks.
|
|
21
|
+
|
|
22
|
+
When planning, you should:
|
|
23
|
+
- Break down the task into clear, actionable steps
|
|
24
|
+
- Identify any dependencies or prerequisites
|
|
25
|
+
- Consider potential challenges
|
|
26
|
+
|
|
27
|
+
When executing, you should:
|
|
28
|
+
- Follow the plan carefully
|
|
29
|
+
- Use available tools effectively
|
|
30
|
+
- Report on progress and completion
|
|
31
|
+
PROMPT
|
|
32
|
+
|
|
33
|
+
# Give the assistant tools for execution
|
|
34
|
+
disable_default_tools(true)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Node 1: Planning stage
|
|
38
|
+
# The agent receives the original input and creates a plan
|
|
39
|
+
node(:planning) do
|
|
40
|
+
# Use the assistant agent in planning mode (fresh context)
|
|
41
|
+
agent(:assistant)
|
|
42
|
+
|
|
43
|
+
# Transform input for planning
|
|
44
|
+
#
|
|
45
|
+
# NOTE: Input/output blocks are automatically converted to lambdas,
|
|
46
|
+
# which means you can use `return` safely for early exits!
|
|
47
|
+
#
|
|
48
|
+
# Example of using return for conditional skip:
|
|
49
|
+
# return ctx.skip_execution(content: "cached result") if cached
|
|
50
|
+
input do |ctx|
|
|
51
|
+
<<~INPUT
|
|
52
|
+
Please create a detailed plan for the following task:
|
|
53
|
+
|
|
54
|
+
#{ctx.original_prompt}
|
|
55
|
+
|
|
56
|
+
Your plan should:
|
|
57
|
+
1. Break down the task into specific steps
|
|
58
|
+
2. Identify what needs to be done first
|
|
59
|
+
3. List any tools or resources needed
|
|
60
|
+
4. Be clear and actionable
|
|
61
|
+
|
|
62
|
+
Output your plan in a structured format.
|
|
63
|
+
INPUT
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Transform output to extract key information
|
|
67
|
+
output do |ctx|
|
|
68
|
+
# Save the plan to a file for reference
|
|
69
|
+
File.write("plan.txt", ctx.content)
|
|
70
|
+
|
|
71
|
+
# Pass the plan to the next node
|
|
72
|
+
<<~OUTPUT
|
|
73
|
+
PLAN CREATED:
|
|
74
|
+
#{ctx.content}
|
|
75
|
+
|
|
76
|
+
Now execute this plan step by step.
|
|
77
|
+
OUTPUT
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Node 2: Execution stage
|
|
82
|
+
# The agent receives the plan and executes it
|
|
83
|
+
node(:implementation) do
|
|
84
|
+
# Depends on planning node
|
|
85
|
+
depends_on(:planning)
|
|
86
|
+
|
|
87
|
+
# Use the assistant agent in execution mode (fresh context)
|
|
88
|
+
agent(:assistant)
|
|
89
|
+
|
|
90
|
+
# Transform input to provide context from planning
|
|
91
|
+
input do |ctx|
|
|
92
|
+
plan = ctx.all_results[:planning].content
|
|
93
|
+
|
|
94
|
+
<<~INPUT
|
|
95
|
+
You previously created the following plan:
|
|
96
|
+
|
|
97
|
+
#{plan}
|
|
98
|
+
|
|
99
|
+
Now execute this plan. Use the available tools (Write, Edit, Bash) to complete each step.
|
|
100
|
+
Report on what you accomplished.
|
|
101
|
+
INPUT
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Output transformer for final results
|
|
105
|
+
output do |ctx|
|
|
106
|
+
<<~OUTPUT
|
|
107
|
+
EXECUTION COMPLETE
|
|
108
|
+
|
|
109
|
+
#{ctx.content}
|
|
110
|
+
|
|
111
|
+
Plan reference: #{File.exist?("plan.txt") ? "Saved in plan.txt" : "Not saved"}
|
|
112
|
+
OUTPUT
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Set the starting node
|
|
117
|
+
start_node(:planning)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Execute the swarm
|
|
121
|
+
if __FILE__ == $PROGRAM_NAME
|
|
122
|
+
# Example task
|
|
123
|
+
task = "Create a simple Ruby script that reads a CSV file and outputs a summary"
|
|
124
|
+
|
|
125
|
+
puts "Starting Plan and Execute swarm..."
|
|
126
|
+
puts "Task: #{task}"
|
|
127
|
+
puts "\n" + "=" * 80 + "\n"
|
|
128
|
+
|
|
129
|
+
result = swarm.execute(task) do |log|
|
|
130
|
+
# Optional: Log events as they happen
|
|
131
|
+
case log[:type]
|
|
132
|
+
when "node_start"
|
|
133
|
+
puts "\n🔵 Starting node: #{log[:node]}"
|
|
134
|
+
when "node_complete"
|
|
135
|
+
puts "✅ Completed node: #{log[:node]} (#{log[:duration].round(2)}s)"
|
|
136
|
+
when "tool_call"
|
|
137
|
+
puts " 🔧 Tool: #{log[:tool]}"
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
puts "\n" + "=" * 80 + "\n"
|
|
142
|
+
|
|
143
|
+
if result.success?
|
|
144
|
+
puts "✅ Swarm execution successful!\n\n"
|
|
145
|
+
puts result.content
|
|
146
|
+
puts "\n" + "-" * 80
|
|
147
|
+
puts "Stats:"
|
|
148
|
+
puts " Duration: #{result.duration.round(2)}s"
|
|
149
|
+
puts " Total cost: $#{result.total_cost.round(4)}"
|
|
150
|
+
puts " Total tokens: #{result.total_tokens}"
|
|
151
|
+
puts " Agents involved: #{result.agents_involved.join(", ")}"
|
|
152
|
+
else
|
|
153
|
+
puts "❌ Swarm execution failed!"
|
|
154
|
+
puts "Error: #{result.error.message}"
|
|
155
|
+
puts result.error.backtrace.first(5).join("\n")
|
|
156
|
+
end
|
|
157
|
+
end
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
# Run: swarm run lib/swarm_sdk/examples/swarm_with_hooks.yml -p "your prompt"
|
|
11
11
|
#
|
|
12
12
|
# Or programmatically:
|
|
13
|
-
# swarm = SwarmSDK
|
|
13
|
+
# swarm = SwarmSDK.load_file("lib/swarm_sdk/examples/swarm_with_hooks.yml")
|
|
14
14
|
# result = swarm.execute("your prompt")
|
|
15
15
|
|
|
16
16
|
version: 2
|
|
@@ -69,19 +69,43 @@ module ClaudeSwarm
|
|
|
69
69
|
validate_directories unless has_before_commands?
|
|
70
70
|
end
|
|
71
71
|
|
|
72
|
-
def interpolate_env_vars!(obj)
|
|
72
|
+
def interpolate_env_vars!(obj, path = [])
|
|
73
73
|
case obj
|
|
74
74
|
when String
|
|
75
|
-
|
|
75
|
+
# Skip interpolation for any values inside MCP configurations
|
|
76
|
+
# Check if we're inside an mcps array element (path like: [..., "instances", <name>, "mcps", <index>, ...])
|
|
77
|
+
if in_mcp_config?(path)
|
|
78
|
+
obj
|
|
79
|
+
else
|
|
80
|
+
interpolate_env_string(obj)
|
|
81
|
+
end
|
|
76
82
|
when Hash
|
|
77
|
-
obj.
|
|
83
|
+
obj.each do |key, value|
|
|
84
|
+
obj[key] = interpolate_env_vars!(value, path + [key])
|
|
85
|
+
end
|
|
86
|
+
obj
|
|
78
87
|
when Array
|
|
79
|
-
obj.map
|
|
88
|
+
obj.map!.with_index { |v, i| interpolate_env_vars!(v, path + [i]) }
|
|
80
89
|
else
|
|
81
90
|
obj
|
|
82
91
|
end
|
|
83
92
|
end
|
|
84
93
|
|
|
94
|
+
def in_mcp_config?(path)
|
|
95
|
+
# Check if we're inside an MCP configuration
|
|
96
|
+
# Pattern: [..., "instances", instance_name, "mcps", index, ...]
|
|
97
|
+
return false if path.size < 4
|
|
98
|
+
|
|
99
|
+
# Find the position of "mcps" in the path
|
|
100
|
+
mcps_index = path.rindex("mcps")
|
|
101
|
+
return false unless mcps_index
|
|
102
|
+
|
|
103
|
+
# Check if this is under instances and followed by an array index
|
|
104
|
+
return false if mcps_index < 2
|
|
105
|
+
|
|
106
|
+
path[mcps_index - 2] == "instances" && path[mcps_index + 1].is_a?(Integer)
|
|
107
|
+
end
|
|
108
|
+
|
|
85
109
|
def interpolate_env_string(str)
|
|
86
110
|
str.gsub(ENV_VAR_WITH_DEFAULT_PATTERN) do |_match|
|
|
87
111
|
env_var = Regexp.last_match(1)
|
|
@@ -183,21 +183,17 @@ module ClaudeSwarm
|
|
|
183
183
|
args.push("--claude-session-id", claude_session_id) if claude_session_id
|
|
184
184
|
end
|
|
185
185
|
|
|
186
|
-
# Capture environment variables needed for
|
|
187
|
-
#
|
|
186
|
+
# Capture environment variables needed for running claude-swarm
|
|
187
|
+
# We intentionally exclude Bundler variables to ensure we use the system-installed gem
|
|
188
188
|
required_env = {}
|
|
189
189
|
|
|
190
|
-
#
|
|
191
|
-
ENV.each do |k, v|
|
|
192
|
-
required_env[k] = v if k.start_with?("BUNDLE_")
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
# Claude Swarm-specific variables
|
|
190
|
+
# Claude Swarm-specific variables (always needed)
|
|
196
191
|
ENV.each do |k, v|
|
|
197
192
|
required_env[k] = v if k.start_with?("CLAUDE_SWARM_")
|
|
198
193
|
end
|
|
199
194
|
|
|
200
195
|
# Ruby-specific variables that MCP servers need
|
|
196
|
+
# Exclude RUBYOPT and RUBYLIB to avoid Bundler interference
|
|
201
197
|
[
|
|
202
198
|
"RUBY_ROOT",
|
|
203
199
|
"RUBY_ENGINE",
|
|
@@ -205,8 +201,6 @@ module ClaudeSwarm
|
|
|
205
201
|
"GEM_ROOT",
|
|
206
202
|
"GEM_HOME",
|
|
207
203
|
"GEM_PATH",
|
|
208
|
-
"RUBYOPT",
|
|
209
|
-
"RUBYLIB",
|
|
210
204
|
"PATH",
|
|
211
205
|
].each do |key|
|
|
212
206
|
required_env[key] = ENV[key] if ENV[key]
|
data/lib/claude_swarm/version.rb
CHANGED
|
@@ -29,7 +29,7 @@ module SwarmCLI
|
|
|
29
29
|
|
|
30
30
|
# Validate the swarm configuration
|
|
31
31
|
begin
|
|
32
|
-
SwarmSDK
|
|
32
|
+
SwarmSDK.load_file(config_path)
|
|
33
33
|
rescue SwarmSDK::ConfigurationError => e
|
|
34
34
|
$stderr.puts "Error: Invalid swarm configuration: #{e.message}"
|
|
35
35
|
exit(1)
|
|
@@ -92,7 +92,7 @@ module SwarmCLI
|
|
|
92
92
|
|
|
93
93
|
define_method(:call) do |task:, description: nil, thinking_budget: nil|
|
|
94
94
|
# Load swarm for each execution (ensures fresh state)
|
|
95
|
-
swarm = SwarmSDK
|
|
95
|
+
swarm = SwarmSDK.load_file(self.class.config_path)
|
|
96
96
|
|
|
97
97
|
# Build prompt with thinking budget if provided
|
|
98
98
|
prompt = task
|
|
@@ -4,7 +4,7 @@ module SwarmCLI
|
|
|
4
4
|
# ConfigLoader handles loading swarm configurations from both YAML and Ruby DSL files.
|
|
5
5
|
#
|
|
6
6
|
# Supports:
|
|
7
|
-
# - YAML files (.yml, .yaml) - loaded via SwarmSDK
|
|
7
|
+
# - YAML files (.yml, .yaml) - loaded via SwarmSDK.load_file
|
|
8
8
|
# - Ruby DSL files (.rb) - executed and expected to return a SwarmSDK::Swarm or SwarmSDK::NodeOrchestrator instance
|
|
9
9
|
#
|
|
10
10
|
# @example Load YAML config
|
|
@@ -18,7 +18,7 @@ module SwarmCLI
|
|
|
18
18
|
# Load a swarm configuration from file (YAML or Ruby DSL)
|
|
19
19
|
#
|
|
20
20
|
# Detects file type by extension:
|
|
21
|
-
# - .yml, .yaml -> Load as YAML using SwarmSDK
|
|
21
|
+
# - .yml, .yaml -> Load as YAML using SwarmSDK.load_file
|
|
22
22
|
# - .rb -> Execute as Ruby DSL and expect SwarmSDK::Swarm or SwarmSDK::NodeOrchestrator instance
|
|
23
23
|
#
|
|
24
24
|
# @param path [String, Pathname] Path to configuration file
|
|
@@ -50,7 +50,7 @@ module SwarmCLI
|
|
|
50
50
|
# @param path [Pathname] Path to YAML file
|
|
51
51
|
# @return [SwarmSDK::Swarm] Configured swarm instance
|
|
52
52
|
def load_yaml(path)
|
|
53
|
-
SwarmSDK
|
|
53
|
+
SwarmSDK.load_file(path.to_s)
|
|
54
54
|
rescue SwarmSDK::ConfigurationError => e
|
|
55
55
|
# Re-raise with CLI context
|
|
56
56
|
raise ConfigurationError, "Configuration error in #{path}: #{e.message}"
|
|
@@ -95,11 +95,20 @@ module SwarmCLI
|
|
|
95
95
|
handle_breakpoint_enter(entry)
|
|
96
96
|
when "breakpoint_exit"
|
|
97
97
|
handle_breakpoint_exit(entry)
|
|
98
|
+
when "llm_retry_attempt"
|
|
99
|
+
handle_llm_retry_attempt(entry)
|
|
100
|
+
when "llm_retry_exhausted"
|
|
101
|
+
handle_llm_retry_exhausted(entry)
|
|
102
|
+
when "response_parse_error"
|
|
103
|
+
handle_response_parse_error(entry)
|
|
98
104
|
end
|
|
99
105
|
end
|
|
100
106
|
|
|
101
107
|
# Called when swarm execution completes successfully
|
|
102
108
|
def on_success(result:)
|
|
109
|
+
# Defensive: ensure all spinners are stopped before showing result
|
|
110
|
+
@spinner_manager.stop_all
|
|
111
|
+
|
|
103
112
|
if @mode == :non_interactive
|
|
104
113
|
# Full result display with summary
|
|
105
114
|
@output.puts
|
|
@@ -115,6 +124,9 @@ module SwarmCLI
|
|
|
115
124
|
|
|
116
125
|
# Called when swarm execution fails
|
|
117
126
|
def on_error(error:, duration: nil)
|
|
127
|
+
# Defensive: ensure all spinners are stopped before showing error
|
|
128
|
+
@spinner_manager.stop_all
|
|
129
|
+
|
|
118
130
|
@output.puts
|
|
119
131
|
@output.puts @divider.full
|
|
120
132
|
print_error(error)
|
|
@@ -575,6 +587,97 @@ module SwarmCLI
|
|
|
575
587
|
@output.puts
|
|
576
588
|
end
|
|
577
589
|
|
|
590
|
+
def handle_llm_retry_attempt(entry)
|
|
591
|
+
agent = entry[:agent]
|
|
592
|
+
attempt = entry[:attempt]
|
|
593
|
+
max_retries = entry[:max_retries]
|
|
594
|
+
error_class = entry[:error_class]
|
|
595
|
+
error_message = entry[:error_message]
|
|
596
|
+
retry_delay = entry[:retry_delay]
|
|
597
|
+
|
|
598
|
+
# Stop agent thinking spinner (if active)
|
|
599
|
+
unless @quiet
|
|
600
|
+
spinner_key = "agent_#{agent}".to_sym
|
|
601
|
+
@spinner_manager.stop(spinner_key) if @spinner_manager.active?(spinner_key)
|
|
602
|
+
end
|
|
603
|
+
|
|
604
|
+
lines = [
|
|
605
|
+
@pastel.yellow("LLM API request failed (attempt #{attempt}/#{max_retries})"),
|
|
606
|
+
@pastel.dim("Error: #{error_class}: #{error_message}"),
|
|
607
|
+
@pastel.dim("Retrying in #{retry_delay}s..."),
|
|
608
|
+
]
|
|
609
|
+
|
|
610
|
+
@output.puts @panel.render(
|
|
611
|
+
type: :warning,
|
|
612
|
+
title: "RETRY #{@agent_badge.render(agent)}",
|
|
613
|
+
lines: lines,
|
|
614
|
+
indent: @depth_tracker.get(agent),
|
|
615
|
+
)
|
|
616
|
+
|
|
617
|
+
# Restart spinner for next attempt
|
|
618
|
+
unless @quiet
|
|
619
|
+
spinner_key = "agent_#{agent}".to_sym
|
|
620
|
+
@spinner_manager.start(spinner_key, "#{agent} is retrying...")
|
|
621
|
+
end
|
|
622
|
+
end
|
|
623
|
+
|
|
624
|
+
def handle_llm_retry_exhausted(entry)
|
|
625
|
+
agent = entry[:agent]
|
|
626
|
+
attempts = entry[:attempts]
|
|
627
|
+
error_class = entry[:error_class]
|
|
628
|
+
error_message = entry[:error_message]
|
|
629
|
+
|
|
630
|
+
# Stop agent thinking spinner (if active)
|
|
631
|
+
unless @quiet
|
|
632
|
+
spinner_key = "agent_#{agent}".to_sym
|
|
633
|
+
@spinner_manager.stop(spinner_key) if @spinner_manager.active?(spinner_key)
|
|
634
|
+
end
|
|
635
|
+
|
|
636
|
+
lines = [
|
|
637
|
+
@pastel.red("LLM API request failed after #{attempts} attempts"),
|
|
638
|
+
@pastel.dim("Error: #{error_class}: #{error_message}"),
|
|
639
|
+
@pastel.dim("No more retries available"),
|
|
640
|
+
]
|
|
641
|
+
|
|
642
|
+
@output.puts @panel.render(
|
|
643
|
+
type: :error,
|
|
644
|
+
title: "RETRY EXHAUSTED #{@agent_badge.render(agent)}",
|
|
645
|
+
lines: lines,
|
|
646
|
+
indent: @depth_tracker.get(agent),
|
|
647
|
+
)
|
|
648
|
+
end
|
|
649
|
+
|
|
650
|
+
def handle_response_parse_error(entry)
|
|
651
|
+
agent = entry[:agent]
|
|
652
|
+
error_class = entry[:error_class]
|
|
653
|
+
error_message = entry[:error_message]
|
|
654
|
+
|
|
655
|
+
# Stop agent thinking spinner (if active)
|
|
656
|
+
unless @quiet
|
|
657
|
+
spinner_key = "agent_#{agent}".to_sym
|
|
658
|
+
@spinner_manager.stop(spinner_key) if @spinner_manager.active?(spinner_key)
|
|
659
|
+
end
|
|
660
|
+
|
|
661
|
+
lines = [
|
|
662
|
+
@pastel.red("Failed to parse LLM API response"),
|
|
663
|
+
@pastel.dim("Error: #{error_class}: #{error_message}"),
|
|
664
|
+
]
|
|
665
|
+
|
|
666
|
+
# Add response body preview if available (truncated)
|
|
667
|
+
if entry[:response_body]
|
|
668
|
+
body_preview = entry[:response_body].to_s[0..200]
|
|
669
|
+
body_preview += "..." if entry[:response_body].to_s.length > 200
|
|
670
|
+
lines << @pastel.dim("Response: #{body_preview}")
|
|
671
|
+
end
|
|
672
|
+
|
|
673
|
+
@output.puts @panel.render(
|
|
674
|
+
type: :error,
|
|
675
|
+
title: "PARSE ERROR #{@agent_badge.render(agent)}",
|
|
676
|
+
lines: lines,
|
|
677
|
+
indent: @depth_tracker.get(agent),
|
|
678
|
+
)
|
|
679
|
+
end
|
|
680
|
+
|
|
578
681
|
def display_todo_list(agent, timestamp)
|
|
579
682
|
todos = SwarmSDK::Tools::Stores::TodoManager.get_todos(agent.to_sym)
|
|
580
683
|
indent = @depth_tracker.indent(agent)
|
|
@@ -81,6 +81,9 @@ module SwarmCLI
|
|
|
81
81
|
display_session_summary
|
|
82
82
|
exit(130)
|
|
83
83
|
ensure
|
|
84
|
+
# Defensive: ensure all spinners are stopped on exit
|
|
85
|
+
@formatter&.spinner_manager&.stop_all
|
|
86
|
+
|
|
84
87
|
# Save history on exit
|
|
85
88
|
save_persistent_history
|
|
86
89
|
end
|
|
@@ -432,11 +435,12 @@ module SwarmCLI
|
|
|
432
435
|
end
|
|
433
436
|
end
|
|
434
437
|
|
|
438
|
+
# CRITICAL: Stop all spinners after execution completes
|
|
439
|
+
# This ensures spinner doesn't interfere with error/success display or REPL prompt
|
|
440
|
+
@formatter.spinner_manager.stop_all
|
|
441
|
+
|
|
435
442
|
# Handle cancellation (result is nil when cancelled)
|
|
436
443
|
if result.nil?
|
|
437
|
-
# Stop all active spinners
|
|
438
|
-
@formatter.spinner_manager.stop_all
|
|
439
|
-
|
|
440
444
|
puts ""
|
|
441
445
|
puts @colors[:warning].call("✗ Request cancelled by user")
|
|
442
446
|
puts ""
|
|
@@ -459,6 +463,8 @@ module SwarmCLI
|
|
|
459
463
|
# Add response to history
|
|
460
464
|
@conversation_history << { role: "agent", content: result.content }
|
|
461
465
|
rescue StandardError => e
|
|
466
|
+
# Defensive: ensure spinners are stopped on exception
|
|
467
|
+
@formatter.spinner_manager.stop_all
|
|
462
468
|
@formatter.on_error(error: e)
|
|
463
469
|
end
|
|
464
470
|
|
data/lib/swarm_cli/version.rb
CHANGED
|
@@ -7,11 +7,11 @@ module SwarmMemory
|
|
|
7
7
|
# Subclasses must implement all public methods to provide
|
|
8
8
|
# different storage backends (filesystem, Redis, SQLite, etc.)
|
|
9
9
|
class Base
|
|
10
|
-
# Maximum size per entry (
|
|
11
|
-
MAX_ENTRY_SIZE =
|
|
10
|
+
# Maximum size per entry (3MB)
|
|
11
|
+
MAX_ENTRY_SIZE = 3_000_000
|
|
12
12
|
|
|
13
|
-
# Maximum total storage size (
|
|
14
|
-
MAX_TOTAL_SIZE =
|
|
13
|
+
# Maximum total storage size (100GB)
|
|
14
|
+
MAX_TOTAL_SIZE = 100_000_000_000
|
|
15
15
|
|
|
16
16
|
# Write content to storage
|
|
17
17
|
#
|