aether-colony 1.1.0
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/.aether/CONTEXT.md +160 -0
- package/.aether/QUEEN.md +84 -0
- package/.aether/aether-utils.sh +7749 -0
- package/.aether/docs/QUEEN-SYSTEM.md +211 -0
- package/.aether/docs/README.md +68 -0
- package/.aether/docs/caste-system.md +48 -0
- package/.aether/docs/disciplines/DISCIPLINES.md +93 -0
- package/.aether/docs/disciplines/coding-standards.md +197 -0
- package/.aether/docs/disciplines/debugging.md +207 -0
- package/.aether/docs/disciplines/learning.md +254 -0
- package/.aether/docs/disciplines/tdd.md +257 -0
- package/.aether/docs/disciplines/verification-loop.md +167 -0
- package/.aether/docs/disciplines/verification.md +116 -0
- package/.aether/docs/error-codes.md +268 -0
- package/.aether/docs/known-issues.md +233 -0
- package/.aether/docs/pheromones.md +205 -0
- package/.aether/docs/queen-commands.md +97 -0
- package/.aether/exchange/colony-registry.xml +11 -0
- package/.aether/exchange/pheromone-xml.sh +575 -0
- package/.aether/exchange/pheromones.xml +87 -0
- package/.aether/exchange/queen-wisdom.xml +14 -0
- package/.aether/exchange/registry-xml.sh +273 -0
- package/.aether/exchange/wisdom-xml.sh +319 -0
- package/.aether/midden/approach-changes.md +5 -0
- package/.aether/midden/build-failures.md +5 -0
- package/.aether/midden/test-failures.md +5 -0
- package/.aether/model-profiles.yaml +100 -0
- package/.aether/rules/aether-colony.md +134 -0
- package/.aether/schemas/aether-types.xsd +255 -0
- package/.aether/schemas/colony-registry.xsd +309 -0
- package/.aether/schemas/example-prompt-builder.xml +234 -0
- package/.aether/schemas/pheromone.xsd +163 -0
- package/.aether/schemas/prompt.xsd +416 -0
- package/.aether/schemas/queen-wisdom.xsd +325 -0
- package/.aether/schemas/worker-priming.xsd +276 -0
- package/.aether/templates/QUEEN.md.template +79 -0
- package/.aether/templates/colony-state-reset.jq.template +22 -0
- package/.aether/templates/colony-state.template.json +35 -0
- package/.aether/templates/constraints.template.json +9 -0
- package/.aether/templates/crowned-anthill.template.md +36 -0
- package/.aether/templates/handoff-build-error.template.md +30 -0
- package/.aether/templates/handoff-build-success.template.md +39 -0
- package/.aether/templates/handoff.template.md +40 -0
- package/.aether/templates/learning-observations.template.json +6 -0
- package/.aether/templates/midden.template.json +7 -0
- package/.aether/templates/pheromones.template.json +6 -0
- package/.aether/templates/session.template.json +9 -0
- package/.aether/utils/atomic-write.sh +219 -0
- package/.aether/utils/chamber-compare.sh +193 -0
- package/.aether/utils/chamber-utils.sh +297 -0
- package/.aether/utils/colorize-log.sh +132 -0
- package/.aether/utils/error-handler.sh +212 -0
- package/.aether/utils/file-lock.sh +158 -0
- package/.aether/utils/queen-to-md.xsl +395 -0
- package/.aether/utils/semantic-cli.sh +413 -0
- package/.aether/utils/spawn-tree.sh +428 -0
- package/.aether/utils/spawn-with-model.sh +56 -0
- package/.aether/utils/state-loader.sh +215 -0
- package/.aether/utils/swarm-display.sh +268 -0
- package/.aether/utils/watch-spawn-tree.sh +253 -0
- package/.aether/utils/xml-compose.sh +253 -0
- package/.aether/utils/xml-convert.sh +273 -0
- package/.aether/utils/xml-core.sh +186 -0
- package/.aether/utils/xml-query.sh +201 -0
- package/.aether/utils/xml-utils.sh +110 -0
- package/.aether/workers.md +765 -0
- package/.claude/agents/ant/aether-ambassador.md +264 -0
- package/.claude/agents/ant/aether-archaeologist.md +322 -0
- package/.claude/agents/ant/aether-auditor.md +266 -0
- package/.claude/agents/ant/aether-builder.md +187 -0
- package/.claude/agents/ant/aether-chaos.md +268 -0
- package/.claude/agents/ant/aether-chronicler.md +304 -0
- package/.claude/agents/ant/aether-gatekeeper.md +325 -0
- package/.claude/agents/ant/aether-includer.md +373 -0
- package/.claude/agents/ant/aether-keeper.md +271 -0
- package/.claude/agents/ant/aether-measurer.md +317 -0
- package/.claude/agents/ant/aether-probe.md +210 -0
- package/.claude/agents/ant/aether-queen.md +325 -0
- package/.claude/agents/ant/aether-route-setter.md +173 -0
- package/.claude/agents/ant/aether-sage.md +353 -0
- package/.claude/agents/ant/aether-scout.md +142 -0
- package/.claude/agents/ant/aether-surveyor-disciplines.md +416 -0
- package/.claude/agents/ant/aether-surveyor-nest.md +354 -0
- package/.claude/agents/ant/aether-surveyor-pathogens.md +288 -0
- package/.claude/agents/ant/aether-surveyor-provisions.md +359 -0
- package/.claude/agents/ant/aether-tracker.md +265 -0
- package/.claude/agents/ant/aether-watcher.md +244 -0
- package/.claude/agents/ant/aether-weaver.md +247 -0
- package/.claude/commands/ant/archaeology.md +341 -0
- package/.claude/commands/ant/build.md +1160 -0
- package/.claude/commands/ant/chaos.md +349 -0
- package/.claude/commands/ant/colonize.md +270 -0
- package/.claude/commands/ant/continue.md +1070 -0
- package/.claude/commands/ant/council.md +309 -0
- package/.claude/commands/ant/dream.md +265 -0
- package/.claude/commands/ant/entomb.md +487 -0
- package/.claude/commands/ant/feedback.md +78 -0
- package/.claude/commands/ant/flag.md +139 -0
- package/.claude/commands/ant/flags.md +155 -0
- package/.claude/commands/ant/focus.md +58 -0
- package/.claude/commands/ant/help.md +122 -0
- package/.claude/commands/ant/history.md +137 -0
- package/.claude/commands/ant/init.md +409 -0
- package/.claude/commands/ant/interpret.md +267 -0
- package/.claude/commands/ant/lay-eggs.md +201 -0
- package/.claude/commands/ant/maturity.md +102 -0
- package/.claude/commands/ant/memory-details.md +77 -0
- package/.claude/commands/ant/migrate-state.md +165 -0
- package/.claude/commands/ant/oracle.md +387 -0
- package/.claude/commands/ant/organize.md +227 -0
- package/.claude/commands/ant/pause-colony.md +247 -0
- package/.claude/commands/ant/phase.md +126 -0
- package/.claude/commands/ant/plan.md +544 -0
- package/.claude/commands/ant/redirect.md +58 -0
- package/.claude/commands/ant/resume-colony.md +182 -0
- package/.claude/commands/ant/resume.md +363 -0
- package/.claude/commands/ant/seal.md +306 -0
- package/.claude/commands/ant/status.md +272 -0
- package/.claude/commands/ant/swarm.md +361 -0
- package/.claude/commands/ant/tunnels.md +425 -0
- package/.claude/commands/ant/update.md +209 -0
- package/.claude/commands/ant/verify-castes.md +95 -0
- package/.claude/commands/ant/watch.md +238 -0
- package/.opencode/agents/aether-ambassador.md +140 -0
- package/.opencode/agents/aether-archaeologist.md +108 -0
- package/.opencode/agents/aether-auditor.md +144 -0
- package/.opencode/agents/aether-builder.md +184 -0
- package/.opencode/agents/aether-chaos.md +115 -0
- package/.opencode/agents/aether-chronicler.md +122 -0
- package/.opencode/agents/aether-gatekeeper.md +116 -0
- package/.opencode/agents/aether-includer.md +117 -0
- package/.opencode/agents/aether-keeper.md +177 -0
- package/.opencode/agents/aether-measurer.md +128 -0
- package/.opencode/agents/aether-probe.md +133 -0
- package/.opencode/agents/aether-queen.md +286 -0
- package/.opencode/agents/aether-route-setter.md +130 -0
- package/.opencode/agents/aether-sage.md +106 -0
- package/.opencode/agents/aether-scout.md +101 -0
- package/.opencode/agents/aether-surveyor-disciplines.md +386 -0
- package/.opencode/agents/aether-surveyor-nest.md +324 -0
- package/.opencode/agents/aether-surveyor-pathogens.md +259 -0
- package/.opencode/agents/aether-surveyor-provisions.md +329 -0
- package/.opencode/agents/aether-tracker.md +137 -0
- package/.opencode/agents/aether-watcher.md +174 -0
- package/.opencode/agents/aether-weaver.md +130 -0
- package/.opencode/commands/ant/archaeology.md +338 -0
- package/.opencode/commands/ant/build.md +1200 -0
- package/.opencode/commands/ant/chaos.md +346 -0
- package/.opencode/commands/ant/colonize.md +202 -0
- package/.opencode/commands/ant/continue.md +938 -0
- package/.opencode/commands/ant/council.md +305 -0
- package/.opencode/commands/ant/dream.md +262 -0
- package/.opencode/commands/ant/entomb.md +367 -0
- package/.opencode/commands/ant/feedback.md +80 -0
- package/.opencode/commands/ant/flag.md +137 -0
- package/.opencode/commands/ant/flags.md +153 -0
- package/.opencode/commands/ant/focus.md +56 -0
- package/.opencode/commands/ant/help.md +124 -0
- package/.opencode/commands/ant/history.md +127 -0
- package/.opencode/commands/ant/init.md +337 -0
- package/.opencode/commands/ant/interpret.md +256 -0
- package/.opencode/commands/ant/lay-eggs.md +141 -0
- package/.opencode/commands/ant/maturity.md +92 -0
- package/.opencode/commands/ant/memory-details.md +77 -0
- package/.opencode/commands/ant/migrate-state.md +153 -0
- package/.opencode/commands/ant/oracle.md +338 -0
- package/.opencode/commands/ant/organize.md +224 -0
- package/.opencode/commands/ant/pause-colony.md +220 -0
- package/.opencode/commands/ant/phase.md +123 -0
- package/.opencode/commands/ant/plan.md +531 -0
- package/.opencode/commands/ant/redirect.md +67 -0
- package/.opencode/commands/ant/resume-colony.md +178 -0
- package/.opencode/commands/ant/resume.md +363 -0
- package/.opencode/commands/ant/seal.md +247 -0
- package/.opencode/commands/ant/status.md +272 -0
- package/.opencode/commands/ant/swarm.md +357 -0
- package/.opencode/commands/ant/tunnels.md +406 -0
- package/.opencode/commands/ant/update.md +191 -0
- package/.opencode/commands/ant/verify-castes.md +85 -0
- package/.opencode/commands/ant/watch.md +220 -0
- package/.opencode/opencode.json +3 -0
- package/CHANGELOG.md +325 -0
- package/DISCLAIMER.md +74 -0
- package/LICENSE +21 -0
- package/README.md +258 -0
- package/bin/cli.js +2436 -0
- package/bin/generate-commands.sh +291 -0
- package/bin/lib/caste-colors.js +57 -0
- package/bin/lib/colors.js +76 -0
- package/bin/lib/errors.js +255 -0
- package/bin/lib/event-types.js +190 -0
- package/bin/lib/file-lock.js +695 -0
- package/bin/lib/init.js +454 -0
- package/bin/lib/logger.js +242 -0
- package/bin/lib/model-profiles.js +445 -0
- package/bin/lib/model-verify.js +288 -0
- package/bin/lib/nestmate-loader.js +130 -0
- package/bin/lib/proxy-health.js +253 -0
- package/bin/lib/spawn-logger.js +266 -0
- package/bin/lib/state-guard.js +602 -0
- package/bin/lib/state-sync.js +516 -0
- package/bin/lib/telemetry.js +441 -0
- package/bin/lib/update-transaction.js +1454 -0
- package/bin/npx-install.js +178 -0
- package/bin/sync-to-runtime.sh +6 -0
- package/bin/validate-package.sh +88 -0
- package/package.json +70 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Spawn Logger Module
|
|
4
|
+
*
|
|
5
|
+
* Provides utilities for logging worker spawn events with model information
|
|
6
|
+
* and formatting spawn trees for display. Used by both CLI and programmatic
|
|
7
|
+
* interfaces to track which models are used for each worker spawn.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const { logActivity } = require('./logger');
|
|
13
|
+
const { recordSpawnTelemetry } = require('./telemetry');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Caste emoji mapping for display
|
|
17
|
+
*/
|
|
18
|
+
const CASTE_EMOJIS = {
|
|
19
|
+
prime: '🏛️',
|
|
20
|
+
builder: '🔨',
|
|
21
|
+
watcher: '👁️',
|
|
22
|
+
oracle: '🔮',
|
|
23
|
+
scout: '🔍',
|
|
24
|
+
chaos: '🎲',
|
|
25
|
+
architect: '📐',
|
|
26
|
+
archaeologist: '🏺',
|
|
27
|
+
colonizer: '🌱',
|
|
28
|
+
route_setter: '🎯',
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Status emoji mapping
|
|
33
|
+
*/
|
|
34
|
+
const STATUS_EMOJIS = {
|
|
35
|
+
spawned: '○',
|
|
36
|
+
completed: '✓',
|
|
37
|
+
failed: '✗',
|
|
38
|
+
blocked: '🚫',
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Log a worker spawn event with model information
|
|
43
|
+
* @param {string} repoPath - Repository root path
|
|
44
|
+
* @param {Object} spawnInfo - Spawn details
|
|
45
|
+
* @param {string} spawnInfo.parent - Parent ant name (e.g., "Queen")
|
|
46
|
+
* @param {string} spawnInfo.caste - Worker caste (e.g., "builder")
|
|
47
|
+
* @param {string} spawnInfo.child - Child ant name (e.g., "Builder-1")
|
|
48
|
+
* @param {string} spawnInfo.task - Task description
|
|
49
|
+
* @param {string} spawnInfo.model - Model used (e.g., "kimi-k2.5")
|
|
50
|
+
* @param {string} spawnInfo.status - Spawn status (default: "spawned")
|
|
51
|
+
* @param {string} spawnInfo.source - Routing source (default: "caste-default")
|
|
52
|
+
* @returns {Promise<boolean>} True if logged successfully
|
|
53
|
+
*/
|
|
54
|
+
async function logSpawn(repoPath, { parent, caste, child, task, model, status = 'spawned', source = 'caste-default' }) {
|
|
55
|
+
try {
|
|
56
|
+
const timestamp = new Date().toISOString();
|
|
57
|
+
const logLine = `${timestamp}|${parent}|${caste}|${child}|${task}|${model || 'default'}|${status}\n`;
|
|
58
|
+
|
|
59
|
+
const spawnTreePath = path.join(repoPath, '.aether', 'data', 'spawn-tree.txt');
|
|
60
|
+
|
|
61
|
+
// Ensure logs directory exists
|
|
62
|
+
const logsDir = path.dirname(spawnTreePath);
|
|
63
|
+
if (!fs.existsSync(logsDir)) {
|
|
64
|
+
fs.mkdirSync(logsDir, { recursive: true });
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Append to spawn tree log
|
|
68
|
+
fs.appendFileSync(spawnTreePath, logLine);
|
|
69
|
+
|
|
70
|
+
// Also log to activity log via logger module
|
|
71
|
+
const casteForLog = caste || 'ant';
|
|
72
|
+
const description = `${child} (${caste}): ${task} [model: ${model || 'default'}]`;
|
|
73
|
+
logActivity('SPAWN', casteForLog, description);
|
|
74
|
+
|
|
75
|
+
// Record telemetry for performance tracking
|
|
76
|
+
// Handle errors gracefully - don't fail spawn logging if telemetry fails
|
|
77
|
+
try {
|
|
78
|
+
recordSpawnTelemetry(repoPath, {
|
|
79
|
+
task: task || 'unknown',
|
|
80
|
+
caste: caste || 'unknown',
|
|
81
|
+
model: model || 'default',
|
|
82
|
+
source: source || 'caste-default',
|
|
83
|
+
timestamp
|
|
84
|
+
});
|
|
85
|
+
} catch (telemetryError) {
|
|
86
|
+
// Silent fail for telemetry errors
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return true;
|
|
90
|
+
} catch (error) {
|
|
91
|
+
// Silent fail - don't cascade errors from logging
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Parse a spawn tree line into its components
|
|
98
|
+
* @param {string} line - Raw line from spawn-tree.txt
|
|
99
|
+
* @returns {Object|null} Parsed spawn record or null if invalid
|
|
100
|
+
*/
|
|
101
|
+
function parseSpawnLine(line) {
|
|
102
|
+
const parts = line.split('|');
|
|
103
|
+
|
|
104
|
+
// Support multiple formats:
|
|
105
|
+
// New format (7 parts): timestamp|parent|caste|child|task|model|status
|
|
106
|
+
// Old format (6 parts): timestamp|parent|caste|child|task|status
|
|
107
|
+
// Complete format (3-4 parts): timestamp|ant_name|status|summary (optional)
|
|
108
|
+
|
|
109
|
+
if (parts.length === 7) {
|
|
110
|
+
// New format with model
|
|
111
|
+
return {
|
|
112
|
+
timestamp: parts[0],
|
|
113
|
+
parent: parts[1],
|
|
114
|
+
caste: parts[2],
|
|
115
|
+
child: parts[3],
|
|
116
|
+
task: parts[4],
|
|
117
|
+
model: parts[5],
|
|
118
|
+
status: parts[6],
|
|
119
|
+
};
|
|
120
|
+
} else if (parts.length === 6) {
|
|
121
|
+
// Old format without model - default to 'unknown'
|
|
122
|
+
return {
|
|
123
|
+
timestamp: parts[0],
|
|
124
|
+
parent: parts[1],
|
|
125
|
+
caste: parts[2],
|
|
126
|
+
child: parts[3],
|
|
127
|
+
task: parts[4],
|
|
128
|
+
model: 'unknown',
|
|
129
|
+
status: parts[5],
|
|
130
|
+
};
|
|
131
|
+
} else if (parts.length >= 3 && parts.length <= 4) {
|
|
132
|
+
// spawn-complete format: timestamp|ant_name|status|summary
|
|
133
|
+
// This is a completion record, treat as special case
|
|
134
|
+
return {
|
|
135
|
+
timestamp: parts[0],
|
|
136
|
+
parent: null,
|
|
137
|
+
caste: 'complete',
|
|
138
|
+
child: parts[1],
|
|
139
|
+
task: parts[3] || '',
|
|
140
|
+
model: 'n/a',
|
|
141
|
+
status: parts[2],
|
|
142
|
+
isCompletion: true,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Unrecognized format
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Format spawn tree for display
|
|
152
|
+
* @param {string} repoPath - Repository root path
|
|
153
|
+
* @returns {string} Formatted tree
|
|
154
|
+
*/
|
|
155
|
+
function formatSpawnTree(repoPath) {
|
|
156
|
+
const spawnTreePath = path.join(repoPath, '.aether', 'data', 'spawn-tree.txt');
|
|
157
|
+
|
|
158
|
+
if (!fs.existsSync(spawnTreePath)) {
|
|
159
|
+
return 'No spawn history found.';
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const content = fs.readFileSync(spawnTreePath, 'utf8').trim();
|
|
163
|
+
if (!content) {
|
|
164
|
+
return 'No spawn history found.';
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const lines = content.split('\n');
|
|
168
|
+
|
|
169
|
+
// Parse and format as tree
|
|
170
|
+
const formatted = lines.map((line) => {
|
|
171
|
+
const record = parseSpawnLine(line);
|
|
172
|
+
if (!record) {
|
|
173
|
+
return ` ? Invalid line: ${line.slice(0, 50)}`;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Handle completion records differently
|
|
177
|
+
if (record.isCompletion) {
|
|
178
|
+
const statusEmoji = STATUS_EMOJIS[record.status] || STATUS_EMOJIS.spawned;
|
|
179
|
+
return `${statusEmoji} ${record.child}: ${record.status}${record.task ? ' - ' + record.task.slice(0, 40) : ''}`;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const casteEmoji = getCasteEmoji(record.caste);
|
|
183
|
+
const statusEmoji = STATUS_EMOJIS[record.status] || STATUS_EMOJIS.spawned;
|
|
184
|
+
const modelDisplay = record.model || 'default';
|
|
185
|
+
|
|
186
|
+
return `${statusEmoji} ${record.parent} → ${casteEmoji} ${record.child} [${modelDisplay}] - ${record.task}`;
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
return formatted.join('\n');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Get spawn tree as structured data
|
|
194
|
+
* @param {string} repoPath - Repository root path
|
|
195
|
+
* @returns {Array<Object>} Array of spawn records
|
|
196
|
+
*/
|
|
197
|
+
function getSpawnTreeData(repoPath) {
|
|
198
|
+
const spawnTreePath = path.join(repoPath, '.aether', 'data', 'spawn-tree.txt');
|
|
199
|
+
|
|
200
|
+
if (!fs.existsSync(spawnTreePath)) {
|
|
201
|
+
return [];
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const content = fs.readFileSync(spawnTreePath, 'utf8').trim();
|
|
205
|
+
if (!content) {
|
|
206
|
+
return [];
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const lines = content.split('\n');
|
|
210
|
+
return lines.map(parseSpawnLine).filter(Boolean);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Get emoji for caste
|
|
215
|
+
* @param {string} caste - Caste name
|
|
216
|
+
* @returns {string} Emoji for the caste
|
|
217
|
+
*/
|
|
218
|
+
function getCasteEmoji(caste) {
|
|
219
|
+
return CASTE_EMOJIS[caste] || '🐜';
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Get spawns by parent
|
|
224
|
+
* @param {string} repoPath - Repository root path
|
|
225
|
+
* @param {string} parentName - Parent ant name to filter by
|
|
226
|
+
* @returns {Array<Object>} Array of spawn records for the parent
|
|
227
|
+
*/
|
|
228
|
+
function getSpawnsByParent(repoPath, parentName) {
|
|
229
|
+
const allSpawns = getSpawnTreeData(repoPath);
|
|
230
|
+
return allSpawns.filter((spawn) => spawn.parent === parentName);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Get spawns by caste
|
|
235
|
+
* @param {string} repoPath - Repository root path
|
|
236
|
+
* @param {string} caste - Caste to filter by
|
|
237
|
+
* @returns {Array<Object>} Array of spawn records for the caste
|
|
238
|
+
*/
|
|
239
|
+
function getSpawnsByCaste(repoPath, caste) {
|
|
240
|
+
const allSpawns = getSpawnTreeData(repoPath);
|
|
241
|
+
return allSpawns.filter((spawn) => spawn.caste === caste);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Get spawns by model
|
|
246
|
+
* @param {string} repoPath - Repository root path
|
|
247
|
+
* @param {string} model - Model to filter by
|
|
248
|
+
* @returns {Array<Object>} Array of spawn records using the model
|
|
249
|
+
*/
|
|
250
|
+
function getSpawnsByModel(repoPath, model) {
|
|
251
|
+
const allSpawns = getSpawnTreeData(repoPath);
|
|
252
|
+
return allSpawns.filter((spawn) => spawn.model === model);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
module.exports = {
|
|
256
|
+
logSpawn,
|
|
257
|
+
formatSpawnTree,
|
|
258
|
+
getSpawnTreeData,
|
|
259
|
+
getCasteEmoji,
|
|
260
|
+
parseSpawnLine,
|
|
261
|
+
getSpawnsByParent,
|
|
262
|
+
getSpawnsByCaste,
|
|
263
|
+
getSpawnsByModel,
|
|
264
|
+
CASTE_EMOJIS,
|
|
265
|
+
STATUS_EMOJIS,
|
|
266
|
+
};
|