aether-colony 3.1.0 β†’ 3.1.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/bin/cli.js CHANGED
@@ -74,6 +74,7 @@ const HUB_SYSTEM = path.join(HUB_DIR, 'system');
74
74
  const HUB_COMMANDS_CLAUDE = path.join(HUB_DIR, 'commands', 'claude');
75
75
  const HUB_COMMANDS_OPENCODE = path.join(HUB_DIR, 'commands', 'opencode');
76
76
  const HUB_AGENTS = path.join(HUB_DIR, 'agents');
77
+ const HUB_VISUALIZATIONS = path.join(HUB_DIR, 'visualizations');
77
78
  const HUB_REGISTRY = path.join(HUB_DIR, 'registry.json');
78
79
  const HUB_VERSION = path.join(HUB_DIR, 'version.json');
79
80
 
@@ -893,6 +894,17 @@ function setupHub() {
893
894
  }
894
895
  }
895
896
 
897
+ // Sync .aether/visualizations/ -> ~/.aether/visualizations/
898
+ const visualizationsSrc = path.join(PACKAGE_DIR, '.aether', 'visualizations');
899
+ if (fs.existsSync(visualizationsSrc)) {
900
+ const result = syncDirWithCleanup(visualizationsSrc, HUB_VISUALIZATIONS);
901
+ log(` Hub visualizations: ${result.copied} files -> ${HUB_VISUALIZATIONS}`);
902
+ if (result.removed.length > 0) {
903
+ log(` Hub visualizations: removed ${result.removed.length} stale files`);
904
+ for (const f of result.removed) log(` - ${f}`);
905
+ }
906
+ }
907
+
896
908
  // Create/preserve registry.json
897
909
  if (!fs.existsSync(HUB_REGISTRY)) {
898
910
  writeJsonSync(HUB_REGISTRY, { schema_version: 1, repos: [] });
@@ -968,15 +980,18 @@ async function updateRepo(repoPath, sourceVersion, opts) {
968
980
  const systemCopied = result.sync_result?.system?.copied || 0;
969
981
  const commandsCopied = (result.sync_result?.commands?.copied || 0);
970
982
  const agentsCopied = result.sync_result?.agents?.copied || 0;
983
+ const visualizationsCopied = result.sync_result?.visualizations?.copied || 0;
971
984
 
972
985
  const systemRemoved = result.sync_result?.system?.removed?.length || 0;
973
986
  const commandsRemoved = result.sync_result?.commands?.removed?.length || 0;
974
987
  const agentsRemoved = result.sync_result?.agents?.removed?.length || 0;
988
+ const visualizationsRemoved = result.sync_result?.visualizations?.removed?.length || 0;
975
989
 
976
990
  const allRemovedFiles = [
977
991
  ...(result.sync_result?.system?.removed || []),
978
992
  ...(result.sync_result?.commands?.removed || []).map(f => `.claude/commands/ant/${f}`),
979
993
  ...(result.sync_result?.agents?.removed || []).map(f => `.opencode/agents/${f}`),
994
+ ...(result.sync_result?.visualizations?.removed || []).map(f => `.aether/visualizations/${f}`),
980
995
  ];
981
996
 
982
997
  return {
@@ -986,7 +1001,8 @@ async function updateRepo(repoPath, sourceVersion, opts) {
986
1001
  system: systemCopied,
987
1002
  commands: commandsCopied,
988
1003
  agents: agentsCopied,
989
- removed: systemRemoved + commandsRemoved + agentsRemoved,
1004
+ visualizations: visualizationsCopied,
1005
+ removed: systemRemoved + commandsRemoved + agentsRemoved + visualizationsRemoved,
990
1006
  removedFiles: allRemovedFiles,
991
1007
  stashCreated: !!transaction.checkpoint?.stashRef,
992
1008
  checkpoint_id: result.checkpoint_id,
@@ -1155,14 +1171,14 @@ program
1155
1171
  console.error(` Skipping. Use --force to stash and update.`);
1156
1172
  dirty++;
1157
1173
  } else if (result.status === 'dry-run') {
1158
- log(` Would update: ${repo.path} (${result.from} -> ${result.to}) [${result.system} system, ${result.commands} commands, ${result.agents} agents]`);
1174
+ log(` Would update: ${repo.path} (${result.from} -> ${result.to}) [${result.system} system, ${result.commands} commands, ${result.agents} agents, ${result.visualizations} visualizations]`);
1159
1175
  if (result.removed > 0) {
1160
1176
  log(` Would remove ${result.removed} stale files:`);
1161
1177
  for (const f of result.removedFiles) log(` - ${f}`);
1162
1178
  }
1163
1179
  updated++;
1164
1180
  } else if (result.status === 'updated') {
1165
- log(` ${c.success('Updated:')} ${repo.path} (${result.from} -> ${result.to}) [${result.system} system, ${result.commands} commands, ${result.agents} agents]`);
1181
+ log(` ${c.success('Updated:')} ${repo.path} (${result.from} -> ${result.to}) [${result.system} system, ${result.commands} commands, ${result.agents} agents, ${result.visualizations} visualizations]`);
1166
1182
  if (result.removed > 0) {
1167
1183
  log(` Removed ${result.removed} stale files:`);
1168
1184
  for (const f of result.removedFiles) log(` - ${f}`);
@@ -1238,7 +1254,7 @@ program
1238
1254
 
1239
1255
  if (result.status === 'dry-run') {
1240
1256
  console.log(`Would update: ${result.from} -> ${result.to}`);
1241
- console.log(` ${result.system} system files, ${result.commands} command files, ${result.agents} agent files`);
1257
+ console.log(` ${result.system} system files, ${result.commands} command files, ${result.agents} agent files, ${result.visualizations} visualization files`);
1242
1258
  if (result.removed > 0) {
1243
1259
  console.log(` Would remove ${result.removed} stale files:`);
1244
1260
  for (const f of result.removedFiles) console.log(` - ${f}`);
@@ -1248,7 +1264,7 @@ program
1248
1264
  }
1249
1265
 
1250
1266
  console.log(c.success(`Updated: ${result.from} -> ${result.to}`));
1251
- console.log(` ${result.system} system files, ${result.commands} command files, ${result.agents} agent files`);
1267
+ console.log(` ${result.system} system files, ${result.commands} command files, ${result.agents} agent files, ${result.visualizations} visualization files`);
1252
1268
  if (result.removed > 0) {
1253
1269
  console.log(` Removed ${result.removed} stale files:`);
1254
1270
  for (const f of result.removedFiles) console.log(` - ${f}`);
@@ -43,7 +43,19 @@ function loadModelProfiles(repoPath) {
43
43
  }
44
44
 
45
45
  try {
46
- return yaml.load(content);
46
+ const config = yaml.load(content);
47
+
48
+ // Substitute environment variables in proxy config
49
+ if (config.proxy) {
50
+ if (config.proxy.auth_token) {
51
+ config.proxy.auth_token = substituteEnvVars(config.proxy.auth_token);
52
+ }
53
+ if (config.proxy.endpoint) {
54
+ config.proxy.endpoint = substituteEnvVars(config.proxy.endpoint);
55
+ }
56
+ }
57
+
58
+ return config;
47
59
  } catch (error) {
48
60
  throw new ConfigurationError(
49
61
  `Invalid YAML in model profiles file: ${error.message}`,
@@ -52,6 +64,25 @@ function loadModelProfiles(repoPath) {
52
64
  }
53
65
  }
54
66
 
67
+ /**
68
+ * Substitute environment variables in a string
69
+ * Supports ${VAR} and ${VAR:-default} syntax
70
+ * @param {string} str - String with potential env vars
71
+ * @returns {string} String with env vars substituted
72
+ */
73
+ function substituteEnvVars(str) {
74
+ if (typeof str !== 'string') return str;
75
+
76
+ // Match ${VAR:-default} or ${VAR}
77
+ return str.replace(/\$\{([^}:]+)(?::-([^}]*))?\}/g, (match, varName, defaultValue) => {
78
+ const envValue = process.env[varName];
79
+ if (envValue !== undefined && envValue !== '') {
80
+ return envValue;
81
+ }
82
+ return defaultValue !== undefined ? defaultValue : '';
83
+ });
84
+ }
85
+
55
86
  /**
56
87
  * Get the assigned model for a specific caste
57
88
  * @param {object} profiles - Parsed model profiles
@@ -163,6 +163,7 @@ class UpdateTransaction {
163
163
  this.HUB_COMMANDS_CLAUDE = path.join(this.HUB_DIR, 'commands', 'claude');
164
164
  this.HUB_COMMANDS_OPENCODE = path.join(this.HUB_DIR, 'commands', 'opencode');
165
165
  this.HUB_AGENTS = path.join(this.HUB_DIR, 'agents');
166
+ this.HUB_VISUALIZATIONS = path.join(this.HUB_DIR, 'visualizations');
166
167
  this.HUB_VERSION = path.join(this.HUB_DIR, 'version.json');
167
168
  this.HUB_REGISTRY = path.join(this.HUB_DIR, 'registry.json');
168
169
 
@@ -696,6 +697,7 @@ class UpdateTransaction {
696
697
  system: { copied: 0, removed: 0, skipped: 0 },
697
698
  commands: { copied: 0, removed: 0, skipped: 0 },
698
699
  agents: { copied: 0, removed: 0, skipped: 0 },
700
+ visualizations: { copied: 0, removed: 0, skipped: 0 },
699
701
  errors: [],
700
702
  };
701
703
 
@@ -727,6 +729,12 @@ class UpdateTransaction {
727
729
  results.agents = this.syncDirWithCleanup(this.HUB_AGENTS, repoAgents, { dryRun });
728
730
  }
729
731
 
732
+ // Sync visualizations from hub
733
+ const repoVisualizations = path.join(this.repoPath, '.aether', 'visualizations');
734
+ if (fs.existsSync(this.HUB_VISUALIZATIONS)) {
735
+ results.visualizations = this.syncDirWithCleanup(this.HUB_VISUALIZATIONS, repoVisualizations, { dryRun });
736
+ }
737
+
730
738
  this.syncResult = results;
731
739
  return results;
732
740
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aether-colony",
3
- "version": "3.1.0",
3
+ "version": "3.1.1",
4
4
  "description": "Multi-agent system using ant colony intelligence for Claude Code and OpenCode β€” workers self-organize via pheromone signals",
5
5
  "bin": {
6
6
  "aether": "./bin/cli.js"
@@ -12,6 +12,7 @@
12
12
  ".opencode/agents/",
13
13
  ".opencode/opencode.json",
14
14
  "runtime/",
15
+ ".aether/visualizations/",
15
16
  "README.md",
16
17
  "LICENSE",
17
18
  "DISCLAIMER.md",
@@ -50,6 +50,106 @@ bash .aether/aether-utils.sh spawn-complete "Hammer-42" "completed" "auth module
50
50
 
51
51
  ---
52
52
 
53
+ ## Model-Aware Spawning
54
+
55
+ Aether colony workers are spawned with model-specific configurations based on their caste. This enables optimal task routing through the LiteLLM proxy.
56
+
57
+ ### How It Works
58
+
59
+ 1. **Model Assignment**: Each caste is mapped to an optimal model in `.aether/model-profiles.yaml`
60
+ 2. **Prompt Context**: Queen includes model assignment in worker's prompt via `--- MODEL CONTEXT ---` section
61
+ 3. **Worker Self-Reporting**: Workers echo their assigned model in JSON output for verification
62
+ 4. **Proxy Routing** (Optional): With LiteLLM proxy running, set `ANTHROPIC_MODEL` in parent shell for true model routing
63
+
64
+ ### Model Assignments by Caste
65
+
66
+ | Caste | Model | Purpose |
67
+ |-------|-------|---------|
68
+ | prime | glm-5 | Long-horizon coordination, strategic planning (200K context) |
69
+ | archaeologist | glm-5 | Historical pattern analysis across long timeframes |
70
+ | architect | glm-5 | Pattern synthesis, documentation coordination (200K context) |
71
+ | oracle | minimax-2.5 | Research, foresight, browse/search (76.3% BrowseComp) |
72
+ | route_setter | kimi-k2.5 | Task decomposition, structured planning (256K context) |
73
+ | builder | kimi-k2.5 | Code generation, refactoring (76.8% SWE-Bench) |
74
+ | watcher | kimi-k2.5 | Validation, testing, verification |
75
+ | scout | minimax-2.5| Research exploration, parallel sub-agent spawning |
76
+ | chaos | kimi-k2.5 | Edge case probing, resilience testing |
77
+ | colonizer | minimax-2.5| Environment setup, visual coding from screenshots |
78
+
79
+ ### Worker Model Self-Reporting
80
+
81
+ All workers must include model context in their JSON output:
82
+
83
+ ```json
84
+ {
85
+ "status": "completed",
86
+ "summary": "...",
87
+ "model_context": {
88
+ "assigned": "kimi-k2.5",
89
+ "caste": "builder",
90
+ "source": "caste-default",
91
+ "reported_at": "2026-02-15T10:30:00Z"
92
+ }
93
+ }
94
+ ```
95
+
96
+ This enables:
97
+ - **Visibility**: See which model each worker used
98
+ - **Verification**: Confirm routing is working correctly
99
+ - **Debugging**: Detect mismatches between expected and actual
100
+
101
+ ### LiteLLM Proxy Integration (Optional)
102
+
103
+ For true model routing through LiteLLM:
104
+
105
+ ```bash
106
+ # 1. Start proxy with your API keys
107
+ litellm --config proxy.yaml
108
+
109
+ # 2. In parent shell (before starting Claude Code):
110
+ export ANTHROPIC_BASE_URL=http://localhost:4000
111
+ export ANTHROPIC_AUTH_TOKEN=sk-litellm-local
112
+ export ANTHROPIC_MODEL=kimi-k2.5 # Or your preferred default
113
+
114
+ # 3. Start Claude Code - it will inherit these variables
115
+ claude
116
+ ```
117
+
118
+ **Note:** Claude Code's Task tool doesn't support explicit environment variable passing,
119
+ so proxy routing relies on parent shell inheritance. The self-reporting approach works
120
+ regardless of proxy status.
121
+
122
+ ### Available Models
123
+
124
+ - **glm-5** (via Z_AI): Powerful reasoning for complex tasks, architecture, planning
125
+ - **kimi-k2.5** (via Kimi): Fast code generation, refactoring, implementation
126
+ - **minimax-2.5** (via MiniMax): Efficient validation, research, lightweight tasks
127
+
128
+ ### Fallback Behavior
129
+
130
+ If the model profile is missing or a caste is not mapped:
131
+ - Default to `kimi-k2.5` (fastest, most cost-effective)
132
+ - Log a warning to the activity log
133
+ - Continue with worker spawn
134
+
135
+ ### Sub-Worker Spawning
136
+
137
+ When workers spawn sub-workers, they should:
138
+ 1. Check if the sub-worker's caste differs from their own
139
+ 2. If different, the sub-worker will automatically get their caste's model via the same mechanism
140
+ 3. If spawning with the same caste, the model remains the same
141
+
142
+ ### Model Context in Prompts
143
+
144
+ Worker prompts include a MODEL CONTEXT section that informs the worker about:
145
+ - Which model they are running on
146
+ - The model's strengths and optimal use cases
147
+ - Expected task complexity
148
+
149
+ This helps workers adjust their approach based on model capabilities.
150
+
151
+ ---
152
+
53
153
  ## Honest Execution Model
54
154
 
55
155
  **What the colony metaphor means:**
@@ -227,7 +327,7 @@ Actions: CREATED (path + lines), MODIFIED (path), RESEARCH (finding), SPAWN (cas
227
327
 
228
328
  ### Spawning Sub-Workers
229
329
 
230
- Workers can spawn sub-workers directly using the **Task tool** with `subagent_type="general-purpose"`.
330
+ Workers can spawn sub-workers directly using the **Task tool** with `subagent_type="general"`.
231
331
 
232
332
  **Depth-Based Behavior:**
233
333
 
@@ -278,7 +378,7 @@ bash .aether/aether-utils.sh spawn-log "{your_name}" "{child_caste}" "{child_nam
278
378
 
279
379
  **Step 4: Use Task tool**
280
380
  ```
281
- Use the Task tool with subagent_type="general-purpose":
381
+ Use the Task tool with subagent_type="general":
282
382
 
283
383
  You are {child_name}, a {emoji} {Caste} Ant in the Aether Colony at depth {your_depth + 1}.
284
384
 
@@ -366,6 +466,12 @@ Next Steps / Recommendations: {required}
366
466
 
367
467
  πŸ”¨ **Purpose:** Implement code, execute commands, and manipulate files to achieve concrete outcomes. The colony's hands -- when tasks need doing, you make them happen.
368
468
 
469
+ **Model Context:**
470
+ - Assigned model: kimi-k2.5
471
+ - Strengths: Code generation, refactoring, multimodal capabilities
472
+ - Best for: Implementation tasks, code writing, visual coding from screenshots
473
+ - Benchmark: 76.8% SWE-Bench Verified, 256K context
474
+
369
475
  **When to use:** Code implementation, file manipulation, command execution
370
476
 
371
477
  **Workflow (TDD-First):**
@@ -417,6 +523,12 @@ Fix count: {N}/3
417
523
 
418
524
  πŸ‘οΈ **Purpose:** Validate implementation, run tests, and ensure quality. The colony's guardian -- when work is done, you verify it's correct and complete. Also handles security audits, performance analysis, and test coverage.
419
525
 
526
+ **Model Context:**
527
+ - Assigned model: kimi-k2.5
528
+ - Strengths: Validation, testing, visual regression testing
529
+ - Best for: Verification, test coverage analysis, multimodal checks (screenshots)
530
+ - Context window: 256K tokens, multimodal capable
531
+
420
532
  **When to use:** Quality review, testing, validation, security/performance audits, phase completion approval
421
533
 
422
534
  **The Watcher's Iron Law:** Evidence before approval, always. No "should work" or "looks good" -- only verified claims with proof.
@@ -520,6 +632,12 @@ Recommendation: {specific fix or investigation needed}
520
632
 
521
633
  πŸ” **Purpose:** Gather information, search documentation, and retrieve context. The colony's researcher -- when the colony needs to know, you venture forth to find answers.
522
634
 
635
+ **Model Context:**
636
+ - Assigned model: kimi-k2.5
637
+ - Strengths: Parallel exploration via agent swarm (up to 100 sub-agents), broad research
638
+ - Best for: Documentation lookup, pattern discovery, wide exploration
639
+ - Benchmark: Can coordinate 1,500 simultaneous tool calls
640
+
523
641
  **When to use:** Research questions, documentation lookup, finding information, learning new domains
524
642
 
525
643
  **Workflow:**
@@ -537,6 +655,12 @@ Recommendation: {specific fix or investigation needed}
537
655
 
538
656
  πŸ—ΊοΈ **Purpose:** Explore and index codebase structure. Build semantic understanding, detect patterns, and map dependencies. The colony's explorer -- when new territory is encountered, you venture forth to understand the landscape.
539
657
 
658
+ **Model Context:**
659
+ - Assigned model: kimi-k2.5
660
+ - Strengths: Visual coding, environment setup, can turn screenshots into functional code
661
+ - Best for: Codebase mapping, dependency analysis, UI/prototype generation
662
+ - Multimodal: Can process visual inputs alongside text
663
+
540
664
  **When to use:** Codebase exploration, structure mapping, dependency analysis, pattern detection
541
665
 
542
666
  **Workflow:**
@@ -553,6 +677,12 @@ Recommendation: {specific fix or investigation needed}
553
677
 
554
678
  πŸ›οΈ **Purpose:** Synthesize knowledge, extract patterns, and coordinate documentation. The colony's wisdom -- when the colony learns, you organize and preserve that knowledge.
555
679
 
680
+ **Model Context:**
681
+ - Assigned model: glm-5
682
+ - Strengths: Long-context synthesis, pattern extraction, complex documentation
683
+ - Best for: Synthesizing knowledge, coordinating docs, pattern recognition
684
+ - Benchmark: 744B MoE, 200K context, strong execution with guidance
685
+
556
686
  **When to use:** Knowledge synthesis, pattern extraction, documentation coordination, decision organization
557
687
 
558
688
  **Workflow:**
@@ -569,6 +699,12 @@ Recommendation: {specific fix or investigation needed}
569
699
 
570
700
  πŸ“‹ **Purpose:** Create structured phase plans, break down goals into achievable tasks, and analyze dependencies. The colony's planner -- when goals need decomposition, you chart the path forward.
571
701
 
702
+ **Model Context:**
703
+ - Assigned model: kimi-k2.5
704
+ - Strengths: Structured planning, large context for understanding codebases, fast iteration
705
+ - Best for: Breaking down goals, creating phase structures, dependency analysis
706
+ - Benchmark: 256K context, 76.8% SWE-Bench, strong at structured output
707
+
572
708
  **When to use:** Planning, goal decomposition, phase structuring, dependency analysis
573
709
 
574
710
  **Planning Discipline:** See `.aether/planning.md` for full reference.
@@ -606,7 +742,15 @@ Steps:
606
742
 
607
743
  ## Prime Worker
608
744
 
609
- The **Prime Worker** is a special coordinator role at depth 1. When spawned by `/ant:build`, the Prime Worker:
745
+ πŸ›οΈ **Purpose:** Coordinate complex, multi-step colony operations. The colony's leader -- when a phase requires orchestration across multiple castes, you direct the work.
746
+
747
+ **Model Context:**
748
+ - Assigned model: glm-5
749
+ - Strengths: Long-horizon planning, strategic coordination, complex reasoning
750
+ - Best for: Multi-phase coordination, long-term task execution, complex synthesis
751
+ - Benchmark: 744B MoE (40B active), 200K context, tested on 1-year business simulations
752
+
753
+ **When spawned by `/ant:build`, the Prime Worker:**
610
754
 
611
755
  1. **Reads phase context** -- tasks, success criteria, constraints
612
756
  2. **Self-organizes** -- decides what specialists to spawn based on task analysis