musubi-sdd 5.1.0 → 5.6.1
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.
- package/README.ja.md +106 -48
- package/README.md +110 -32
- package/bin/musubi-analyze.js +74 -67
- package/bin/musubi-browser.js +27 -26
- package/bin/musubi-change.js +48 -47
- package/bin/musubi-checkpoint.js +10 -7
- package/bin/musubi-convert.js +25 -25
- package/bin/musubi-costs.js +27 -10
- package/bin/musubi-gui.js +52 -46
- package/bin/musubi-init.js +1952 -10
- package/bin/musubi-orchestrate.js +327 -239
- package/bin/musubi-remember.js +69 -56
- package/bin/musubi-resolve.js +53 -45
- package/bin/musubi-trace.js +51 -22
- package/bin/musubi-validate.js +39 -30
- package/bin/musubi-workflow.js +33 -34
- package/bin/musubi.js +39 -2
- package/package.json +1 -1
- package/src/agents/agent-loop.js +94 -95
- package/src/agents/agentic/code-generator.js +119 -109
- package/src/agents/agentic/code-reviewer.js +105 -108
- package/src/agents/agentic/index.js +4 -4
- package/src/agents/browser/action-executor.js +13 -13
- package/src/agents/browser/ai-comparator.js +11 -10
- package/src/agents/browser/context-manager.js +6 -6
- package/src/agents/browser/index.js +5 -5
- package/src/agents/browser/nl-parser.js +31 -46
- package/src/agents/browser/screenshot.js +2 -2
- package/src/agents/browser/test-generator.js +6 -4
- package/src/agents/function-tool.js +71 -65
- package/src/agents/index.js +7 -7
- package/src/agents/schema-generator.js +98 -94
- package/src/analyzers/ast-extractor.js +158 -146
- package/src/analyzers/codegraph-auto-update.js +858 -0
- package/src/analyzers/complexity-analyzer.js +536 -0
- package/src/analyzers/context-optimizer.js +241 -126
- package/src/analyzers/impact-analyzer.js +1 -1
- package/src/analyzers/large-project-analyzer.js +766 -0
- package/src/analyzers/repository-map.js +77 -81
- package/src/analyzers/security-analyzer.js +19 -11
- package/src/analyzers/stuck-detector.js +19 -17
- package/src/converters/index.js +78 -57
- package/src/converters/ir/types.js +12 -12
- package/src/converters/parsers/musubi-parser.js +134 -126
- package/src/converters/parsers/openapi-parser.js +70 -53
- package/src/converters/parsers/speckit-parser.js +239 -175
- package/src/converters/writers/musubi-writer.js +123 -118
- package/src/converters/writers/speckit-writer.js +124 -113
- package/src/generators/rust-migration-generator.js +512 -0
- package/src/gui/public/index.html +1365 -1211
- package/src/gui/server.js +41 -40
- package/src/gui/services/file-watcher.js +23 -8
- package/src/gui/services/project-scanner.js +26 -20
- package/src/gui/services/replanning-service.js +27 -23
- package/src/gui/services/traceability-service.js +8 -8
- package/src/gui/services/workflow-service.js +14 -7
- package/src/index.js +151 -0
- package/src/integrations/cicd.js +90 -104
- package/src/integrations/codegraph-mcp.js +643 -0
- package/src/integrations/documentation.js +142 -103
- package/src/integrations/examples.js +95 -80
- package/src/integrations/github-client.js +17 -17
- package/src/integrations/index.js +5 -5
- package/src/integrations/mcp/index.js +21 -21
- package/src/integrations/mcp/mcp-context-provider.js +76 -78
- package/src/integrations/mcp/mcp-discovery.js +74 -72
- package/src/integrations/mcp/mcp-tool-registry.js +99 -94
- package/src/integrations/mcp-connector.js +70 -66
- package/src/integrations/platforms.js +50 -49
- package/src/integrations/tool-discovery.js +37 -31
- package/src/llm-providers/anthropic-provider.js +11 -11
- package/src/llm-providers/base-provider.js +16 -18
- package/src/llm-providers/copilot-provider.js +22 -19
- package/src/llm-providers/index.js +26 -25
- package/src/llm-providers/ollama-provider.js +11 -11
- package/src/llm-providers/openai-provider.js +12 -12
- package/src/managers/agent-memory.js +36 -24
- package/src/managers/checkpoint-manager.js +4 -8
- package/src/managers/delta-spec.js +19 -19
- package/src/managers/index.js +13 -4
- package/src/managers/memory-condenser.js +35 -45
- package/src/managers/repo-skill-manager.js +57 -31
- package/src/managers/skill-loader.js +25 -22
- package/src/managers/skill-tools.js +36 -72
- package/src/managers/workflow.js +30 -22
- package/src/monitoring/cost-tracker.js +48 -46
- package/src/monitoring/incident-manager.js +116 -106
- package/src/monitoring/index.js +144 -134
- package/src/monitoring/observability.js +75 -62
- package/src/monitoring/quality-dashboard.js +45 -41
- package/src/monitoring/release-manager.js +63 -53
- package/src/orchestration/agent-skill-binding.js +39 -47
- package/src/orchestration/error-handler.js +65 -107
- package/src/orchestration/guardrails/base-guardrail.js +26 -24
- package/src/orchestration/guardrails/guardrail-rules.js +50 -64
- package/src/orchestration/guardrails/index.js +5 -5
- package/src/orchestration/guardrails/input-guardrail.js +58 -45
- package/src/orchestration/guardrails/output-guardrail.js +104 -81
- package/src/orchestration/guardrails/safety-check.js +79 -79
- package/src/orchestration/index.js +38 -55
- package/src/orchestration/mcp-tool-adapters.js +96 -99
- package/src/orchestration/orchestration-engine.js +21 -21
- package/src/orchestration/pattern-registry.js +60 -45
- package/src/orchestration/patterns/auto.js +34 -47
- package/src/orchestration/patterns/group-chat.js +59 -65
- package/src/orchestration/patterns/handoff.js +67 -65
- package/src/orchestration/patterns/human-in-loop.js +51 -72
- package/src/orchestration/patterns/nested.js +25 -40
- package/src/orchestration/patterns/sequential.js +35 -34
- package/src/orchestration/patterns/swarm.js +63 -56
- package/src/orchestration/patterns/triage.js +150 -109
- package/src/orchestration/reasoning/index.js +9 -9
- package/src/orchestration/reasoning/planning-engine.js +143 -140
- package/src/orchestration/reasoning/reasoning-engine.js +206 -144
- package/src/orchestration/reasoning/self-correction.js +121 -128
- package/src/orchestration/replanning/adaptive-goal-modifier.js +107 -112
- package/src/orchestration/replanning/alternative-generator.js +37 -42
- package/src/orchestration/replanning/config.js +63 -59
- package/src/orchestration/replanning/goal-progress-tracker.js +98 -100
- package/src/orchestration/replanning/index.js +24 -20
- package/src/orchestration/replanning/plan-evaluator.js +49 -50
- package/src/orchestration/replanning/plan-monitor.js +32 -28
- package/src/orchestration/replanning/proactive-path-optimizer.js +175 -178
- package/src/orchestration/replanning/replan-history.js +33 -26
- package/src/orchestration/replanning/replanning-engine.js +106 -108
- package/src/orchestration/skill-executor.js +107 -109
- package/src/orchestration/skill-registry.js +85 -89
- package/src/orchestration/workflow-examples.js +228 -231
- package/src/orchestration/workflow-executor.js +65 -68
- package/src/orchestration/workflow-orchestrator.js +72 -73
- package/src/phase4-integration.js +47 -40
- package/src/phase5-integration.js +89 -30
- package/src/reporters/coverage-report.js +82 -30
- package/src/reporters/hierarchical-reporter.js +498 -0
- package/src/reporters/traceability-matrix-report.js +29 -20
- package/src/resolvers/issue-resolver.js +43 -31
- package/src/steering/advanced-validation.js +133 -124
- package/src/steering/auto-updater.js +60 -73
- package/src/steering/index.js +6 -6
- package/src/steering/quality-metrics.js +41 -35
- package/src/steering/steering-auto-update.js +83 -86
- package/src/steering/steering-validator.js +98 -106
- package/src/steering/template-constraints.js +53 -54
- package/src/templates/agents/claude-code/CLAUDE.md +32 -32
- package/src/templates/agents/claude-code/skills/agent-assistant/SKILL.md +13 -5
- package/src/templates/agents/claude-code/skills/ai-ml-engineer/mlops-guide.md +23 -23
- package/src/templates/agents/claude-code/skills/ai-ml-engineer/model-card-template.md +60 -41
- package/src/templates/agents/claude-code/skills/api-designer/api-patterns.md +27 -19
- package/src/templates/agents/claude-code/skills/api-designer/openapi-template.md +11 -7
- package/src/templates/agents/claude-code/skills/bug-hunter/SKILL.md +4 -3
- package/src/templates/agents/claude-code/skills/bug-hunter/root-cause-analysis.md +37 -15
- package/src/templates/agents/claude-code/skills/change-impact-analyzer/dependency-graph-patterns.md +36 -42
- package/src/templates/agents/claude-code/skills/change-impact-analyzer/impact-analysis-template.md +69 -60
- package/src/templates/agents/claude-code/skills/cloud-architect/aws-patterns.md +31 -38
- package/src/templates/agents/claude-code/skills/cloud-architect/azure-patterns.md +28 -23
- package/src/templates/agents/claude-code/skills/code-reviewer/SKILL.md +61 -0
- package/src/templates/agents/claude-code/skills/code-reviewer/best-practices.md +27 -0
- package/src/templates/agents/claude-code/skills/code-reviewer/review-checklist.md +29 -10
- package/src/templates/agents/claude-code/skills/code-reviewer/review-standards.md +29 -24
- package/src/templates/agents/claude-code/skills/constitution-enforcer/SKILL.md +8 -6
- package/src/templates/agents/claude-code/skills/constitution-enforcer/constitutional-articles.md +62 -26
- package/src/templates/agents/claude-code/skills/constitution-enforcer/phase-minus-one-gates.md +35 -16
- package/src/templates/agents/claude-code/skills/database-administrator/backup-recovery.md +27 -17
- package/src/templates/agents/claude-code/skills/database-administrator/tuning-guide.md +25 -20
- package/src/templates/agents/claude-code/skills/database-schema-designer/schema-patterns.md +39 -22
- package/src/templates/agents/claude-code/skills/devops-engineer/ci-cd-templates.md +25 -22
- package/src/templates/agents/claude-code/skills/issue-resolver/SKILL.md +24 -21
- package/src/templates/agents/claude-code/skills/orchestrator/SKILL.md +148 -63
- package/src/templates/agents/claude-code/skills/orchestrator/patterns.md +35 -16
- package/src/templates/agents/claude-code/skills/orchestrator/selection-matrix.md +69 -64
- package/src/templates/agents/claude-code/skills/performance-engineer/optimization-playbook.md +47 -47
- package/src/templates/agents/claude-code/skills/performance-optimizer/SKILL.md +69 -0
- package/src/templates/agents/claude-code/skills/performance-optimizer/benchmark-template.md +63 -45
- package/src/templates/agents/claude-code/skills/performance-optimizer/optimization-patterns.md +33 -35
- package/src/templates/agents/claude-code/skills/project-manager/SKILL.md +7 -6
- package/src/templates/agents/claude-code/skills/project-manager/agile-ceremonies.md +47 -28
- package/src/templates/agents/claude-code/skills/project-manager/project-templates.md +94 -78
- package/src/templates/agents/claude-code/skills/quality-assurance/SKILL.md +20 -17
- package/src/templates/agents/claude-code/skills/quality-assurance/qa-plan-template.md +63 -49
- package/src/templates/agents/claude-code/skills/release-coordinator/SKILL.md +5 -5
- package/src/templates/agents/claude-code/skills/release-coordinator/feature-flag-guide.md +30 -26
- package/src/templates/agents/claude-code/skills/release-coordinator/release-plan-template.md +67 -35
- package/src/templates/agents/claude-code/skills/requirements-analyst/ears-format.md +54 -42
- package/src/templates/agents/claude-code/skills/requirements-analyst/validation-rules.md +36 -33
- package/src/templates/agents/claude-code/skills/security-auditor/SKILL.md +77 -19
- package/src/templates/agents/claude-code/skills/security-auditor/audit-checklists.md +24 -24
- package/src/templates/agents/claude-code/skills/security-auditor/owasp-top-10.md +61 -20
- package/src/templates/agents/claude-code/skills/security-auditor/vulnerability-patterns.md +43 -11
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/SKILL.md +1 -0
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/incident-response-template.md +55 -25
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/observability-patterns.md +78 -68
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/slo-sli-guide.md +73 -53
- package/src/templates/agents/claude-code/skills/software-developer/solid-principles.md +83 -37
- package/src/templates/agents/claude-code/skills/software-developer/test-first-workflow.md +38 -31
- package/src/templates/agents/claude-code/skills/steering/SKILL.md +1 -0
- package/src/templates/agents/claude-code/skills/steering/auto-update-rules.md +31 -0
- package/src/templates/agents/claude-code/skills/system-architect/adr-template.md +25 -7
- package/src/templates/agents/claude-code/skills/system-architect/c4-model-guide.md +74 -61
- package/src/templates/agents/claude-code/skills/technical-writer/doc-templates/documentation-templates.md +70 -52
- package/src/templates/agents/claude-code/skills/test-engineer/SKILL.md +2 -0
- package/src/templates/agents/claude-code/skills/test-engineer/ears-test-mapping.md +75 -71
- package/src/templates/agents/claude-code/skills/test-engineer/test-types.md +85 -63
- package/src/templates/agents/claude-code/skills/traceability-auditor/coverage-matrix-template.md +39 -36
- package/src/templates/agents/claude-code/skills/traceability-auditor/gap-detection-rules.md +22 -17
- package/src/templates/agents/claude-code/skills/ui-ux-designer/SKILL.md +1 -0
- package/src/templates/agents/claude-code/skills/ui-ux-designer/accessibility-guidelines.md +49 -75
- package/src/templates/agents/claude-code/skills/ui-ux-designer/design-system-components.md +71 -59
- package/src/templates/agents/codex/AGENTS.md +74 -42
- package/src/templates/agents/cursor/AGENTS.md +74 -42
- package/src/templates/agents/gemini-cli/GEMINI.md +74 -42
- package/src/templates/agents/github-copilot/AGENTS.md +83 -51
- package/src/templates/agents/qwen-code/QWEN.md +74 -42
- package/src/templates/agents/windsurf/AGENTS.md +74 -42
- package/src/templates/architectures/README.md +41 -0
- package/src/templates/architectures/clean-architecture/README.md +113 -0
- package/src/templates/architectures/event-driven/README.md +162 -0
- package/src/templates/architectures/hexagonal/README.md +130 -0
- package/src/templates/index.js +6 -1
- package/src/templates/locale-manager.js +16 -16
- package/src/templates/shared/delta-spec-template.md +20 -13
- package/src/templates/shared/github-actions/musubi-issue-resolver.yml +5 -5
- package/src/templates/shared/github-actions/musubi-security-check.yml +3 -3
- package/src/templates/shared/github-actions/musubi-validate.yml +4 -4
- package/src/templates/shared/steering/structure.md +95 -0
- package/src/templates/skills/browser-agent.md +21 -16
- package/src/templates/skills/web-gui.md +8 -0
- package/src/templates/template-constraints.js +50 -53
- package/src/validators/advanced-validation.js +30 -36
- package/src/validators/constitutional-validator.js +77 -73
- package/src/validators/critic-system.js +49 -59
- package/src/validators/delta-format.js +59 -55
- package/src/validators/traceability-validator.js +7 -11
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* GroupChatPattern - Multi-skill collaborative discussion pattern
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Enables multiple skills to collaborate on a task through
|
|
5
5
|
* iterative discussion and consensus building.
|
|
6
6
|
*/
|
|
@@ -12,18 +12,18 @@ const { PatternType, ExecutionContext, ExecutionStatus } = require('../orchestra
|
|
|
12
12
|
* Discussion mode
|
|
13
13
|
*/
|
|
14
14
|
const DiscussionMode = {
|
|
15
|
-
ROUND_ROBIN: 'round-robin',
|
|
16
|
-
OPEN_FLOOR: 'open-floor',
|
|
17
|
-
MODERATED: 'moderated'
|
|
15
|
+
ROUND_ROBIN: 'round-robin', // Each skill speaks in turn
|
|
16
|
+
OPEN_FLOOR: 'open-floor', // Skills speak based on relevance
|
|
17
|
+
MODERATED: 'moderated', // Moderator skill controls discussion
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Consensus type
|
|
22
22
|
*/
|
|
23
23
|
const ConsensusType = {
|
|
24
|
-
UNANIMOUS: 'unanimous',
|
|
25
|
-
MAJORITY: 'majority',
|
|
26
|
-
FIRST_AGREEMENT: 'first'
|
|
24
|
+
UNANIMOUS: 'unanimous', // All must agree
|
|
25
|
+
MAJORITY: 'majority', // 50%+ must agree
|
|
26
|
+
FIRST_AGREEMENT: 'first', // First agreement wins
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
/**
|
|
@@ -37,15 +37,10 @@ class GroupChatPattern extends BasePattern {
|
|
|
37
37
|
description: 'Enable multi-skill collaborative discussion and consensus',
|
|
38
38
|
version: '1.0.0',
|
|
39
39
|
tags: ['collaboration', 'discussion', 'consensus', 'multi-agent'],
|
|
40
|
-
useCases: [
|
|
41
|
-
'Design reviews',
|
|
42
|
-
'Code reviews',
|
|
43
|
-
'Decision making',
|
|
44
|
-
'Brainstorming'
|
|
45
|
-
],
|
|
40
|
+
useCases: ['Design reviews', 'Code reviews', 'Decision making', 'Brainstorming'],
|
|
46
41
|
complexity: 'high',
|
|
47
42
|
supportsParallel: false,
|
|
48
|
-
requiresHuman: false
|
|
43
|
+
requiresHuman: false,
|
|
49
44
|
});
|
|
50
45
|
|
|
51
46
|
this.options = {
|
|
@@ -54,7 +49,7 @@ class GroupChatPattern extends BasePattern {
|
|
|
54
49
|
maxRounds: options.maxRounds || 5,
|
|
55
50
|
moderator: options.moderator || null,
|
|
56
51
|
convergenceThreshold: options.convergenceThreshold || 0.8,
|
|
57
|
-
...options
|
|
52
|
+
...options,
|
|
58
53
|
};
|
|
59
54
|
}
|
|
60
55
|
|
|
@@ -99,7 +94,7 @@ class GroupChatPattern extends BasePattern {
|
|
|
99
94
|
|
|
100
95
|
return {
|
|
101
96
|
valid: errors.length === 0,
|
|
102
|
-
errors
|
|
97
|
+
errors,
|
|
103
98
|
};
|
|
104
99
|
}
|
|
105
100
|
|
|
@@ -125,7 +120,7 @@ class GroupChatPattern extends BasePattern {
|
|
|
125
120
|
context,
|
|
126
121
|
participants,
|
|
127
122
|
topic,
|
|
128
|
-
mode: this.options.mode
|
|
123
|
+
mode: this.options.mode,
|
|
129
124
|
});
|
|
130
125
|
|
|
131
126
|
try {
|
|
@@ -135,7 +130,7 @@ class GroupChatPattern extends BasePattern {
|
|
|
135
130
|
engine.emit('groupChatRoundStarted', {
|
|
136
131
|
context,
|
|
137
132
|
round,
|
|
138
|
-
maxRounds: this.options.maxRounds
|
|
133
|
+
maxRounds: this.options.maxRounds,
|
|
139
134
|
});
|
|
140
135
|
|
|
141
136
|
const roundResponses = await this._executeRound(
|
|
@@ -150,13 +145,13 @@ class GroupChatPattern extends BasePattern {
|
|
|
150
145
|
|
|
151
146
|
transcript.push({
|
|
152
147
|
round,
|
|
153
|
-
responses: roundResponses
|
|
148
|
+
responses: roundResponses,
|
|
154
149
|
});
|
|
155
150
|
|
|
156
151
|
// Check for consensus
|
|
157
152
|
const consensusResult = this._checkConsensus(roundResponses);
|
|
158
153
|
consensusReached = consensusResult.reached;
|
|
159
|
-
|
|
154
|
+
|
|
160
155
|
if (consensusReached) {
|
|
161
156
|
finalDecision = consensusResult.decision;
|
|
162
157
|
}
|
|
@@ -165,7 +160,7 @@ class GroupChatPattern extends BasePattern {
|
|
|
165
160
|
context,
|
|
166
161
|
round,
|
|
167
162
|
responses: roundResponses,
|
|
168
|
-
consensusReached
|
|
163
|
+
consensusReached,
|
|
169
164
|
});
|
|
170
165
|
}
|
|
171
166
|
|
|
@@ -176,7 +171,7 @@ class GroupChatPattern extends BasePattern {
|
|
|
176
171
|
transcript,
|
|
177
172
|
consensusReached,
|
|
178
173
|
finalDecision,
|
|
179
|
-
summary
|
|
174
|
+
summary,
|
|
180
175
|
});
|
|
181
176
|
|
|
182
177
|
return {
|
|
@@ -184,15 +179,14 @@ class GroupChatPattern extends BasePattern {
|
|
|
184
179
|
rounds: round,
|
|
185
180
|
consensusReached,
|
|
186
181
|
finalDecision,
|
|
187
|
-
summary
|
|
182
|
+
summary,
|
|
188
183
|
};
|
|
189
|
-
|
|
190
184
|
} catch (error) {
|
|
191
185
|
engine.emit('groupChatFailed', {
|
|
192
186
|
context,
|
|
193
187
|
transcript,
|
|
194
188
|
round,
|
|
195
|
-
error
|
|
189
|
+
error,
|
|
196
190
|
});
|
|
197
191
|
throw error;
|
|
198
192
|
}
|
|
@@ -202,13 +196,21 @@ class GroupChatPattern extends BasePattern {
|
|
|
202
196
|
* Execute a single round of discussion
|
|
203
197
|
* @private
|
|
204
198
|
*/
|
|
205
|
-
async _executeRound(
|
|
199
|
+
async _executeRound(
|
|
200
|
+
participants,
|
|
201
|
+
topic,
|
|
202
|
+
transcript,
|
|
203
|
+
initialContext,
|
|
204
|
+
parentContext,
|
|
205
|
+
engine,
|
|
206
|
+
round
|
|
207
|
+
) {
|
|
206
208
|
const responses = [];
|
|
207
209
|
const discussionContext = {
|
|
208
210
|
topic,
|
|
209
211
|
round,
|
|
210
212
|
previousRounds: transcript,
|
|
211
|
-
...initialContext
|
|
213
|
+
...initialContext,
|
|
212
214
|
};
|
|
213
215
|
|
|
214
216
|
for (const participant of participants) {
|
|
@@ -218,48 +220,43 @@ class GroupChatPattern extends BasePattern {
|
|
|
218
220
|
input: {
|
|
219
221
|
...discussionContext,
|
|
220
222
|
previousResponses: responses,
|
|
221
|
-
role: 'participant'
|
|
223
|
+
role: 'participant',
|
|
222
224
|
},
|
|
223
225
|
parentId: parentContext.id,
|
|
224
226
|
metadata: {
|
|
225
227
|
pattern: PatternType.GROUP_CHAT,
|
|
226
228
|
round,
|
|
227
|
-
participant
|
|
228
|
-
}
|
|
229
|
+
participant,
|
|
230
|
+
},
|
|
229
231
|
});
|
|
230
232
|
|
|
231
233
|
parentContext.children.push(stepContext);
|
|
232
234
|
|
|
233
235
|
try {
|
|
234
236
|
stepContext.start();
|
|
235
|
-
|
|
236
|
-
const response = await engine.executeSkill(
|
|
237
|
-
participant,
|
|
238
|
-
stepContext.input,
|
|
239
|
-
parentContext
|
|
240
|
-
);
|
|
237
|
+
|
|
238
|
+
const response = await engine.executeSkill(participant, stepContext.input, parentContext);
|
|
241
239
|
|
|
242
240
|
stepContext.complete(response);
|
|
243
241
|
|
|
244
242
|
responses.push({
|
|
245
243
|
participant,
|
|
246
244
|
response,
|
|
247
|
-
status: ExecutionStatus.COMPLETED
|
|
245
|
+
status: ExecutionStatus.COMPLETED,
|
|
248
246
|
});
|
|
249
247
|
|
|
250
248
|
engine.emit('groupChatResponse', {
|
|
251
249
|
participant,
|
|
252
250
|
round,
|
|
253
|
-
response
|
|
251
|
+
response,
|
|
254
252
|
});
|
|
255
|
-
|
|
256
253
|
} catch (error) {
|
|
257
254
|
stepContext.fail(error);
|
|
258
|
-
|
|
255
|
+
|
|
259
256
|
responses.push({
|
|
260
257
|
participant,
|
|
261
258
|
error: error.message,
|
|
262
|
-
status: ExecutionStatus.FAILED
|
|
259
|
+
status: ExecutionStatus.FAILED,
|
|
263
260
|
});
|
|
264
261
|
}
|
|
265
262
|
}
|
|
@@ -272,21 +269,21 @@ class GroupChatPattern extends BasePattern {
|
|
|
272
269
|
* @private
|
|
273
270
|
*/
|
|
274
271
|
_checkConsensus(responses) {
|
|
275
|
-
const validResponses = responses.filter(r =>
|
|
276
|
-
r.status === ExecutionStatus.COMPLETED
|
|
277
|
-
);
|
|
272
|
+
const validResponses = responses.filter(r => r.status === ExecutionStatus.COMPLETED);
|
|
278
273
|
|
|
279
274
|
if (validResponses.length === 0) {
|
|
280
275
|
return { reached: false, decision: null };
|
|
281
276
|
}
|
|
282
277
|
|
|
283
278
|
// Extract decisions from responses
|
|
284
|
-
const decisions = validResponses
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
279
|
+
const decisions = validResponses
|
|
280
|
+
.map(r => {
|
|
281
|
+
if (r.response && typeof r.response === 'object') {
|
|
282
|
+
return r.response.decision || r.response.recommendation || r.response.answer;
|
|
283
|
+
}
|
|
284
|
+
return r.response;
|
|
285
|
+
})
|
|
286
|
+
.filter(d => d !== undefined && d !== null);
|
|
290
287
|
|
|
291
288
|
if (decisions.length === 0) {
|
|
292
289
|
return { reached: false, decision: null };
|
|
@@ -295,9 +292,7 @@ class GroupChatPattern extends BasePattern {
|
|
|
295
292
|
// Count votes for each decision
|
|
296
293
|
const votes = {};
|
|
297
294
|
for (const decision of decisions) {
|
|
298
|
-
const key = typeof decision === 'object'
|
|
299
|
-
? JSON.stringify(decision)
|
|
300
|
-
: String(decision);
|
|
295
|
+
const key = typeof decision === 'object' ? JSON.stringify(decision) : String(decision);
|
|
301
296
|
votes[key] = (votes[key] || 0) + 1;
|
|
302
297
|
}
|
|
303
298
|
|
|
@@ -317,30 +312,30 @@ class GroupChatPattern extends BasePattern {
|
|
|
317
312
|
|
|
318
313
|
// Check consensus based on type
|
|
319
314
|
const total = validResponses.length;
|
|
320
|
-
|
|
315
|
+
|
|
321
316
|
switch (this.options.consensusType) {
|
|
322
317
|
case ConsensusType.UNANIMOUS:
|
|
323
318
|
return {
|
|
324
319
|
reached: maxVotes === total,
|
|
325
|
-
decision: maxVotes === total ? winningDecision : null
|
|
320
|
+
decision: maxVotes === total ? winningDecision : null,
|
|
326
321
|
};
|
|
327
|
-
|
|
322
|
+
|
|
328
323
|
case ConsensusType.MAJORITY:
|
|
329
324
|
return {
|
|
330
325
|
reached: maxVotes > total / 2,
|
|
331
|
-
decision: maxVotes > total / 2 ? winningDecision : null
|
|
326
|
+
decision: maxVotes > total / 2 ? winningDecision : null,
|
|
332
327
|
};
|
|
333
|
-
|
|
328
|
+
|
|
334
329
|
case ConsensusType.FIRST_AGREEMENT:
|
|
335
330
|
return {
|
|
336
331
|
reached: maxVotes >= 2,
|
|
337
|
-
decision: maxVotes >= 2 ? winningDecision : null
|
|
332
|
+
decision: maxVotes >= 2 ? winningDecision : null,
|
|
338
333
|
};
|
|
339
|
-
|
|
334
|
+
|
|
340
335
|
default:
|
|
341
336
|
return {
|
|
342
337
|
reached: maxVotes >= total * this.options.convergenceThreshold,
|
|
343
|
-
decision: winningDecision
|
|
338
|
+
decision: winningDecision,
|
|
344
339
|
};
|
|
345
340
|
}
|
|
346
341
|
}
|
|
@@ -371,9 +366,8 @@ class GroupChatPattern extends BasePattern {
|
|
|
371
366
|
successfulResponses,
|
|
372
367
|
failedResponses,
|
|
373
368
|
consensusReached,
|
|
374
|
-
successRate:
|
|
375
|
-
? (successfulResponses / totalResponses * 100).toFixed(1) + '%'
|
|
376
|
-
: '0%'
|
|
369
|
+
successRate:
|
|
370
|
+
totalResponses > 0 ? ((successfulResponses / totalResponses) * 100).toFixed(1) + '%' : '0%',
|
|
377
371
|
};
|
|
378
372
|
}
|
|
379
373
|
}
|
|
@@ -391,5 +385,5 @@ module.exports = {
|
|
|
391
385
|
GroupChatPattern,
|
|
392
386
|
DiscussionMode,
|
|
393
387
|
ConsensusType,
|
|
394
|
-
createGroupChatPattern
|
|
388
|
+
createGroupChatPattern,
|
|
395
389
|
};
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* HandoffPattern - Agent delegation pattern
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Enables conversation control transfer between agents.
|
|
5
5
|
* Implements OpenAI Agents SDK-style handoff mechanism for MUSUBI.
|
|
6
|
-
*
|
|
6
|
+
*
|
|
7
7
|
* @module orchestration/patterns/handoff
|
|
8
8
|
* @version 1.0.0
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
const { BasePattern } = require('../pattern-registry');
|
|
12
|
-
const { PatternType, ExecutionContext,
|
|
12
|
+
const { PatternType, ExecutionContext, _ExecutionStatus } = require('../orchestration-engine');
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Extended PatternType with HANDOFF
|
|
@@ -17,17 +17,17 @@ const { PatternType, ExecutionContext, ExecutionStatus } = require('../orchestra
|
|
|
17
17
|
const HandoffPatternType = {
|
|
18
18
|
...PatternType,
|
|
19
19
|
HANDOFF: 'handoff',
|
|
20
|
-
TRIAGE: 'triage'
|
|
20
|
+
TRIAGE: 'triage',
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Handoff strategy options
|
|
25
25
|
*/
|
|
26
26
|
const HandoffStrategy = {
|
|
27
|
-
FIRST_MATCH: 'first-match',
|
|
28
|
-
BEST_MATCH: 'best-match',
|
|
29
|
-
ROUND_ROBIN: 'round-robin',
|
|
30
|
-
WEIGHTED: 'weighted'
|
|
27
|
+
FIRST_MATCH: 'first-match', // Use first matching agent
|
|
28
|
+
BEST_MATCH: 'best-match', // Use best scoring agent
|
|
29
|
+
ROUND_ROBIN: 'round-robin', // Rotate through agents
|
|
30
|
+
WEIGHTED: 'weighted', // Use weighted selection
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
/**
|
|
@@ -37,49 +37,51 @@ const HandoffFilters = {
|
|
|
37
37
|
/**
|
|
38
38
|
* Remove all tool calls from history
|
|
39
39
|
*/
|
|
40
|
-
removeAllTools:
|
|
40
|
+
removeAllTools: history => {
|
|
41
41
|
return history.filter(msg => msg.type !== 'tool_call' && msg.type !== 'tool_result');
|
|
42
42
|
},
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* Remove tool results only (keep calls)
|
|
46
46
|
*/
|
|
47
|
-
removeToolResults:
|
|
47
|
+
removeToolResults: history => {
|
|
48
48
|
return history.filter(msg => msg.type !== 'tool_result');
|
|
49
49
|
},
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
52
|
* Keep only user messages
|
|
53
53
|
*/
|
|
54
|
-
userMessagesOnly:
|
|
54
|
+
userMessagesOnly: history => {
|
|
55
55
|
return history.filter(msg => msg.role === 'user');
|
|
56
56
|
},
|
|
57
57
|
|
|
58
58
|
/**
|
|
59
59
|
* Keep last N messages
|
|
60
60
|
*/
|
|
61
|
-
lastN:
|
|
61
|
+
lastN: n => history => {
|
|
62
62
|
return history.slice(-n);
|
|
63
63
|
},
|
|
64
64
|
|
|
65
65
|
/**
|
|
66
66
|
* Keep everything (no filter)
|
|
67
67
|
*/
|
|
68
|
-
keepAll:
|
|
68
|
+
keepAll: history => history,
|
|
69
69
|
|
|
70
70
|
/**
|
|
71
71
|
* Summarize history to single message
|
|
72
72
|
*/
|
|
73
|
-
summarize:
|
|
73
|
+
summarize: history => {
|
|
74
74
|
if (history.length === 0) return [];
|
|
75
|
-
const summary = history
|
|
76
|
-
`[${msg.role || msg.type}]: ${msg.content?.substring(0, 100) || '...'}`
|
|
77
|
-
|
|
78
|
-
return [
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
75
|
+
const summary = history
|
|
76
|
+
.map(msg => `[${msg.role || msg.type}]: ${msg.content?.substring(0, 100) || '...'}`)
|
|
77
|
+
.join('\n');
|
|
78
|
+
return [
|
|
79
|
+
{
|
|
80
|
+
role: 'system',
|
|
81
|
+
content: `Previous conversation summary:\n${summary}`,
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
},
|
|
83
85
|
};
|
|
84
86
|
|
|
85
87
|
/**
|
|
@@ -102,7 +104,7 @@ class EscalationData {
|
|
|
102
104
|
sourceAgent: this.sourceAgent,
|
|
103
105
|
context: this.context,
|
|
104
106
|
timestamp: this.timestamp.toISOString(),
|
|
105
|
-
metadata: this.metadata
|
|
107
|
+
metadata: this.metadata,
|
|
106
108
|
};
|
|
107
109
|
}
|
|
108
110
|
}
|
|
@@ -112,13 +114,13 @@ class EscalationData {
|
|
|
112
114
|
*/
|
|
113
115
|
class HandoffConfig {
|
|
114
116
|
constructor(options = {}) {
|
|
115
|
-
this.agent = options.agent;
|
|
117
|
+
this.agent = options.agent; // Target agent
|
|
116
118
|
this.toolNameOverride = options.toolNameOverride || null;
|
|
117
119
|
this.inputType = options.inputType || EscalationData;
|
|
118
120
|
this.inputFilter = options.inputFilter || HandoffFilters.keepAll;
|
|
119
|
-
this.onHandoff = options.onHandoff || null;
|
|
120
|
-
this.condition = options.condition || null;
|
|
121
|
-
this.priority = options.priority || 0;
|
|
121
|
+
this.onHandoff = options.onHandoff || null; // Callback when handoff occurs
|
|
122
|
+
this.condition = options.condition || null; // Condition function
|
|
123
|
+
this.priority = options.priority || 0; // Selection priority
|
|
122
124
|
}
|
|
123
125
|
}
|
|
124
126
|
|
|
@@ -151,12 +153,12 @@ class HandoffPattern extends BasePattern {
|
|
|
151
153
|
'Escalation workflows',
|
|
152
154
|
'Customer service routing',
|
|
153
155
|
'Multi-expert consultation',
|
|
154
|
-
'Fallback handling'
|
|
156
|
+
'Fallback handling',
|
|
155
157
|
],
|
|
156
158
|
complexity: 'medium',
|
|
157
159
|
supportsParallel: false,
|
|
158
160
|
supportsReplanning: true,
|
|
159
|
-
requiresHuman: false
|
|
161
|
+
requiresHuman: false,
|
|
160
162
|
});
|
|
161
163
|
|
|
162
164
|
this.options = {
|
|
@@ -167,7 +169,7 @@ class HandoffPattern extends BasePattern {
|
|
|
167
169
|
inputFilter: options.inputFilter || HandoffFilters.keepAll,
|
|
168
170
|
onHandoff: options.onHandoff || null,
|
|
169
171
|
onHandoffComplete: options.onHandoffComplete || null,
|
|
170
|
-
...options
|
|
172
|
+
...options,
|
|
171
173
|
};
|
|
172
174
|
|
|
173
175
|
// Track handoff chain
|
|
@@ -199,7 +201,7 @@ class HandoffPattern extends BasePattern {
|
|
|
199
201
|
for (let i = 0; i < input.targetAgents.length; i++) {
|
|
200
202
|
const target = input.targetAgents[i];
|
|
201
203
|
const agent = target.agent || target;
|
|
202
|
-
|
|
204
|
+
|
|
203
205
|
// Check if agent is a HandoffConfig or direct agent
|
|
204
206
|
if (!agent) {
|
|
205
207
|
errors.push(`Target agent ${i} is invalid`);
|
|
@@ -216,7 +218,7 @@ class HandoffPattern extends BasePattern {
|
|
|
216
218
|
|
|
217
219
|
return {
|
|
218
220
|
valid: errors.length === 0,
|
|
219
|
-
errors
|
|
221
|
+
errors,
|
|
220
222
|
};
|
|
221
223
|
}
|
|
222
224
|
|
|
@@ -238,7 +240,7 @@ class HandoffPattern extends BasePattern {
|
|
|
238
240
|
message,
|
|
239
241
|
history = [],
|
|
240
242
|
escalationData = null,
|
|
241
|
-
sharedContext = {}
|
|
243
|
+
sharedContext = {},
|
|
242
244
|
} = context.input;
|
|
243
245
|
|
|
244
246
|
const startTime = Date.now();
|
|
@@ -248,7 +250,7 @@ class HandoffPattern extends BasePattern {
|
|
|
248
250
|
context,
|
|
249
251
|
sourceAgent: this._getAgentName(sourceAgent),
|
|
250
252
|
targetAgents: targetAgents.map(t => this._getAgentName(t.agent || t)),
|
|
251
|
-
escalationData
|
|
253
|
+
escalationData,
|
|
252
254
|
});
|
|
253
255
|
|
|
254
256
|
try {
|
|
@@ -256,33 +258,32 @@ class HandoffPattern extends BasePattern {
|
|
|
256
258
|
engine.emit('handoff:selecting', {
|
|
257
259
|
context,
|
|
258
260
|
strategy: this.options.strategy,
|
|
259
|
-
candidates: targetAgents.length
|
|
261
|
+
candidates: targetAgents.length,
|
|
260
262
|
});
|
|
261
263
|
|
|
262
|
-
const selectedTarget = await this.selectTargetAgent(
|
|
263
|
-
context,
|
|
264
|
-
targetAgents,
|
|
265
|
-
engine
|
|
266
|
-
);
|
|
264
|
+
const selectedTarget = await this.selectTargetAgent(context, targetAgents, engine);
|
|
267
265
|
|
|
268
266
|
if (!selectedTarget) {
|
|
269
267
|
throw new Error('No suitable target agent found for handoff');
|
|
270
268
|
}
|
|
271
269
|
|
|
272
|
-
const selectedConfig =
|
|
273
|
-
|
|
274
|
-
|
|
270
|
+
const selectedConfig =
|
|
271
|
+
selectedTarget instanceof HandoffConfig
|
|
272
|
+
? selectedTarget
|
|
273
|
+
: new HandoffConfig({ agent: selectedTarget });
|
|
275
274
|
|
|
276
275
|
// Step 2: Apply input filter to history
|
|
277
276
|
const inputFilter = selectedConfig.inputFilter || this.options.inputFilter;
|
|
278
277
|
const filteredHistory = inputFilter(history);
|
|
279
278
|
|
|
280
279
|
// Step 3: Create escalation data if not provided
|
|
281
|
-
const escalation =
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
280
|
+
const escalation =
|
|
281
|
+
escalationData ||
|
|
282
|
+
new EscalationData({
|
|
283
|
+
reason: context.input.reason || 'Agent handoff',
|
|
284
|
+
sourceAgent: this._getAgentName(sourceAgent),
|
|
285
|
+
context: sharedContext,
|
|
286
|
+
});
|
|
286
287
|
|
|
287
288
|
// Step 4: Execute onHandoff callback if provided
|
|
288
289
|
if (selectedConfig.onHandoff) {
|
|
@@ -297,7 +298,7 @@ class HandoffPattern extends BasePattern {
|
|
|
297
298
|
from: this._getAgentName(sourceAgent),
|
|
298
299
|
to: this._getAgentName(selectedConfig.agent),
|
|
299
300
|
reason: escalation.reason,
|
|
300
|
-
timestamp: new Date()
|
|
301
|
+
timestamp: new Date(),
|
|
301
302
|
});
|
|
302
303
|
|
|
303
304
|
// Step 6: Perform handoff (execute target agent)
|
|
@@ -308,7 +309,7 @@ class HandoffPattern extends BasePattern {
|
|
|
308
309
|
message,
|
|
309
310
|
history: filteredHistory,
|
|
310
311
|
escalation,
|
|
311
|
-
sharedContext
|
|
312
|
+
sharedContext,
|
|
312
313
|
},
|
|
313
314
|
context,
|
|
314
315
|
engine
|
|
@@ -328,7 +329,7 @@ class HandoffPattern extends BasePattern {
|
|
|
328
329
|
targetAgent: this._getAgentName(selectedConfig.agent),
|
|
329
330
|
result,
|
|
330
331
|
duration: endTime - startTime,
|
|
331
|
-
handoffChain: this.handoffChain
|
|
332
|
+
handoffChain: this.handoffChain,
|
|
332
333
|
});
|
|
333
334
|
|
|
334
335
|
return {
|
|
@@ -337,15 +338,14 @@ class HandoffPattern extends BasePattern {
|
|
|
337
338
|
targetAgent: this._getAgentName(selectedConfig.agent),
|
|
338
339
|
result,
|
|
339
340
|
handoffChain: [...this.handoffChain],
|
|
340
|
-
duration: endTime - startTime
|
|
341
|
+
duration: endTime - startTime,
|
|
341
342
|
};
|
|
342
|
-
|
|
343
343
|
} catch (error) {
|
|
344
344
|
engine.emit('handoff:failed', {
|
|
345
345
|
context,
|
|
346
346
|
sourceAgent: this._getAgentName(sourceAgent),
|
|
347
347
|
error: error.message,
|
|
348
|
-
handoffChain: this.handoffChain
|
|
348
|
+
handoffChain: this.handoffChain,
|
|
349
349
|
});
|
|
350
350
|
|
|
351
351
|
throw error;
|
|
@@ -360,7 +360,7 @@ class HandoffPattern extends BasePattern {
|
|
|
360
360
|
* @returns {Promise<HandoffConfig|Agent>} Selected agent
|
|
361
361
|
*/
|
|
362
362
|
async selectTargetAgent(context, targetAgents, engine) {
|
|
363
|
-
const {
|
|
363
|
+
const { _message, _history, _sharedContext } = context.input;
|
|
364
364
|
|
|
365
365
|
switch (this.options.strategy) {
|
|
366
366
|
case HandoffStrategy.FIRST_MATCH:
|
|
@@ -385,8 +385,9 @@ class HandoffPattern extends BasePattern {
|
|
|
385
385
|
*/
|
|
386
386
|
async _selectFirstMatch(targetAgents, context) {
|
|
387
387
|
for (const target of targetAgents) {
|
|
388
|
-
const config =
|
|
389
|
-
|
|
388
|
+
const config =
|
|
389
|
+
target instanceof HandoffConfig ? target : new HandoffConfig({ agent: target });
|
|
390
|
+
|
|
390
391
|
if (config.condition) {
|
|
391
392
|
const matches = await config.condition(context);
|
|
392
393
|
if (matches) return config;
|
|
@@ -400,13 +401,14 @@ class HandoffPattern extends BasePattern {
|
|
|
400
401
|
/**
|
|
401
402
|
* Select best matching agent based on scoring
|
|
402
403
|
*/
|
|
403
|
-
async _selectBestMatch(targetAgents, context,
|
|
404
|
+
async _selectBestMatch(targetAgents, context, _engine) {
|
|
404
405
|
let bestScore = -1;
|
|
405
406
|
let bestTarget = null;
|
|
406
407
|
|
|
407
408
|
for (const target of targetAgents) {
|
|
408
|
-
const config =
|
|
409
|
-
|
|
409
|
+
const config =
|
|
410
|
+
target instanceof HandoffConfig ? target : new HandoffConfig({ agent: target });
|
|
411
|
+
|
|
410
412
|
let score = config.priority || 0;
|
|
411
413
|
|
|
412
414
|
// If condition function exists, use it for scoring
|
|
@@ -473,7 +475,7 @@ class HandoffPattern extends BasePattern {
|
|
|
473
475
|
*/
|
|
474
476
|
async performHandoff(source, target, handoffData, parentContext, engine) {
|
|
475
477
|
const targetName = this._getAgentName(target);
|
|
476
|
-
|
|
478
|
+
|
|
477
479
|
// Create child context for target execution
|
|
478
480
|
const childContext = new ExecutionContext({
|
|
479
481
|
parentId: parentContext.id,
|
|
@@ -485,12 +487,12 @@ class HandoffPattern extends BasePattern {
|
|
|
485
487
|
escalation: handoffData.escalation?.toJSON?.() || handoffData.escalation,
|
|
486
488
|
sharedContext: handoffData.sharedContext,
|
|
487
489
|
isHandoff: true,
|
|
488
|
-
sourceAgent: this._getAgentName(source)
|
|
490
|
+
sourceAgent: this._getAgentName(source),
|
|
489
491
|
},
|
|
490
492
|
metadata: {
|
|
491
493
|
handoffChain: this.handoffChain,
|
|
492
|
-
handoffDepth: this.handoffChain.length
|
|
493
|
-
}
|
|
494
|
+
handoffDepth: this.handoffChain.length,
|
|
495
|
+
},
|
|
494
496
|
});
|
|
495
497
|
|
|
496
498
|
parentContext.children.push(childContext);
|
|
@@ -554,5 +556,5 @@ module.exports = {
|
|
|
554
556
|
HandoffConfig,
|
|
555
557
|
EscalationData,
|
|
556
558
|
handoff,
|
|
557
|
-
createHandoffPattern
|
|
559
|
+
createHandoffPattern,
|
|
558
560
|
};
|