@polderlabs/bizar 6.2.0 → 6.2.2

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.
@@ -10,7 +10,7 @@
10
10
  */
11
11
  import { test, describe, beforeEach, afterEach } from 'node:test';
12
12
  import assert from 'node:assert/strict';
13
- import { mkdtempSync, mkdirSync, writeFileSync, rmSync, existsSync, readFileSync } from 'node:fs';
13
+ import { mkdtempSync, mkdirSync, writeFileSync, rmSync, existsSync, readFileSync, chmodSync } from 'node:fs';
14
14
  import { tmpdir } from 'node:os';
15
15
  import { join } from 'node:path';
16
16
  import { Writable } from 'node:stream';
@@ -68,7 +68,7 @@ function makeFakeClineInstall(root) {
68
68
  'audit.md', 'bizar.md', 'explain.md', 'init.md', 'learn.md',
69
69
  'plan.md', 'plow-through.md', 'pr-review.md', 'tailscale-serve.md',
70
70
  'visual-plan.md',
71
- 'team.md', 'test.md', 'validate.md',
71
+ 'team.md', 'test.md', 'validate.md', 'setup-provider.md',
72
72
  ]) {
73
73
  writeFileSync(join(cmdsDir, f), '# fake command');
74
74
  }
@@ -85,8 +85,10 @@ function makeFakeClineInstall(root) {
85
85
  }
86
86
  const hooksDir = join(root, 'hooks');
87
87
  mkdirSync(hooksDir, { recursive: true });
88
- for (const h of ['pre-tool-use.md', 'post-tool-use.md', 'README.md']) {
89
- writeFileSync(join(hooksDir, h), '# fake hook');
88
+ for (const h of ['PreToolUse', 'PostToolUse', 'TaskStart', 'TaskResume', 'UserPromptSubmit']) {
89
+ // Cline hooks must be executable scripts with a shebang line.
90
+ writeFileSync(join(hooksDir, h), '#!/usr/bin/env node\n// fake hook\n');
91
+ chmodSync(join(hooksDir, h), 0o755);
90
92
  }
91
93
  const pluginDir = join(root, 'plugins', 'bizar');
92
94
  mkdirSync(pluginDir, { recursive: true });
@@ -203,28 +205,54 @@ describe('runValidate() — JSON output', () => {
203
205
  assert.equal(exitCode, 1, 'should fail when enableAgentTeams is false');
204
206
  });
205
207
 
206
- test('fails when provider config is missing', async () => {
208
+ test('passes when no provider is configured (v6.2.2+ — user must configure)', async () => {
209
+ // v6.2.2: the installer no longer touches provider config. The
210
+ // user must add their own provider. The provider-config check
211
+ // is therefore ALWAYS lenient — it just reports state.
207
212
  const cfg = JSON.parse(readFileSync(join(workDir, 'cline.json'), 'utf8'));
208
213
  delete cfg.provider;
209
214
  writeFileSync(join(workDir, 'cline.json'), JSON.stringify(cfg, null, 2));
210
- const { exitCode } = await captureRun({ json: true });
211
- assert.equal(exitCode, 1);
215
+ const { exitCode, stdout } = await captureRun({ json: true });
216
+ assert.equal(exitCode, 0, 'no-provider must not fail validation (v6.2.2+ contract)');
217
+ const parsed = JSON.parse(stdout);
218
+ const p = parsed.results.find((r) => r.name === 'provider-config');
219
+ assert.ok(p, 'provider-config check should be present');
220
+ assert.equal(p.ok, true, 'provider-config always returns ok (lenient)');
221
+ assert.match(p.message, /no provider configured/);
212
222
  });
213
223
 
214
- test('passes when only 9router is configured (no minimax)', async () => {
224
+ test('reports user-configured providers when present', async () => {
225
+ // User has set up their own provider (anything goes).
215
226
  const cfg = JSON.parse(readFileSync(join(workDir, 'cline.json'), 'utf8'));
216
- delete cfg.provider.minimax;
227
+ cfg.provider = {
228
+ 'my-custom-provider': {
229
+ baseUrl: 'https://my-llm.example/v1',
230
+ apiKey: 'sk-test',
231
+ models: { 'my-model-1': {}, 'my-model-2': {} },
232
+ },
233
+ };
217
234
  writeFileSync(join(workDir, 'cline.json'), JSON.stringify(cfg, null, 2));
218
- const { exitCode } = await captureRun({ json: true });
235
+ const { exitCode, stdout } = await captureRun({ json: true });
219
236
  assert.equal(exitCode, 0);
237
+ const parsed = JSON.parse(stdout);
238
+ const p = parsed.results.find((r) => r.name === 'provider-config');
239
+ assert.match(p.message, /my-custom-provider/);
240
+ assert.match(p.message, /2 models/);
220
241
  });
221
242
 
222
- test('passes when only minimax is configured (no 9router)', async () => {
243
+ test('reports both providers if user has multiple', async () => {
223
244
  const cfg = JSON.parse(readFileSync(join(workDir, 'cline.json'), 'utf8'));
224
- delete cfg.provider['9router'];
245
+ cfg.provider = {
246
+ 'a': { baseUrl: 'https://a.example/v1', models: { 'm1': {} } },
247
+ 'b': { baseUrl: 'https://b.example/v1', models: { 'm2': {}, 'm3': {} } },
248
+ };
225
249
  writeFileSync(join(workDir, 'cline.json'), JSON.stringify(cfg, null, 2));
226
- const { exitCode } = await captureRun({ json: true });
250
+ const { exitCode, stdout } = await captureRun({ json: true });
227
251
  assert.equal(exitCode, 0);
252
+ const parsed = JSON.parse(stdout);
253
+ const p = parsed.results.find((r) => r.name === 'provider-config');
254
+ assert.match(p.message, /\ba\b/);
255
+ assert.match(p.message, /\bb\b/);
228
256
  });
229
257
 
230
258
  test('default mode is lenient on 9router-unreachable', async () => {
package/cli/provision.mjs CHANGED
@@ -38,7 +38,7 @@
38
38
 
39
39
  import chalk from 'chalk';
40
40
  import { execSync, spawn, spawnSync } from 'node:child_process';
41
- import { existsSync, readFileSync, readdirSync, rmSync, writeFileSync, mkdirSync, statSync, copyFileSync } from 'node:fs';
41
+ import { existsSync, readFileSync, readdirSync, rmSync, writeFileSync, mkdirSync, statSync, copyFileSync, chmodSync } from 'node:fs';
42
42
  import { homedir } from 'node:os';
43
43
  import { join, dirname, sep } from 'node:path';
44
44
  import { fileURLToPath } from 'node:url';
@@ -860,94 +860,69 @@ export async function patchClineJson({ dryRun, force }) {
860
860
  (p) => Array.isArray(p) && typeof p[0] === 'string' && p[0].includes('plugins/bizar'),
861
861
  );
862
862
 
863
- // v6.2.0 — Multi-patch installer. On every install/update, ensure the
864
- // full Bizar config surface is present in cline.json:
863
+ // v6.2.2 — Multi-patch installer. On every install/update, ensure the
864
+ // Bizar config surface is present in cline.json:
865
865
  //
866
- // 1. provider.9router (preferred gateway since v6.0.1) add if
867
- // missing so the install is "complete" out of the box.
868
- // 2. provider.minimax (legacy fallback) — kept for back-compat.
869
- // 3. default_agent — set to "odin" if missing.
870
- // 4. $schema — add if missing (helps editors validate).
871
- // 5. instructions — point at .cline/instructions/bizar-tools.md if
872
- // missing, so Cline loads the tool reference on every session.
873
- // 6. plugin entry — add if missing (the critical one; without this
866
+ // 1. plugin entry add if missing (the critical one; without this
874
867
  // the Bizar plugin never loads).
875
- // 7. permissions — set to "allow" if missing.
876
- // 8. snapshotset to false if missing.
868
+ // 2. default_agent — set to "odin" if missing.
869
+ // 3. $schemaadd if missing (helps editors validate).
870
+ // 4. instructions — point at .cline/instructions/bizar-tools.md if
871
+ // missing, so Cline loads the tool reference on every session.
872
+ // 5. permissions — set to "allow" if missing.
873
+ // 6. snapshot — set to false if missing.
874
+ //
875
+ // v6.2.2 REMOVED:
876
+ // - provider.9router (was added automatically in v6.0.1–v6.2.1)
877
+ // - provider.minimax (legacy fallback)
878
+ //
879
+ // Per user request: "the installer should do nothing with providers,
880
+ // the user has to configure it themselves." The user picks their own
881
+ // provider, plugs in their API key, and configures which model catalog
882
+ // to use. The installer just sets up the Bizar scaffolding (plugin
883
+ // entry, default agent, schema, instructions, etc.) and stays out of
884
+ // provider configuration entirely.
877
885
  //
878
886
  // All patches are additive and idempotent. We never overwrite a value
879
887
  // the user has set; the `force` flag bypasses that protection for the
880
888
  // plugin entry only.
881
- let addedProvider = false;
882
889
  let addedDefaultAgent = false;
883
890
  let addedSchema = false;
884
891
  let addedInstructions = false;
885
892
  let addedPermissions = false;
886
893
  let addedSnapshot = false;
887
- let added9router = false;
888
-
889
- if (!cfg.provider) cfg.provider = {};
890
-
891
- // 1. provider.9router — preferred gateway.
892
- if (!cfg.provider['9router'] && existsSync(join(REPO_ROOT, 'config', 'cline.json'))) {
893
- try {
894
- const tpl = JSON.parse(readFileSync(join(REPO_ROOT, 'config', 'cline.json'), 'utf8'));
895
- if (tpl.provider && tpl.provider['9router']) {
896
- cfg.provider['9router'] = tpl.provider['9router'];
897
- added9router = true;
898
- }
899
- } catch { /* ignore template parse errors */ }
900
- }
901
-
902
- // 2. provider.minimax — legacy fallback.
903
- const DEFAULT_MINIMAX_BLOCK = {
904
- options: {
905
- baseURL: 'https://api.minimax.io/v1',
906
- apiKey: '{env:MiniMax_API_KEY}',
907
- },
908
- models: {
909
- 'MiniMax-M2.7-Flash': { name: 'MiniMax M2.7 Flash', interleaved: { field: 'reasoning_details' }, reasoning: true },
910
- 'MiniMax-M2.7': { name: 'MiniMax M2.7', interleaved: { field: 'reasoning_details' }, reasoning: true },
911
- 'MiniMax-M3': { name: 'MiniMax M3', interleaved: { field: 'reasoning_details' }, reasoning: true },
912
- 'MiniMax-M3-Reasoning': { name: 'MiniMax M3 Reasoning', interleaved: { field: 'reasoning_details' }, reasoning: true },
913
- },
914
- };
915
- if (!cfg.provider.minimax) {
916
- cfg.provider.minimax = DEFAULT_MINIMAX_BLOCK;
917
- addedProvider = true;
918
- }
919
894
 
920
- // 3. default_agent
895
+ // 1. default_agent
921
896
  if (!cfg.default_agent) {
922
897
  cfg.default_agent = 'odin';
923
898
  addedDefaultAgent = true;
924
899
  }
925
900
 
926
- // 4. $schema
901
+ // 2. $schema
927
902
  if (!cfg.$schema) {
928
903
  cfg.$schema = 'https://docs.cline.bot/config.json';
929
904
  addedSchema = true;
930
905
  }
931
906
 
932
- // 5. instructions — point at the bundled Bizar tools reference.
907
+ // 3. instructions — point at the bundled Bizar tools reference.
933
908
  if (!cfg.instructions || (Array.isArray(cfg.instructions) && cfg.instructions.length === 0)) {
934
909
  cfg.instructions = ['.cline/instructions/bizar-tools.md'];
935
910
  addedInstructions = true;
936
911
  }
937
912
 
938
- // 6. permission
913
+ // 4. permission
939
914
  if (!cfg.permission) {
940
915
  cfg.permission = 'allow';
941
916
  addedPermissions = true;
942
917
  }
943
918
 
944
- // 7. snapshot
919
+ // 5. snapshot
945
920
  if (typeof cfg.snapshot !== 'boolean') {
946
921
  cfg.snapshot = false;
947
922
  addedSnapshot = true;
948
923
  }
949
924
 
950
- const anyAdded = addedProvider || added9router || addedDefaultAgent || addedSchema
925
+ const anyAdded = addedDefaultAgent || addedSchema
951
926
  || addedInstructions || addedPermissions || addedSnapshot;
952
927
 
953
928
  if (hasEntry && !force && !anyAdded) {
@@ -957,8 +932,6 @@ export async function patchClineJson({ dryRun, force }) {
957
932
  if (dryRun) {
958
933
  const added = [];
959
934
  if (!hasEntry) added.push('plugin entry');
960
- if (added9router) added.push('provider.9router');
961
- if (addedProvider) added.push('provider.minimax');
962
935
  if (addedDefaultAgent) added.push('default_agent');
963
936
  if (addedSchema) added.push('$schema');
964
937
  if (addedInstructions) added.push('instructions');
@@ -988,8 +961,6 @@ export async function patchClineJson({ dryRun, force }) {
988
961
  writeFileSync(cfgPath, JSON.stringify(cfg, null, 2) + '\n');
989
962
  const added = [];
990
963
  if (!hasEntry) added.push('plugin entry');
991
- if (added9router) added.push('provider.9router');
992
- if (addedProvider) added.push('provider.minimax');
993
964
  if (addedDefaultAgent) added.push('default_agent');
994
965
  if (addedSchema) added.push('$schema');
995
966
  if (addedInstructions) added.push('instructions');
@@ -1278,12 +1249,47 @@ export async function syncConfigExtras({ dryRun }) {
1278
1249
  }
1279
1250
 
1280
1251
  // ── Hooks ────────────────────────────────────────────────────
1252
+ // v6.2.1 — Cline hooks are real executable scripts (PreToolUse,
1253
+ // PostToolUse, TaskStart, TaskResume, UserPromptSubmit). They live in
1254
+ // `~/.cline/hooks/` AND `~/Documents/Cline/Hooks/`. Cline only loads
1255
+ // hooks from the second path (the first is for additional runtime
1256
+ // hook injection via `--hooks-dir`), but we install to BOTH so:
1257
+ // 1. `bizar validate` can verify the hooks are on disk.
1258
+ // 2. Power users who pass `--hooks-dir ~/.cline/hooks` get them.
1259
+ // 3. The official `~/Documents/Cline/Hooks/` location is canonical
1260
+ // and works without any extra config.
1261
+ //
1262
+ // Hooks must be `chmod +x` executable (Cline silently skips
1263
+ // non-executable hook files per the Cline hooks contract).
1281
1264
  const hooksSrc = join(REPO_ROOT, 'config', 'hooks');
1282
1265
  if (existsSync(hooksSrc)) {
1283
- const hooksDst = join(CLINE_DIR, 'hooks');
1284
- mkdirSync(hooksDst, { recursive: true });
1285
- await copyDirIfExists(hooksSrc, hooksDst);
1286
- counts.hooks = 1;
1266
+ const hookEntries = readdirSync(hooksSrc, { withFileTypes: true });
1267
+ const hookFiles = hookEntries
1268
+ .filter((e) => e.isFile() && !e.name.endsWith('.md') && !e.name.endsWith('.txt'))
1269
+ .map((e) => e.name);
1270
+
1271
+ // Install to ~/.cline/hooks/ (used by --hooks-dir override)
1272
+ const hooksDst1 = join(CLINE_DIR, 'hooks');
1273
+ mkdirSync(hooksDst1, { recursive: true });
1274
+ for (const hookFile of hookFiles) {
1275
+ const src = join(hooksSrc, hookFile);
1276
+ const dst = join(hooksDst1, hookFile);
1277
+ copyFileSync(src, dst);
1278
+ try { chmodSync(dst, 0o755); } catch { /* best-effort */ }
1279
+ }
1280
+
1281
+ // Also install to the canonical location: ~/Documents/Cline/Hooks/
1282
+ // (Cline's default global hooks directory per the official docs)
1283
+ const hooksDst2 = join(HOME, 'Documents', 'Cline', 'Hooks');
1284
+ mkdirSync(hooksDst2, { recursive: true });
1285
+ for (const hookFile of hookFiles) {
1286
+ const src = join(hooksSrc, hookFile);
1287
+ const dst = join(hooksDst2, hookFile);
1288
+ copyFileSync(src, dst);
1289
+ try { chmodSync(dst, 0o755); } catch { /* best-effort */ }
1290
+ }
1291
+
1292
+ counts.hooks = hookFiles.length;
1287
1293
  }
1288
1294
 
1289
1295
  // ── Rules ────────────────────────────────────────────────────
@@ -1938,29 +1944,33 @@ export async function runProvision(opts = {}) {
1938
1944
  console.log(chalk.green(`\n ✓ ${mode === 'update' ? 'Update' : 'Install'} complete\n`));
1939
1945
  }
1940
1946
 
1941
- // ── 13. API key bootstrap warning ────────────────────────────────────
1942
- // v5.xAfter a successful install, check whether any API keys are
1943
- // configured. If not, surface a prominent warning (but don't block —
1944
- // many users configure keys later).
1947
+ // ── 13. Provider bootstrap warning ───────────────────────────────
1948
+ // v6.2.2The installer no longer configures a provider. The user
1949
+ // must add their own. After a successful install, surface a clear
1950
+ // hint pointing them at the right places.
1945
1951
  if (mode === 'install' && !dryRun && !anyFail) {
1946
- const envJsonPath = join(BIZAR_HOME, 'env.json');
1947
- const marker = readInstallMarker();
1948
- const hasApiKeys = Boolean(
1949
- process.env.OPENAI_API_KEY ||
1950
- process.env.ANTHROPIC_API_KEY ||
1951
- process.env.MINIMAX_API_KEY ||
1952
- (existsSync(envJsonPath) && (() => {
1953
- try {
1954
- const env = JSON.parse(readFileSync(envJsonPath, 'utf8'));
1955
- return Boolean(env?.OPENAI_API_KEY || env?.ANTHROPIC_API_KEY || env?.MINIMAX_API_KEY);
1956
- } catch { return false; }
1957
- })())
1958
- );
1959
- if (!hasApiKeys) {
1960
- console.log(chalk.yellow(' ⚠ No API keys configured.'));
1961
- console.log(chalk.yellow(' Run `bizar connect` to add providers.'));
1962
- const dashPort = process.env.BIZAR_DASHBOARD_PORT || '4097';
1963
- console.log(chalk.yellow(` Or visit http://localhost:${dashPort}/connect after starting the dashboard.`));
1952
+ const cfgPath = join(CLINE_DIR, 'cline.json');
1953
+ const cfg = readJsonSafe(cfgPath, null);
1954
+ const hasProvider = cfg && cfg.provider && Object.keys(cfg.provider).length > 0;
1955
+ if (!hasProvider) {
1956
+ console.log(chalk.yellow(' ⚠ No provider configured in cline.json.'));
1957
+ console.log(chalk.yellow(' `bizar install` no longer touches provider config (v6.2.2+).'));
1958
+ console.log(chalk.yellow(' You must add one yourself — see the "Provider setup" section below.'));
1959
+ console.log('');
1960
+ console.log(chalk.cyan(' ┌─ Provider setup ─────────────────────────────────────────────┐'));
1961
+ console.log(chalk.cyan(' │ 1. Edit ~/.cline/cline.json and add a `provider` block: │'));
1962
+ console.log(chalk.cyan(' │ { "provider": { "9router": { │'));
1963
+ console.log(chalk.cyan(' │ "baseUrl": "http://localhost:20128/v1", │'));
1964
+ console.log(chalk.cyan(' │ "apiKey": "<your-key>", │'));
1965
+ console.log(chalk.cyan(' │ "models": { "minimax/MiniMax-M3": {}, │'));
1966
+ console.log(chalk.cyan(' │ "minimax/MiniMax-M2.7": {} } } } │'));
1967
+ console.log(chalk.cyan(' │ │'));
1968
+ console.log(chalk.cyan(' │ 2. Or run `bizar connect` for an interactive TUI setup. │'));
1969
+ console.log(chalk.cyan(' └──────────────────────────────────────────────────────────────┘'));
1970
+ console.log('');
1971
+ console.log(chalk.dim(' Models available at http://localhost:20128/v1/models:'));
1972
+ console.log(chalk.dim(' minimax/MiniMax-M3, minimax/MiniMax-M2.7, nvidia/minimaxai/minimax-m3,'));
1973
+ console.log(chalk.dim(' nvidia/z-ai/glm-5.2, nvidia/deepseek-ai/deepseek-v4-pro, etc.'));
1964
1974
  console.log('');
1965
1975
  }
1966
1976
  }
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Baldr — UI/UX design system specialist. Creates DESIGN.md files using Google's design.md standard. Aesthetic direction, typography, design tokens, anti-slop audits. Does not implement code.
3
3
  mode: subagent
4
- model: minimax/MiniMax-M2.7
4
+ model: minimaxcustom/MiniMax-M2.7
5
5
  color: "#ec4899"
6
6
  permission:
7
7
  read: allow
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Forseti — Audits, criticizes, and corrects implementation plans before execution. No write permissions. Review only.
3
3
  mode: subagent
4
- model: minimax/MiniMax-M3
4
+ model: minimaxcustom/MiniMax-M3
5
5
  color: "#ef4444"
6
6
  permission:
7
7
  read: allow
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Frigg — Read-only codebase Q&A. Answers questions about the project with file references, never modifies anything. Routes to no one.
3
3
  mode: subagent
4
- model: minimax/MiniMax-M2.7
4
+ model: minimaxcustom/MiniMax-M2.7
5
5
  color: "#f472b6"
6
6
  permission:
7
7
  read: allow
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Heimdall — Simple, routine, and deterministic tasks using DeepSeek. Quick edits, mechanical work, file operations. The ever-watchful guardian.
3
3
  mode: subagent
4
- model: minimax/MiniMax-M2.7
4
+ model: minimaxcustom/MiniMax-M2.7
5
5
  color: "#10b981"
6
6
  permission:
7
7
  read: allow
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Hermod — Git and GitHub operations specialist using MiniMax M2.7. The only agent allowed to perform write-level git (commit, push, merge, rebase, branch) and `gh` CLI operations.
3
3
  mode: subagent
4
- model: minimax/MiniMax-M2.7
4
+ model: minimaxcustom/MiniMax-M2.7
5
5
  color: "#f59e0b"
6
6
  permission:
7
7
  read: allow
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Mimir — Deep codebase research and exploration. Uses Semble as primary search tool. Architecture analysis, pattern discovery, documentation research, and project initialization.
3
3
  mode: subagent
4
- model: minimax/MiniMax-M2.7
4
+ model: minimaxcustom/MiniMax-M2.7
5
5
  color: "#06b6d4"
6
6
  permission:
7
7
  read: allow
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Odin — Pure router that delegates all work to subagents. Routes across Frigg (DeepSeek/Q&A), Vör (DeepSeek/clarify), Mimir (DeepSeek/research), Heimdall (DeepSeek/simple), Hermod (M2.7/git), Thor (M2.7/mid), Baldr (M2.7/design), Tyr (M3/top), Vidarr (GPT-5.5/ultra), Forseti (verifier/M3).
3
3
  mode: primary
4
- model: minimax/MiniMax-M3
4
+ model: minimaxcustom/MiniMax-M3
5
5
  color: "#6366f1"
6
6
  permission:
7
7
  task: allow
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Quick (quick) — fast single-shot tasks. No delegation, no parallel streams. Use for small edits, mechanical changes, one-shot questions. Routes to no one.
3
3
  mode: primary
4
- model: minimax/MiniMax-M2.7-Flash
4
+ model: minimaxcustom/MiniMax-M2.7-highspeed
5
5
  color: "#22d3ee"
6
6
  permission:
7
7
  read: allow
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Code search agent for exploring any codebase. Use for finding code by intent, locating implementations, understanding how something works, or discovering related code. Prefer over Bash/Read for any semantic or exploratory question.
3
3
  mode: subagent
4
- model: minimax/MiniMax-M2.7
4
+ model: minimaxcustom/MiniMax-M2.7
5
5
  color: "#64748b"
6
6
  permission:
7
7
  read: allow
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Thor — Handles medium-complexity implementation tasks using MiniMax M2.7. New features, non-trivial debugging, refactoring, code review, and writing tests.
3
3
  mode: subagent
4
- model: minimax/MiniMax-M2.7
4
+ model: minimaxcustom/MiniMax-M2.7
5
5
  color: "#a855f7"
6
6
  permission:
7
7
  read: allow
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Tyr — Handles the most complex implementation, debugging, and architectural work using MiniMax M3. Reserved for the hardest problems. Always plan-then-Forseti-gate.
3
3
  mode: subagent
4
- model: minimax/MiniMax-M3
4
+ model: minimaxcustom/MiniMax-M3
5
5
  color: "#dc2626"
6
6
  permission:
7
7
  read: allow
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Vidarr — The ultimate fallback via MiniMax M3. For the hardest problems when Tyr stalls, debugging is stuck, or novel insight is needed. Use sparingly — highest cost.
3
3
  mode: subagent
4
- model: minimax/MiniMax-M3
4
+ model: minimaxcustom/MiniMax-M3
5
5
  color: "#0ea5e9"
6
6
  permission:
7
7
  read: allow
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Vör — Asks clarifying questions for ambiguous or incomplete requests. Reads project context first, then asks one targeted, project-specific question.
3
3
  mode: subagent
4
- model: minimax/MiniMax-M2.7
4
+ model: minimaxcustom/MiniMax-M2.7
5
5
  color: "#a78bfa"
6
6
  permission:
7
7
  read: allow