@jungjaehoon/mama-os 0.9.2 → 0.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/README.md +41 -7
  2. package/dist/agent/agent-loop.d.ts.map +1 -1
  3. package/dist/agent/agent-loop.js +2 -3
  4. package/dist/agent/agent-loop.js.map +1 -1
  5. package/dist/agent/claude-cli-wrapper.d.ts +4 -4
  6. package/dist/agent/claude-cli-wrapper.d.ts.map +1 -1
  7. package/dist/agent/claude-cli-wrapper.js +17 -5
  8. package/dist/agent/claude-cli-wrapper.js.map +1 -1
  9. package/dist/agent/claude-client.js +3 -3
  10. package/dist/agent/claude-client.js.map +1 -1
  11. package/dist/agent/codex-mcp-process.d.ts +10 -0
  12. package/dist/agent/codex-mcp-process.d.ts.map +1 -1
  13. package/dist/agent/codex-mcp-process.js +226 -58
  14. package/dist/agent/codex-mcp-process.js.map +1 -1
  15. package/dist/agent/gateway-tool-executor.d.ts +15 -1
  16. package/dist/agent/gateway-tool-executor.d.ts.map +1 -1
  17. package/dist/agent/gateway-tool-executor.js +37 -3
  18. package/dist/agent/gateway-tool-executor.js.map +1 -1
  19. package/dist/agent/gateway-tools.md +1 -0
  20. package/dist/agent/persistent-cli-process.d.ts +2 -0
  21. package/dist/agent/persistent-cli-process.d.ts.map +1 -1
  22. package/dist/agent/persistent-cli-process.js +15 -0
  23. package/dist/agent/persistent-cli-process.js.map +1 -1
  24. package/dist/agent/types.d.ts +3 -3
  25. package/dist/agent/types.d.ts.map +1 -1
  26. package/dist/agent/types.js.map +1 -1
  27. package/dist/api/graph-api.d.ts.map +1 -1
  28. package/dist/api/graph-api.js +31 -5
  29. package/dist/api/graph-api.js.map +1 -1
  30. package/dist/cli/commands/start.d.ts.map +1 -1
  31. package/dist/cli/commands/start.js +91 -6
  32. package/dist/cli/commands/start.js.map +1 -1
  33. package/dist/cli/commands/stop.d.ts +7 -1
  34. package/dist/cli/commands/stop.d.ts.map +1 -1
  35. package/dist/cli/commands/stop.js +49 -0
  36. package/dist/cli/commands/stop.js.map +1 -1
  37. package/dist/cli/config/config-manager.d.ts.map +1 -1
  38. package/dist/cli/config/config-manager.js +60 -15
  39. package/dist/cli/config/config-manager.js.map +1 -1
  40. package/dist/cli/config/types.d.ts +19 -5
  41. package/dist/cli/config/types.d.ts.map +1 -1
  42. package/dist/cli/config/types.js +3 -3
  43. package/dist/cli/config/types.js.map +1 -1
  44. package/dist/gateways/image-analyzer.js +1 -1
  45. package/dist/gateways/image-analyzer.js.map +1 -1
  46. package/dist/gateways/slack.d.ts.map +1 -1
  47. package/dist/gateways/slack.js +8 -19
  48. package/dist/gateways/slack.js.map +1 -1
  49. package/dist/multi-agent/agent-process-manager.d.ts +15 -1
  50. package/dist/multi-agent/agent-process-manager.d.ts.map +1 -1
  51. package/dist/multi-agent/agent-process-manager.js +121 -22
  52. package/dist/multi-agent/agent-process-manager.js.map +1 -1
  53. package/dist/multi-agent/background-task-manager.d.ts +2 -2
  54. package/dist/multi-agent/background-task-manager.js +2 -2
  55. package/dist/multi-agent/bmad-templates.d.ts +67 -0
  56. package/dist/multi-agent/bmad-templates.d.ts.map +1 -0
  57. package/dist/multi-agent/bmad-templates.js +248 -0
  58. package/dist/multi-agent/bmad-templates.js.map +1 -0
  59. package/dist/multi-agent/council-engine.d.ts +60 -0
  60. package/dist/multi-agent/council-engine.d.ts.map +1 -0
  61. package/dist/multi-agent/council-engine.js +284 -0
  62. package/dist/multi-agent/council-engine.js.map +1 -0
  63. package/dist/multi-agent/multi-agent-base.d.ts +18 -9
  64. package/dist/multi-agent/multi-agent-base.d.ts.map +1 -1
  65. package/dist/multi-agent/multi-agent-base.js +116 -33
  66. package/dist/multi-agent/multi-agent-base.js.map +1 -1
  67. package/dist/multi-agent/multi-agent-discord.d.ts +3 -35
  68. package/dist/multi-agent/multi-agent-discord.d.ts.map +1 -1
  69. package/dist/multi-agent/multi-agent-discord.js +81 -302
  70. package/dist/multi-agent/multi-agent-discord.js.map +1 -1
  71. package/dist/multi-agent/multi-agent-slack.d.ts +2 -25
  72. package/dist/multi-agent/multi-agent-slack.d.ts.map +1 -1
  73. package/dist/multi-agent/multi-agent-slack.js +173 -253
  74. package/dist/multi-agent/multi-agent-slack.js.map +1 -1
  75. package/dist/multi-agent/runtime-process.d.ts +3 -0
  76. package/dist/multi-agent/runtime-process.d.ts.map +1 -1
  77. package/dist/multi-agent/runtime-process.js +4 -0
  78. package/dist/multi-agent/runtime-process.js.map +1 -1
  79. package/dist/multi-agent/shared-context.d.ts.map +1 -1
  80. package/dist/multi-agent/shared-context.js +4 -4
  81. package/dist/multi-agent/shared-context.js.map +1 -1
  82. package/dist/multi-agent/system-reminder.d.ts +1 -1
  83. package/dist/multi-agent/system-reminder.js +1 -1
  84. package/dist/multi-agent/types.d.ts +31 -15
  85. package/dist/multi-agent/types.d.ts.map +1 -1
  86. package/dist/multi-agent/types.js +1 -3
  87. package/dist/multi-agent/types.js.map +1 -1
  88. package/dist/multi-agent/ultrawork-state.d.ts +57 -0
  89. package/dist/multi-agent/ultrawork-state.d.ts.map +1 -0
  90. package/dist/multi-agent/ultrawork-state.js +191 -0
  91. package/dist/multi-agent/ultrawork-state.js.map +1 -0
  92. package/dist/multi-agent/ultrawork.d.ts +37 -19
  93. package/dist/multi-agent/ultrawork.d.ts.map +1 -1
  94. package/dist/multi-agent/ultrawork.js +587 -41
  95. package/dist/multi-agent/ultrawork.js.map +1 -1
  96. package/dist/multi-agent/workflow-engine.d.ts +7 -0
  97. package/dist/multi-agent/workflow-engine.d.ts.map +1 -1
  98. package/dist/multi-agent/workflow-engine.js +238 -33
  99. package/dist/multi-agent/workflow-engine.js.map +1 -1
  100. package/dist/multi-agent/workflow-types.d.ts +74 -1
  101. package/dist/multi-agent/workflow-types.d.ts.map +1 -1
  102. package/dist/onboarding/complete-autonomous-prompt.d.ts +1 -1
  103. package/dist/onboarding/complete-autonomous-prompt.d.ts.map +1 -1
  104. package/dist/onboarding/complete-autonomous-prompt.js +27 -10
  105. package/dist/onboarding/complete-autonomous-prompt.js.map +1 -1
  106. package/dist/onboarding/phase-7-integrations.d.ts.map +1 -1
  107. package/dist/onboarding/phase-7-integrations.js +23 -3
  108. package/dist/onboarding/phase-7-integrations.js.map +1 -1
  109. package/dist/onboarding/phase-9-finalization.d.ts.map +1 -1
  110. package/dist/onboarding/phase-9-finalization.js +33 -0
  111. package/dist/onboarding/phase-9-finalization.js.map +1 -1
  112. package/dist/setup/setup-prompt.d.ts +1 -1
  113. package/dist/setup/setup-prompt.d.ts.map +1 -1
  114. package/dist/setup/setup-prompt.js +1 -1
  115. package/package.json +1 -1
  116. package/public/viewer/js/modules/settings.js +110 -15
  117. package/public/viewer/js/utils/format.js +10 -7
  118. package/public/viewer/src/modules/settings.ts +133 -16
  119. package/public/viewer/src/utils/api.ts +2 -1
  120. package/public/viewer/src/utils/format.ts +10 -7
  121. package/public/viewer/viewer.html +1 -0
  122. package/templates/bmad/LICENSE +28 -0
  123. package/templates/bmad/architecture.md +343 -0
  124. package/templates/bmad/bmm-workflow-status.template.yaml +66 -0
  125. package/templates/bmad/prd.md +198 -0
  126. package/templates/bmad/product-brief.md +149 -0
  127. package/templates/bmad/sprint-status.template.yaml +35 -0
  128. package/templates/bmad/tech-spec.md +151 -0
  129. package/templates/personas/architect.md +70 -0
  130. package/templates/personas/conductor.md +373 -0
  131. package/templates/personas/developer.md +20 -7
  132. package/templates/personas/pm.md +49 -33
  133. package/templates/personas/reviewer.md +18 -5
  134. package/dist/multi-agent/pr-review-poller.d.ts +0 -197
  135. package/dist/multi-agent/pr-review-poller.d.ts.map +0 -1
  136. package/dist/multi-agent/pr-review-poller.js +0 -972
  137. package/dist/multi-agent/pr-review-poller.js.map +0 -1
  138. package/templates/personas/sisyphus-builtin-en.md +0 -161
  139. package/templates/personas/sisyphus.md +0 -218
@@ -85,7 +85,7 @@ Ask users which AI backend they want to use:
85
85
  To configure:
86
86
  \`\`\`
87
87
  update_config("agent.backend", "claude") // or "codex-mcp"
88
- update_config("agent.model", "claude-sonnet-4-20250514") // for claude
88
+ update_config("agent.model", "claude-sonnet-4-6") // for claude
89
89
  update_config("agent.model", "gpt-5.3-codex") // for codex-mcp
90
90
  \`\`\`
91
91
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jungjaehoon/mama-os",
3
- "version": "0.9.2",
3
+ "version": "0.9.4",
4
4
  "description": "MAMA OS - Your AI Operating System. Control + Visibility for AI-Powered Automation",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -30,18 +30,22 @@ const MODEL_OPTIONS = {
30
30
  'o3-mini',
31
31
  ],
32
32
  claude: [
33
- // Latest models
33
+ // Latest models (4.6)
34
34
  'claude-opus-4-6',
35
+ 'claude-sonnet-4-6',
36
+ // Previous gen (4.5)
37
+ 'claude-opus-4-5-20251101',
35
38
  'claude-sonnet-4-5-20250929',
36
39
  'claude-haiku-4-5-20251001',
37
40
  // Legacy models
38
- 'claude-opus-4-5-20251101',
39
41
  'claude-sonnet-4-20250514',
40
42
  'claude-opus-4-20250514',
41
43
  'claude-3-7-sonnet-20250219',
42
44
  'claude-3-haiku-20240307',
43
45
  ],
44
46
  };
47
+ const EFFORT_SUPPORTED_MODELS = new Set(['claude-opus-4-6', 'claude-sonnet-4-6']);
48
+ const MAX_EFFORT_MODELS = new Set(['claude-opus-4-6']);
45
49
  /**
46
50
  * Settings Module Class
47
51
  */
@@ -53,6 +57,49 @@ export class SettingsModule {
53
57
  backendListenersInitialized = false;
54
58
  delegatedListenersInitialized = false;
55
59
  constructor() { }
60
+ supportsEffortModel(model) {
61
+ return EFFORT_SUPPORTED_MODELS.has(model);
62
+ }
63
+ supportsMaxEffortModel(model) {
64
+ return MAX_EFFORT_MODELS.has(model);
65
+ }
66
+ normalizeEffortForModel(model, effort) {
67
+ if (effort === 'max' && !this.supportsMaxEffortModel(model)) {
68
+ return 'high';
69
+ }
70
+ return effort;
71
+ }
72
+ getEffortLevelsForModel(model) {
73
+ if (this.supportsMaxEffortModel(model)) {
74
+ return ['low', 'medium', 'high', 'max'];
75
+ }
76
+ return ['low', 'medium', 'high'];
77
+ }
78
+ buildEffortOptions(model, selectedEffort) {
79
+ return this.getEffortLevelsForModel(model)
80
+ .map((effort) => {
81
+ const selected = selectedEffort === effort ? ' selected' : '';
82
+ const label = effort === 'max' ? `${effort} (Opus)` : effort;
83
+ return `<option value="${effort}"${selected}>${label}</option>`;
84
+ })
85
+ .join('');
86
+ }
87
+ refreshAgentEffortControls(agentId, model) {
88
+ const effortContainer = getElementByIdOrNull(`agent-effort-container-${agentId}`);
89
+ if (!effortContainer) {
90
+ return;
91
+ }
92
+ const supportsEffort = this.supportsEffortModel(model);
93
+ effortContainer.style.display = supportsEffort ? 'block' : 'none';
94
+ const effortSelect = getElementByIdOrNull(`agent-effort-${agentId}`);
95
+ if (!effortSelect) {
96
+ return;
97
+ }
98
+ const currentEffort = (effortSelect.value || 'medium');
99
+ const normalizedEffort = this.normalizeEffortForModel(model, currentEffort);
100
+ effortSelect.innerHTML = this.buildEffortOptions(model, normalizedEffort);
101
+ effortSelect.value = normalizedEffort;
102
+ }
56
103
  /**
57
104
  * Parse and validate required integer input.
58
105
  */
@@ -144,6 +191,14 @@ export class SettingsModule {
144
191
  }
145
192
  return;
146
193
  }
194
+ if (action === 'agent-model') {
195
+ const select = actionElement;
196
+ const agentId = select.dataset.agentId || '';
197
+ if (agentId) {
198
+ this.onAgentModelChange(agentId);
199
+ }
200
+ return;
201
+ }
147
202
  if (action === 'cron-toggle') {
148
203
  const checkbox = actionElement;
149
204
  const cronId = checkbox.dataset.cronId || '';
@@ -240,7 +295,7 @@ export class SettingsModule {
240
295
  this.setValue('settings-heartbeat-quiet-end', this.config.heartbeat?.quiet_end ?? 8);
241
296
  // Agent
242
297
  const backend = (this.config.agent?.backend || 'claude');
243
- const model = this.config.agent?.model || 'claude-sonnet-4-20250514';
298
+ const model = this.config.agent?.model || 'claude-sonnet-4-6';
244
299
  const effort = (this.config.agent?.effort || 'medium');
245
300
  this.setSelectValue('settings-agent-backend', backend);
246
301
  this.updateModelOptions(backend, model);
@@ -527,6 +582,10 @@ export class SettingsModule {
527
582
  const model = this.getSelectValue('settings-agent-model');
528
583
  const effort = (this.getSelectValue('settings-agent-effort') || 'medium');
529
584
  const useClaudeCli = backend === 'claude';
585
+ const resolvedModel = model || (backend === 'codex-mcp' ? 'gpt-5.2-codex' : 'claude-sonnet-4-6');
586
+ const normalizedEffort = this.supportsEffortModel(resolvedModel)
587
+ ? this.normalizeEffortForModel(resolvedModel, effort)
588
+ : undefined;
530
589
  // Get token values - if empty and original was masked, keep original
531
590
  const discordToken = this.getTokenValue('settings-discord-token', this.config?.discord?.token);
532
591
  const slackBotToken = this.getTokenValue('settings-slack-bot-token', this.config?.slack?.bot_token);
@@ -561,9 +620,9 @@ export class SettingsModule {
561
620
  use_claude_cli: useClaudeCli,
562
621
  agent: {
563
622
  backend,
564
- model: model || (backend === 'codex-mcp' ? 'gpt-5.2-codex' : 'claude-sonnet-4-20250514'),
565
- // Only include effort for Opus 4.6 (supports adaptive thinking)
566
- effort: model === 'claude-opus-4-6' ? effort : undefined,
623
+ model: resolvedModel,
624
+ // Effort for Claude 4.6 models (adaptive thinking). 'max' is Opus-only.
625
+ effort: normalizedEffort,
567
626
  max_turns: this.parseIntegerInput('settings-agent-max-turns', 1, 100, 10),
568
627
  timeout: this.parseIntegerInput('settings-agent-timeout', 1, 600, 300) * 1000,
569
628
  tools: this.collectToolModeData(),
@@ -623,21 +682,28 @@ export class SettingsModule {
623
682
  }
624
683
  /**
625
684
  * Show/hide effort level dropdown based on model selection
626
- * Effort level only applies to Claude Opus 4.6 which supports adaptive thinking
685
+ * Effort applies to Claude 4.6 models, with 'max' reserved for Opus.
627
686
  */
628
687
  updateEffortVisibility(model) {
629
688
  const effortContainer = getElementByIdOrNull('settings-effort-container');
630
689
  if (!effortContainer) {
631
690
  return;
632
691
  }
633
- // Show effort only for Opus 4.6 which supports adaptive thinking
634
- const supportsEffort = model === 'claude-opus-4-6';
692
+ const supportsEffort = this.supportsEffortModel(model);
635
693
  effortContainer.style.display = supportsEffort ? 'block' : 'none';
694
+ const effortSelect = getElementByIdOrNull('settings-agent-effort');
695
+ if (!effortSelect) {
696
+ return;
697
+ }
698
+ const currentEffort = (effortSelect.value || 'medium');
699
+ const normalizedEffort = this.normalizeEffortForModel(model, currentEffort);
700
+ effortSelect.innerHTML = this.buildEffortOptions(model, normalizedEffort);
701
+ effortSelect.value = normalizedEffort;
636
702
  }
637
703
  getNormalizedModelForBackend(backend, model) {
638
704
  const isCodexBackend = backend === 'codex-mcp';
639
705
  if (!model) {
640
- return isCodexBackend ? 'gpt-5.2-codex' : 'claude-sonnet-4-20250514';
706
+ return isCodexBackend ? 'gpt-5.2-codex' : 'claude-sonnet-4-6';
641
707
  }
642
708
  const isClaudeModel = /^claude-/i.test(model);
643
709
  if (isCodexBackend && isClaudeModel) {
@@ -811,7 +877,7 @@ export class SettingsModule {
811
877
  if (!container) {
812
878
  return;
813
879
  }
814
- const agents = (this.multiAgentData?.agents || []);
880
+ const agents = this.multiAgentData?.agents || [];
815
881
  if (agents.length === 0) {
816
882
  container.innerHTML = `
817
883
  <div class="bg-white border border-gray-200 rounded-lg p-3 text-xs text-gray-500">
@@ -829,7 +895,7 @@ export class SettingsModule {
829
895
  const agentCards = agents
830
896
  .map((agent) => {
831
897
  const tierColor = tierColors[agent.tier || 1] || tierColors[1];
832
- const backend = (agent.backend || this.config?.agent?.backend || 'claude') || 'claude';
898
+ const backend = (agent.backend || this.config?.agent?.backend || 'claude');
833
899
  const normalizedModel = this.getNormalizedModelForBackend(backend, agent.model || '');
834
900
  const agentId = agent.id || '';
835
901
  const backendOptions = ['codex-mcp', 'claude']
@@ -839,6 +905,10 @@ export class SettingsModule {
839
905
  const modelOptionHtml = modelOptions
840
906
  .map((m) => `<option value="${escapeAttr(m)}" ${m === normalizedModel ? 'selected' : ''}>${escapeHtml(formatModelName(m))}</option>`)
841
907
  .join('');
908
+ // Effort level (Claude 4.6 models only, max on Opus).
909
+ const supportsAgentEffort = this.supportsEffortModel(normalizedModel);
910
+ const selectedAgentEffort = this.normalizeEffortForModel(normalizedModel, (agent.effort || 'medium'));
911
+ const effortOptions = this.buildEffortOptions(normalizedModel, selectedAgentEffort);
842
912
  // Permission flags
843
913
  const canDelegate = agent.can_delegate ?? false;
844
914
  const hasAllTools = agent.tool_permissions?.allowed?.includes('*') ?? true;
@@ -857,9 +927,13 @@ export class SettingsModule {
857
927
  </div>
858
928
 
859
929
  <!-- Backend + Model Row -->
860
- <div class="flex gap-1 mb-2">
930
+ <div class="flex gap-1 mb-1">
861
931
  <select id="agent-backend-${escapeAttr(agentId)}" data-action="agent-backend" data-agent-id="${escapeAttr(agentId)}" class="flex-1 text-[10px] rounded border border-gray-200 px-1 py-0.5 bg-gray-50">${backendOptions}</select>
862
- <select id="agent-model-${escapeAttr(agentId)}" class="flex-1 text-[10px] rounded border border-gray-200 px-1 py-0.5 bg-gray-50">${modelOptionHtml}</select>
932
+ <select id="agent-model-${escapeAttr(agentId)}" data-action="agent-model" data-agent-id="${escapeAttr(agentId)}" class="flex-1 text-[10px] rounded border border-gray-200 px-1 py-0.5 bg-gray-50">${modelOptionHtml}</select>
933
+ </div>
934
+ <!-- Effort Row (Claude 4.6 only) -->
935
+ <div id="agent-effort-container-${escapeAttr(agentId)}" class="mb-2" style="display: ${supportsAgentEffort ? 'block' : 'none'}">
936
+ <select id="agent-effort-${escapeAttr(agentId)}" class="w-full text-[10px] rounded border border-gray-200 px-1 py-0.5 bg-gray-50">${effortOptions}</select>
863
937
  </div>
864
938
 
865
939
  <!-- Permissions Row -->
@@ -869,7 +943,12 @@ export class SettingsModule {
869
943
  <span>Delegate</span>
870
944
  </label>
871
945
  <label class="flex items-center gap-0.5 cursor-pointer">
872
- <input type="checkbox" id="agent-alltools-${escapeAttr(agentId)}" class="w-3 h-3 rounded border-gray-300 text-yellow-500 focus:ring-yellow-400" ${hasAllTools ? 'checked' : ''}>
946
+ <input
947
+ type="checkbox"
948
+ id="agent-alltools-${escapeAttr(agentId)}"
949
+ class="w-3 h-3 rounded border-gray-300 text-yellow-500 focus:ring-yellow-400"
950
+ ${hasAllTools ? 'checked' : ''}
951
+ >
873
952
  <span>All Tools</span>
874
953
  </label>
875
954
  </div>
@@ -914,6 +993,15 @@ export class SettingsModule {
914
993
  modelSelect.innerHTML = options
915
994
  .map((m) => `<option value="${escapeAttr(m)}" ${m === normalized ? 'selected' : ''}>${escapeHtml(formatModelName(m))}</option>`)
916
995
  .join('');
996
+ this.refreshAgentEffortControls(agentId, normalized);
997
+ }
998
+ onAgentModelChange(agentId) {
999
+ const modelSelect = getElementByIdOrNull(`agent-model-${agentId}`);
1000
+ if (!modelSelect) {
1001
+ return;
1002
+ }
1003
+ const model = modelSelect.value || '';
1004
+ this.refreshAgentEffortControls(agentId, model);
917
1005
  }
918
1006
  async saveAgentConfig(agentId) {
919
1007
  try {
@@ -928,6 +1016,12 @@ export class SettingsModule {
928
1016
  const model = this.getNormalizedModelForBackend(backend, modelSelect.value || '');
929
1017
  const can_delegate = delegateCheckbox?.checked ?? false;
930
1018
  const hasAllTools = allToolsCheckbox?.checked ?? true;
1019
+ // Effort level
1020
+ const effortSelect = getElementByIdOrNull(`agent-effort-${agentId}`);
1021
+ const supportsEffort = this.supportsEffortModel(model);
1022
+ const effort = supportsEffort && effortSelect
1023
+ ? this.normalizeEffortForModel(model, effortSelect.value)
1024
+ : undefined;
931
1025
  // Build tool_permissions based on checkbox
932
1026
  const tool_permissions = hasAllTools
933
1027
  ? { allowed: ['*'], blocked: [] }
@@ -935,6 +1029,7 @@ export class SettingsModule {
935
1029
  await API.put(`/api/multi-agent/agents/${agentId}`, {
936
1030
  backend,
937
1031
  model,
1032
+ effort,
938
1033
  can_delegate,
939
1034
  tool_permissions,
940
1035
  });
@@ -9,24 +9,27 @@
9
9
  * https://platform.claude.com/docs/en/about-claude/models/overview
10
10
  */
11
11
  const MODEL_NAMES = {
12
- // Latest models
12
+ // Claude 4.6
13
13
  'claude-opus-4-6': 'Claude Opus 4.6',
14
+ 'claude-sonnet-4-6': 'Claude Sonnet 4.6',
15
+ // Claude 4.5
16
+ 'claude-opus-4-5-20251101': 'Claude Opus 4.5',
14
17
  'claude-sonnet-4-5-20250929': 'Claude Sonnet 4.5',
15
18
  'claude-haiku-4-5-20251001': 'Claude Haiku 4.5',
16
- // Legacy models
17
- 'claude-opus-4-5-20251101': 'Claude Opus 4.5',
19
+ // Claude 4.0
18
20
  'claude-sonnet-4-20250514': 'Claude Sonnet 4',
19
21
  'claude-opus-4-20250514': 'Claude Opus 4',
22
+ // Legacy
20
23
  'claude-3-7-sonnet-20250219': 'Claude Sonnet 3.7',
21
24
  'claude-3-haiku-20240307': 'Claude Haiku 3',
22
- // GPT models
25
+ // GPT / Codex
23
26
  'gpt-5.3-codex': 'GPT-5.3 Codex',
24
- 'gpt-5.2': 'GPT-5.2',
25
- 'gpt-5.1': 'GPT-5.1',
27
+ 'gpt-5.2-codex': 'GPT-5.2 Codex',
28
+ 'gpt-5.1-codex-max': 'GPT-5.1 Codex Max',
26
29
  'gpt-4.1': 'GPT-4.1',
27
30
  'gpt-4o': 'GPT-4o',
28
31
  'gpt-4o-mini': 'GPT-4o Mini',
29
- 'o1': 'o1',
32
+ o1: 'o1',
30
33
  'o1-mini': 'o1 Mini',
31
34
  'o3-mini': 'o3 Mini',
32
35
  };
@@ -94,12 +94,14 @@ const MODEL_OPTIONS: Record<AgentBackend, readonly string[]> = {
94
94
  'o3-mini',
95
95
  ],
96
96
  claude: [
97
- // Latest models
97
+ // Latest models (4.6)
98
98
  'claude-opus-4-6',
99
+ 'claude-sonnet-4-6',
100
+ // Previous gen (4.5)
101
+ 'claude-opus-4-5-20251101',
99
102
  'claude-sonnet-4-5-20250929',
100
103
  'claude-haiku-4-5-20251001',
101
104
  // Legacy models
102
- 'claude-opus-4-5-20251101',
103
105
  'claude-sonnet-4-20250514',
104
106
  'claude-opus-4-20250514',
105
107
  'claude-3-7-sonnet-20250219',
@@ -107,6 +109,9 @@ const MODEL_OPTIONS: Record<AgentBackend, readonly string[]> = {
107
109
  ],
108
110
  };
109
111
 
112
+ const EFFORT_SUPPORTED_MODELS = new Set<string>(['claude-opus-4-6', 'claude-sonnet-4-6']);
113
+ const MAX_EFFORT_MODELS = new Set<string>(['claude-opus-4-6']);
114
+
110
115
  /**
111
116
  * Settings Module Class
112
117
  */
@@ -120,6 +125,58 @@ export class SettingsModule {
120
125
 
121
126
  constructor() {}
122
127
 
128
+ private supportsEffortModel(model: string): boolean {
129
+ return EFFORT_SUPPORTED_MODELS.has(model);
130
+ }
131
+
132
+ private supportsMaxEffortModel(model: string): boolean {
133
+ return MAX_EFFORT_MODELS.has(model);
134
+ }
135
+
136
+ private normalizeEffortForModel(model: string, effort: EffortLevel): EffortLevel {
137
+ if (effort === 'max' && !this.supportsMaxEffortModel(model)) {
138
+ return 'high';
139
+ }
140
+ return effort;
141
+ }
142
+
143
+ private getEffortLevelsForModel(model: string): EffortLevel[] {
144
+ if (this.supportsMaxEffortModel(model)) {
145
+ return ['low', 'medium', 'high', 'max'];
146
+ }
147
+ return ['low', 'medium', 'high'];
148
+ }
149
+
150
+ private buildEffortOptions(model: string, selectedEffort: EffortLevel): string {
151
+ return this.getEffortLevelsForModel(model)
152
+ .map((effort) => {
153
+ const selected = selectedEffort === effort ? ' selected' : '';
154
+ const label = effort === 'max' ? `${effort} (Opus)` : effort;
155
+ return `<option value="${effort}"${selected}>${label}</option>`;
156
+ })
157
+ .join('');
158
+ }
159
+
160
+ private refreshAgentEffortControls(agentId: string, model: string): void {
161
+ const effortContainer = getElementByIdOrNull<HTMLElement>(`agent-effort-container-${agentId}`);
162
+ if (!effortContainer) {
163
+ return;
164
+ }
165
+
166
+ const supportsEffort = this.supportsEffortModel(model);
167
+ effortContainer.style.display = supportsEffort ? 'block' : 'none';
168
+
169
+ const effortSelect = getElementByIdOrNull<HTMLSelectElement>(`agent-effort-${agentId}`);
170
+ if (!effortSelect) {
171
+ return;
172
+ }
173
+
174
+ const currentEffort = (effortSelect.value || 'medium') as EffortLevel;
175
+ const normalizedEffort = this.normalizeEffortForModel(model, currentEffort);
176
+ effortSelect.innerHTML = this.buildEffortOptions(model, normalizedEffort);
177
+ effortSelect.value = normalizedEffort;
178
+ }
179
+
123
180
  /**
124
181
  * Parse and validate required integer input.
125
182
  */
@@ -237,6 +294,15 @@ export class SettingsModule {
237
294
  return;
238
295
  }
239
296
 
297
+ if (action === 'agent-model') {
298
+ const select = actionElement as HTMLSelectElement;
299
+ const agentId = select.dataset.agentId || '';
300
+ if (agentId) {
301
+ this.onAgentModelChange(agentId);
302
+ }
303
+ return;
304
+ }
305
+
240
306
  if (action === 'cron-toggle') {
241
307
  const checkbox = actionElement as HTMLInputElement;
242
308
  const cronId = checkbox.dataset.cronId || '';
@@ -348,7 +414,7 @@ export class SettingsModule {
348
414
 
349
415
  // Agent
350
416
  const backend = (this.config.agent?.backend || 'claude') as AgentBackend;
351
- const model = this.config.agent?.model || 'claude-sonnet-4-20250514';
417
+ const model = this.config.agent?.model || 'claude-sonnet-4-6';
352
418
  const effort = (this.config.agent?.effort || 'medium') as EffortLevel;
353
419
  this.setSelectValue('settings-agent-backend', backend);
354
420
  this.updateModelOptions(backend, model);
@@ -688,6 +754,11 @@ export class SettingsModule {
688
754
  const model = this.getSelectValue('settings-agent-model');
689
755
  const effort = (this.getSelectValue('settings-agent-effort') || 'medium') as EffortLevel;
690
756
  const useClaudeCli = backend === 'claude';
757
+ const resolvedModel =
758
+ model || (backend === 'codex-mcp' ? 'gpt-5.2-codex' : 'claude-sonnet-4-6');
759
+ const normalizedEffort = this.supportsEffortModel(resolvedModel)
760
+ ? this.normalizeEffortForModel(resolvedModel, effort)
761
+ : undefined;
691
762
 
692
763
  // Get token values - if empty and original was masked, keep original
693
764
  const discordToken = this.getTokenValue('settings-discord-token', this.config?.discord?.token);
@@ -736,9 +807,9 @@ export class SettingsModule {
736
807
  use_claude_cli: useClaudeCli,
737
808
  agent: {
738
809
  backend,
739
- model: model || (backend === 'codex-mcp' ? 'gpt-5.2-codex' : 'claude-sonnet-4-20250514'),
740
- // Only include effort for Opus 4.6 (supports adaptive thinking)
741
- effort: model === 'claude-opus-4-6' ? effort : undefined,
810
+ model: resolvedModel,
811
+ // Effort for Claude 4.6 models (adaptive thinking). 'max' is Opus-only.
812
+ effort: normalizedEffort,
742
813
  max_turns: this.parseIntegerInput('settings-agent-max-turns', 1, 100, 10),
743
814
  timeout: this.parseIntegerInput('settings-agent-timeout', 1, 600, 300) * 1000,
744
815
  tools: this.collectToolModeData(),
@@ -810,22 +881,31 @@ export class SettingsModule {
810
881
 
811
882
  /**
812
883
  * Show/hide effort level dropdown based on model selection
813
- * Effort level only applies to Claude Opus 4.6 which supports adaptive thinking
884
+ * Effort applies to Claude 4.6 models, with 'max' reserved for Opus.
814
885
  */
815
886
  updateEffortVisibility(model: string): void {
816
887
  const effortContainer = getElementByIdOrNull<HTMLElement>('settings-effort-container');
817
888
  if (!effortContainer) {
818
889
  return;
819
890
  }
820
- // Show effort only for Opus 4.6 which supports adaptive thinking
821
- const supportsEffort = model === 'claude-opus-4-6';
891
+ const supportsEffort = this.supportsEffortModel(model);
822
892
  effortContainer.style.display = supportsEffort ? 'block' : 'none';
893
+
894
+ const effortSelect = getElementByIdOrNull<HTMLSelectElement>('settings-agent-effort');
895
+ if (!effortSelect) {
896
+ return;
897
+ }
898
+
899
+ const currentEffort = (effortSelect.value || 'medium') as EffortLevel;
900
+ const normalizedEffort = this.normalizeEffortForModel(model, currentEffort);
901
+ effortSelect.innerHTML = this.buildEffortOptions(model, normalizedEffort);
902
+ effortSelect.value = normalizedEffort;
823
903
  }
824
904
 
825
905
  getNormalizedModelForBackend(backend: AgentBackend, model: string): string {
826
906
  const isCodexBackend = backend === 'codex-mcp';
827
907
  if (!model) {
828
- return isCodexBackend ? 'gpt-5.2-codex' : 'claude-sonnet-4-20250514';
908
+ return isCodexBackend ? 'gpt-5.2-codex' : 'claude-sonnet-4-6';
829
909
  }
830
910
  const isClaudeModel = /^claude-/i.test(model);
831
911
  if (isCodexBackend && isClaudeModel) {
@@ -1022,7 +1102,7 @@ export class SettingsModule {
1022
1102
  return;
1023
1103
  }
1024
1104
 
1025
- const agents = (this.multiAgentData?.agents || []) as MultiAgentAgent[];
1105
+ const agents = this.multiAgentData?.agents || [];
1026
1106
 
1027
1107
  if (agents.length === 0) {
1028
1108
  container.innerHTML = `
@@ -1043,8 +1123,7 @@ export class SettingsModule {
1043
1123
  const agentCards = agents
1044
1124
  .map((agent: MultiAgentAgent) => {
1045
1125
  const tierColor = tierColors[agent.tier || 1] || tierColors[1];
1046
- const backend =
1047
- ((agent.backend || this.config?.agent?.backend || 'claude') as AgentBackend) || 'claude';
1126
+ const backend = (agent.backend || this.config?.agent?.backend || 'claude') as AgentBackend;
1048
1127
  const normalizedModel = this.getNormalizedModelForBackend(backend, agent.model || '');
1049
1128
  const agentId = agent.id || '';
1050
1129
  const backendOptions = ['codex-mcp', 'claude']
@@ -1061,6 +1140,14 @@ export class SettingsModule {
1061
1140
  )
1062
1141
  .join('');
1063
1142
 
1143
+ // Effort level (Claude 4.6 models only, max on Opus).
1144
+ const supportsAgentEffort = this.supportsEffortModel(normalizedModel);
1145
+ const selectedAgentEffort = this.normalizeEffortForModel(
1146
+ normalizedModel,
1147
+ (agent.effort || 'medium') as EffortLevel
1148
+ );
1149
+ const effortOptions = this.buildEffortOptions(normalizedModel, selectedAgentEffort);
1150
+
1064
1151
  // Permission flags
1065
1152
  const canDelegate = agent.can_delegate ?? false;
1066
1153
  const hasAllTools = agent.tool_permissions?.allowed?.includes('*') ?? true;
@@ -1080,9 +1167,13 @@ export class SettingsModule {
1080
1167
  </div>
1081
1168
 
1082
1169
  <!-- Backend + Model Row -->
1083
- <div class="flex gap-1 mb-2">
1170
+ <div class="flex gap-1 mb-1">
1084
1171
  <select id="agent-backend-${escapeAttr(agentId)}" data-action="agent-backend" data-agent-id="${escapeAttr(agentId)}" class="flex-1 text-[10px] rounded border border-gray-200 px-1 py-0.5 bg-gray-50">${backendOptions}</select>
1085
- <select id="agent-model-${escapeAttr(agentId)}" class="flex-1 text-[10px] rounded border border-gray-200 px-1 py-0.5 bg-gray-50">${modelOptionHtml}</select>
1172
+ <select id="agent-model-${escapeAttr(agentId)}" data-action="agent-model" data-agent-id="${escapeAttr(agentId)}" class="flex-1 text-[10px] rounded border border-gray-200 px-1 py-0.5 bg-gray-50">${modelOptionHtml}</select>
1173
+ </div>
1174
+ <!-- Effort Row (Claude 4.6 only) -->
1175
+ <div id="agent-effort-container-${escapeAttr(agentId)}" class="mb-2" style="display: ${supportsAgentEffort ? 'block' : 'none'}">
1176
+ <select id="agent-effort-${escapeAttr(agentId)}" class="w-full text-[10px] rounded border border-gray-200 px-1 py-0.5 bg-gray-50">${effortOptions}</select>
1086
1177
  </div>
1087
1178
 
1088
1179
  <!-- Permissions Row -->
@@ -1092,7 +1183,12 @@ export class SettingsModule {
1092
1183
  <span>Delegate</span>
1093
1184
  </label>
1094
1185
  <label class="flex items-center gap-0.5 cursor-pointer">
1095
- <input type="checkbox" id="agent-alltools-${escapeAttr(agentId)}" class="w-3 h-3 rounded border-gray-300 text-yellow-500 focus:ring-yellow-400" ${hasAllTools ? 'checked' : ''}>
1186
+ <input
1187
+ type="checkbox"
1188
+ id="agent-alltools-${escapeAttr(agentId)}"
1189
+ class="w-3 h-3 rounded border-gray-300 text-yellow-500 focus:ring-yellow-400"
1190
+ ${hasAllTools ? 'checked' : ''}
1191
+ >
1096
1192
  <span>All Tools</span>
1097
1193
  </label>
1098
1194
  </div>
@@ -1147,6 +1243,18 @@ export class SettingsModule {
1147
1243
  `<option value="${escapeAttr(m)}" ${m === normalized ? 'selected' : ''}>${escapeHtml(formatModelName(m))}</option>`
1148
1244
  )
1149
1245
  .join('');
1246
+
1247
+ this.refreshAgentEffortControls(agentId, normalized);
1248
+ }
1249
+
1250
+ onAgentModelChange(agentId: string): void {
1251
+ const modelSelect = getElementByIdOrNull<HTMLSelectElement>(`agent-model-${agentId}`);
1252
+ if (!modelSelect) {
1253
+ return;
1254
+ }
1255
+
1256
+ const model = modelSelect.value || '';
1257
+ this.refreshAgentEffortControls(agentId, model);
1150
1258
  }
1151
1259
 
1152
1260
  async saveAgentConfig(agentId: string): Promise<void> {
@@ -1165,6 +1273,14 @@ export class SettingsModule {
1165
1273
  const can_delegate = delegateCheckbox?.checked ?? false;
1166
1274
  const hasAllTools = allToolsCheckbox?.checked ?? true;
1167
1275
 
1276
+ // Effort level
1277
+ const effortSelect = getElementByIdOrNull<HTMLSelectElement>(`agent-effort-${agentId}`);
1278
+ const supportsEffort = this.supportsEffortModel(model);
1279
+ const effort: EffortLevel | undefined =
1280
+ supportsEffort && effortSelect
1281
+ ? this.normalizeEffortForModel(model, effortSelect.value as EffortLevel)
1282
+ : undefined;
1283
+
1168
1284
  // Build tool_permissions based on checkbox
1169
1285
  const tool_permissions = hasAllTools
1170
1286
  ? { allowed: ['*'], blocked: [] }
@@ -1173,6 +1289,7 @@ export class SettingsModule {
1173
1289
  await API.put(`/api/multi-agent/agents/${agentId}`, {
1174
1290
  backend,
1175
1291
  model,
1292
+ effort,
1176
1293
  can_delegate,
1177
1294
  tool_permissions,
1178
1295
  });
@@ -124,7 +124,7 @@ export interface ApiAgentToolsConfig {
124
124
  [key: string]: unknown;
125
125
  }
126
126
 
127
- export type EffortLevel = 'low' | 'medium' | 'high';
127
+ export type EffortLevel = 'low' | 'medium' | 'high' | 'max';
128
128
 
129
129
  export interface ApiAgentConfig {
130
130
  backend?: 'claude' | 'codex-mcp';
@@ -184,6 +184,7 @@ export interface MultiAgentAgent {
184
184
  tier?: number;
185
185
  status?: string;
186
186
  model?: string;
187
+ effort?: EffortLevel;
187
188
  backend?: 'claude' | 'codex-mcp';
188
189
  bot_token?: string;
189
190
  slack_bot_token?: string | null;
@@ -11,24 +11,27 @@
11
11
  * https://platform.claude.com/docs/en/about-claude/models/overview
12
12
  */
13
13
  const MODEL_NAMES: Record<string, string> = {
14
- // Latest models
14
+ // Claude 4.6
15
15
  'claude-opus-4-6': 'Claude Opus 4.6',
16
+ 'claude-sonnet-4-6': 'Claude Sonnet 4.6',
17
+ // Claude 4.5
18
+ 'claude-opus-4-5-20251101': 'Claude Opus 4.5',
16
19
  'claude-sonnet-4-5-20250929': 'Claude Sonnet 4.5',
17
20
  'claude-haiku-4-5-20251001': 'Claude Haiku 4.5',
18
- // Legacy models
19
- 'claude-opus-4-5-20251101': 'Claude Opus 4.5',
21
+ // Claude 4.0
20
22
  'claude-sonnet-4-20250514': 'Claude Sonnet 4',
21
23
  'claude-opus-4-20250514': 'Claude Opus 4',
24
+ // Legacy
22
25
  'claude-3-7-sonnet-20250219': 'Claude Sonnet 3.7',
23
26
  'claude-3-haiku-20240307': 'Claude Haiku 3',
24
- // GPT models
27
+ // GPT / Codex
25
28
  'gpt-5.3-codex': 'GPT-5.3 Codex',
26
- 'gpt-5.2': 'GPT-5.2',
27
- 'gpt-5.1': 'GPT-5.1',
29
+ 'gpt-5.2-codex': 'GPT-5.2 Codex',
30
+ 'gpt-5.1-codex-max': 'GPT-5.1 Codex Max',
28
31
  'gpt-4.1': 'GPT-4.1',
29
32
  'gpt-4o': 'GPT-4o',
30
33
  'gpt-4o-mini': 'GPT-4o Mini',
31
- 'o1': 'o1',
34
+ o1: 'o1',
32
35
  'o1-mini': 'o1 Mini',
33
36
  'o3-mini': 'o3 Mini',
34
37
  };
@@ -576,6 +576,7 @@
576
576
  <option value="low">Low</option>
577
577
  <option value="medium" selected>Medium</option>
578
578
  <option value="high">High</option>
579
+ <option value="max">Max (Opus only)</option>
579
580
  </select>
580
581
  </div>
581
582
  <div>
@@ -0,0 +1,28 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 BMad Code, LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ TRADEMARK NOTICE: "BMad", "BMad Method", and "BMAD-METHOD" are trademarks of
26
+ BMad Code, LLC and are NOT covered by this MIT license. These templates are
27
+ used under MIT license terms. MAMA is not affiliated with or endorsed by
28
+ BMad Code, LLC.