squads-cli 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +521 -288
- package/dist/auth-YW3UPFSB.js +23 -0
- package/dist/auth-YW3UPFSB.js.map +1 -0
- package/dist/autonomy-PSVZVX7A.js +105 -0
- package/dist/autonomy-PSVZVX7A.js.map +1 -0
- package/dist/chunk-67RO2HKR.js +174 -0
- package/dist/chunk-67RO2HKR.js.map +1 -0
- package/dist/chunk-7OCVIDC7.js +12 -0
- package/dist/chunk-7OCVIDC7.js.map +1 -0
- package/dist/chunk-BODLDQY7.js +452 -0
- package/dist/chunk-BODLDQY7.js.map +1 -0
- package/dist/chunk-EHQJHRIW.js +103 -0
- package/dist/chunk-EHQJHRIW.js.map +1 -0
- package/dist/chunk-FFFCFZ6A.js +121 -0
- package/dist/chunk-FFFCFZ6A.js.map +1 -0
- package/dist/chunk-FIWT2NMM.js +165 -0
- package/dist/chunk-FIWT2NMM.js.map +1 -0
- package/dist/chunk-HF4WR7RA.js +154 -0
- package/dist/chunk-HF4WR7RA.js.map +1 -0
- package/dist/chunk-J6QF4ZQX.js +230 -0
- package/dist/chunk-J6QF4ZQX.js.map +1 -0
- package/dist/chunk-LOA3KWYJ.js +294 -0
- package/dist/chunk-LOA3KWYJ.js.map +1 -0
- package/dist/chunk-M5FXNY6Y.js +384 -0
- package/dist/chunk-M5FXNY6Y.js.map +1 -0
- package/dist/chunk-QHNUMM4V.js +87 -0
- package/dist/chunk-QHNUMM4V.js.map +1 -0
- package/dist/chunk-QJ7C7CMB.js +223 -0
- package/dist/chunk-QJ7C7CMB.js.map +1 -0
- package/dist/chunk-RM6BWILN.js +74 -0
- package/dist/chunk-RM6BWILN.js.map +1 -0
- package/dist/chunk-TYFTF53O.js +613 -0
- package/dist/chunk-TYFTF53O.js.map +1 -0
- package/dist/chunk-TZXD6WFN.js +420 -0
- package/dist/chunk-TZXD6WFN.js.map +1 -0
- package/dist/chunk-WVOIY5GW.js +621 -0
- package/dist/chunk-WVOIY5GW.js.map +1 -0
- package/dist/chunk-Z2UKDBNL.js +162 -0
- package/dist/chunk-Z2UKDBNL.js.map +1 -0
- package/dist/chunk-ZTQ7ISUR.js +338 -0
- package/dist/chunk-ZTQ7ISUR.js.map +1 -0
- package/dist/cli.js +2483 -5902
- package/dist/cli.js.map +1 -1
- package/dist/context-GWPF4SEY.js +291 -0
- package/dist/context-GWPF4SEY.js.map +1 -0
- package/dist/context-feed-AJGVAR6H.js +394 -0
- package/dist/context-feed-AJGVAR6H.js.map +1 -0
- package/dist/cost-XBCDJ7XC.js +275 -0
- package/dist/cost-XBCDJ7XC.js.map +1 -0
- package/dist/create-BLFGG6PF.js +286 -0
- package/dist/create-BLFGG6PF.js.map +1 -0
- package/dist/dashboard-LGT2B2BL.js +951 -0
- package/dist/dashboard-LGT2B2BL.js.map +1 -0
- package/dist/dashboard-RMK2BOD2.js +794 -0
- package/dist/dashboard-RMK2BOD2.js.map +1 -0
- package/dist/doctor-XPUIIBHJ.js +374 -0
- package/dist/doctor-XPUIIBHJ.js.map +1 -0
- package/dist/env-config-SQEI3Y7Y.js +21 -0
- package/dist/env-config-SQEI3Y7Y.js.map +1 -0
- package/dist/exec-OUXM7JBF.js +223 -0
- package/dist/exec-OUXM7JBF.js.map +1 -0
- package/dist/feedback-KNAOG5QK.js +229 -0
- package/dist/feedback-KNAOG5QK.js.map +1 -0
- package/dist/github-UQTM5KMS.js +23 -0
- package/dist/github-UQTM5KMS.js.map +1 -0
- package/dist/goal-BVHV5573.js +168 -0
- package/dist/goal-BVHV5573.js.map +1 -0
- package/dist/health-4UXN44PF.js +218 -0
- package/dist/health-4UXN44PF.js.map +1 -0
- package/dist/history-ILH3SWHB.js +232 -0
- package/dist/history-ILH3SWHB.js.map +1 -0
- package/dist/index.d.ts +736 -8
- package/dist/index.js +1312 -6
- package/dist/index.js.map +1 -1
- package/dist/init-XQZ7BOGT.js +812 -0
- package/dist/init-XQZ7BOGT.js.map +1 -0
- package/dist/kpi-RQIU7WGK.js +413 -0
- package/dist/kpi-RQIU7WGK.js.map +1 -0
- package/dist/learn-OIFUVZAS.js +269 -0
- package/dist/learn-OIFUVZAS.js.map +1 -0
- package/dist/login-DXZANWZY.js +155 -0
- package/dist/login-DXZANWZY.js.map +1 -0
- package/dist/memory-T3ACCS7E.js +560 -0
- package/dist/memory-T3ACCS7E.js.map +1 -0
- package/dist/memory-VNF2VFRB.js +23 -0
- package/dist/memory-VNF2VFRB.js.map +1 -0
- package/dist/progress-DAUZMT3N.js +202 -0
- package/dist/progress-DAUZMT3N.js.map +1 -0
- package/dist/providers-3P5D2XL5.js +65 -0
- package/dist/providers-3P5D2XL5.js.map +1 -0
- package/dist/results-UECWGLTB.js +224 -0
- package/dist/results-UECWGLTB.js.map +1 -0
- package/dist/run-I6KAXU6U.js +4049 -0
- package/dist/run-I6KAXU6U.js.map +1 -0
- package/dist/session-HBU6KZOD.js +64 -0
- package/dist/session-HBU6KZOD.js.map +1 -0
- package/dist/sessions-CK25VGPL.js +333 -0
- package/dist/sessions-CK25VGPL.js.map +1 -0
- package/dist/squad-parser-DCG65BJS.js +35 -0
- package/dist/squad-parser-DCG65BJS.js.map +1 -0
- package/dist/stats-G6NAU5BD.js +334 -0
- package/dist/stats-G6NAU5BD.js.map +1 -0
- package/dist/status-AQNLDZVN.js +352 -0
- package/dist/status-AQNLDZVN.js.map +1 -0
- package/dist/sync-ZI3MHA4G.js +836 -0
- package/dist/sync-ZI3MHA4G.js.map +1 -0
- package/dist/templates/core/AGENTS.md.template +51 -0
- package/dist/templates/core/BUSINESS_BRIEF.md.template +29 -0
- package/dist/templates/core/CLAUDE.md.template +48 -0
- package/dist/templates/core/provider.yaml.template +5 -0
- package/dist/templates/first-squad/SQUAD.md.template +23 -0
- package/dist/templates/first-squad/lead.md.template +44 -0
- package/dist/templates/memory/getting-started/state.md.template +19 -0
- package/dist/templates/seed/BUSINESS_BRIEF.md.template +27 -0
- package/dist/templates/seed/CLAUDE.md.template +119 -0
- package/dist/templates/seed/README.md.template +42 -0
- package/dist/templates/seed/config/SYSTEM.md +52 -0
- package/dist/templates/seed/config/provider.yaml +4 -0
- package/dist/templates/seed/hooks/settings.json.template +31 -0
- package/dist/templates/seed/memory/company/directives.md +37 -0
- package/dist/templates/seed/memory/company/manager/state.md +16 -0
- package/dist/templates/seed/memory/engineering/issue-solver/state.md +12 -0
- package/dist/templates/seed/memory/intelligence/intel-lead/state.md +9 -0
- package/dist/templates/seed/memory/marketing/content-drafter/state.md +12 -0
- package/dist/templates/seed/memory/operations/ops-lead/state.md +12 -0
- package/dist/templates/seed/memory/product/lead/state.md +14 -0
- package/dist/templates/seed/memory/research/lead/state.md +14 -0
- package/dist/templates/seed/skills/gh/SKILL.md +57 -0
- package/dist/templates/seed/skills/squads-cli/SKILL.md +84 -0
- package/dist/templates/seed/squads/company/SQUAD.md +51 -0
- package/dist/templates/seed/squads/company/company-critic.md +49 -0
- package/dist/templates/seed/squads/company/company-eval.md +49 -0
- package/dist/templates/seed/squads/company/event-dispatcher.md +43 -0
- package/dist/templates/seed/squads/company/goal-tracker.md +43 -0
- package/dist/templates/seed/squads/company/manager.md +54 -0
- package/dist/templates/seed/squads/engineering/SQUAD.md +48 -0
- package/dist/templates/seed/squads/engineering/code-reviewer.md +57 -0
- package/dist/templates/seed/squads/engineering/issue-solver.md +58 -0
- package/dist/templates/seed/squads/engineering/test-writer.md +50 -0
- package/dist/templates/seed/squads/intelligence/SQUAD.md +38 -0
- package/dist/templates/seed/squads/intelligence/intel-critic.md +36 -0
- package/dist/templates/seed/squads/intelligence/intel-eval.md +31 -0
- package/dist/templates/seed/squads/intelligence/intel-lead.md +71 -0
- package/dist/templates/seed/squads/marketing/SQUAD.md +47 -0
- package/dist/templates/seed/squads/marketing/content-drafter.md +71 -0
- package/dist/templates/seed/squads/marketing/growth-analyst.md +49 -0
- package/dist/templates/seed/squads/marketing/social-poster.md +44 -0
- package/dist/templates/seed/squads/operations/SQUAD.md +45 -0
- package/dist/templates/seed/squads/operations/finance-tracker.md +47 -0
- package/dist/templates/seed/squads/operations/goal-tracker.md +48 -0
- package/dist/templates/seed/squads/operations/ops-lead.md +58 -0
- package/dist/templates/seed/squads/product/SQUAD.md +41 -0
- package/dist/templates/seed/squads/product/lead.md +56 -0
- package/dist/templates/seed/squads/product/scanner.md +50 -0
- package/dist/templates/seed/squads/product/worker.md +55 -0
- package/dist/templates/seed/squads/research/SQUAD.md +38 -0
- package/dist/templates/seed/squads/research/analyst.md +50 -0
- package/dist/templates/seed/squads/research/lead.md +52 -0
- package/dist/templates/seed/squads/research/synthesizer.md +59 -0
- package/dist/templates/skills/squads-learn/SKILL.md +86 -0
- package/dist/templates/skills/squads-workflow/instruction.md +70 -0
- package/dist/terminal-FBQFQTKZ.js +55 -0
- package/dist/terminal-FBQFQTKZ.js.map +1 -0
- package/dist/update-D7CGIZ3M.js +18 -0
- package/dist/update-D7CGIZ3M.js.map +1 -0
- package/dist/update-STU276HR.js +83 -0
- package/dist/update-STU276HR.js.map +1 -0
- package/package.json +31 -13
- package/templates/core/AGENTS.md.template +51 -0
- package/templates/core/BUSINESS_BRIEF.md.template +29 -0
- package/templates/core/CLAUDE.md.template +48 -0
- package/templates/core/provider.yaml.template +5 -0
- package/templates/first-squad/SQUAD.md.template +23 -0
- package/templates/first-squad/lead.md.template +44 -0
- package/templates/memory/getting-started/state.md.template +19 -0
- package/templates/seed/BUSINESS_BRIEF.md.template +27 -0
- package/templates/seed/CLAUDE.md.template +119 -0
- package/templates/seed/README.md.template +42 -0
- package/templates/seed/config/SYSTEM.md +52 -0
- package/templates/seed/config/provider.yaml +4 -0
- package/templates/seed/hooks/settings.json.template +31 -0
- package/templates/seed/memory/company/directives.md +37 -0
- package/templates/seed/memory/company/manager/state.md +16 -0
- package/templates/seed/memory/engineering/issue-solver/state.md +12 -0
- package/templates/seed/memory/intelligence/intel-lead/state.md +9 -0
- package/templates/seed/memory/marketing/content-drafter/state.md +12 -0
- package/templates/seed/memory/operations/ops-lead/state.md +12 -0
- package/templates/seed/memory/product/lead/state.md +14 -0
- package/templates/seed/memory/research/lead/state.md +14 -0
- package/templates/seed/skills/gh/SKILL.md +57 -0
- package/templates/seed/skills/squads-cli/SKILL.md +84 -0
- package/templates/seed/squads/company/SQUAD.md +51 -0
- package/templates/seed/squads/company/company-critic.md +49 -0
- package/templates/seed/squads/company/company-eval.md +49 -0
- package/templates/seed/squads/company/event-dispatcher.md +43 -0
- package/templates/seed/squads/company/goal-tracker.md +43 -0
- package/templates/seed/squads/company/manager.md +54 -0
- package/templates/seed/squads/engineering/SQUAD.md +48 -0
- package/templates/seed/squads/engineering/code-reviewer.md +57 -0
- package/templates/seed/squads/engineering/issue-solver.md +58 -0
- package/templates/seed/squads/engineering/test-writer.md +50 -0
- package/templates/seed/squads/intelligence/SQUAD.md +38 -0
- package/templates/seed/squads/intelligence/intel-critic.md +36 -0
- package/templates/seed/squads/intelligence/intel-eval.md +31 -0
- package/templates/seed/squads/intelligence/intel-lead.md +71 -0
- package/templates/seed/squads/marketing/SQUAD.md +47 -0
- package/templates/seed/squads/marketing/content-drafter.md +71 -0
- package/templates/seed/squads/marketing/growth-analyst.md +49 -0
- package/templates/seed/squads/marketing/social-poster.md +44 -0
- package/templates/seed/squads/operations/SQUAD.md +45 -0
- package/templates/seed/squads/operations/finance-tracker.md +47 -0
- package/templates/seed/squads/operations/goal-tracker.md +48 -0
- package/templates/seed/squads/operations/ops-lead.md +58 -0
- package/templates/seed/squads/product/SQUAD.md +41 -0
- package/templates/seed/squads/product/lead.md +56 -0
- package/templates/seed/squads/product/scanner.md +50 -0
- package/templates/seed/squads/product/worker.md +55 -0
- package/templates/seed/squads/research/SQUAD.md +38 -0
- package/templates/seed/squads/research/analyst.md +50 -0
- package/templates/seed/squads/research/lead.md +52 -0
- package/templates/seed/squads/research/synthesizer.md +59 -0
- package/templates/skills/squads-learn/SKILL.md +86 -0
- package/templates/skills/squads-workflow/instruction.md +70 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
appendToMemory,
|
|
4
|
+
appendToMemorySync,
|
|
5
|
+
findMemoryDir,
|
|
6
|
+
getSquadState,
|
|
7
|
+
listMemoryEntries,
|
|
8
|
+
searchMemory,
|
|
9
|
+
updateMemory,
|
|
10
|
+
updateMemorySync
|
|
11
|
+
} from "./chunk-ZTQ7ISUR.js";
|
|
12
|
+
import "./chunk-7OCVIDC7.js";
|
|
13
|
+
export {
|
|
14
|
+
appendToMemory,
|
|
15
|
+
appendToMemorySync,
|
|
16
|
+
findMemoryDir,
|
|
17
|
+
getSquadState,
|
|
18
|
+
listMemoryEntries,
|
|
19
|
+
searchMemory,
|
|
20
|
+
updateMemory,
|
|
21
|
+
updateMemorySync
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=memory-VNF2VFRB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "./chunk-TYFTF53O.js";
|
|
3
|
+
import {
|
|
4
|
+
findMemoryDir
|
|
5
|
+
} from "./chunk-ZTQ7ISUR.js";
|
|
6
|
+
import {
|
|
7
|
+
RESET,
|
|
8
|
+
bold,
|
|
9
|
+
box,
|
|
10
|
+
colors,
|
|
11
|
+
gradient,
|
|
12
|
+
icons,
|
|
13
|
+
padEnd,
|
|
14
|
+
truncate,
|
|
15
|
+
writeLine
|
|
16
|
+
} from "./chunk-M5FXNY6Y.js";
|
|
17
|
+
import "./chunk-7OCVIDC7.js";
|
|
18
|
+
|
|
19
|
+
// src/commands/progress.ts
|
|
20
|
+
import { execSync } from "child_process";
|
|
21
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
22
|
+
import { join } from "path";
|
|
23
|
+
function getTasksFilePath() {
|
|
24
|
+
const memoryDir = findMemoryDir();
|
|
25
|
+
if (!memoryDir) {
|
|
26
|
+
const cwd = process.cwd();
|
|
27
|
+
const agentsDir = join(cwd, ".agents");
|
|
28
|
+
if (!existsSync(agentsDir)) {
|
|
29
|
+
mkdirSync(agentsDir, { recursive: true });
|
|
30
|
+
}
|
|
31
|
+
return join(agentsDir, "tasks.json");
|
|
32
|
+
}
|
|
33
|
+
return join(memoryDir, "..", "tasks.json");
|
|
34
|
+
}
|
|
35
|
+
function loadTasks() {
|
|
36
|
+
const tasksPath = getTasksFilePath();
|
|
37
|
+
if (existsSync(tasksPath)) {
|
|
38
|
+
try {
|
|
39
|
+
return JSON.parse(readFileSync(tasksPath, "utf-8"));
|
|
40
|
+
} catch {
|
|
41
|
+
return { tasks: [], lastUpdated: (/* @__PURE__ */ new Date()).toISOString() };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return { tasks: [], lastUpdated: (/* @__PURE__ */ new Date()).toISOString() };
|
|
45
|
+
}
|
|
46
|
+
function saveTasks(data) {
|
|
47
|
+
const tasksPath = getTasksFilePath();
|
|
48
|
+
data.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
49
|
+
writeFileSync(tasksPath, JSON.stringify(data, null, 2));
|
|
50
|
+
}
|
|
51
|
+
function getRecentActivity() {
|
|
52
|
+
const activity = [];
|
|
53
|
+
const squadKeywords = {
|
|
54
|
+
website: ["website", "web", "homepage", "astro", "page"],
|
|
55
|
+
product: ["cli", "squads-cli", "command"],
|
|
56
|
+
research: ["research", "report", "analysis"],
|
|
57
|
+
engineering: ["infra", "engineering", "build"],
|
|
58
|
+
intelligence: ["intel", "monitor", "competitor"],
|
|
59
|
+
customer: ["lead", "customer", "outreach"],
|
|
60
|
+
finance: ["cost", "finance", "budget"],
|
|
61
|
+
company: ["company", "strategy", "mission"],
|
|
62
|
+
marketing: ["marketing", "content", "social"]
|
|
63
|
+
};
|
|
64
|
+
try {
|
|
65
|
+
const logOutput = execSync(
|
|
66
|
+
'git log --since="24 hours ago" --format="%h|%aI|%s" 2>/dev/null',
|
|
67
|
+
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
68
|
+
).trim();
|
|
69
|
+
if (!logOutput) return activity;
|
|
70
|
+
for (const line of logOutput.split("\n")) {
|
|
71
|
+
const [hash, date, ...msgParts] = line.split("|");
|
|
72
|
+
const message = msgParts.join("|");
|
|
73
|
+
if (!hash || !message) continue;
|
|
74
|
+
const msgLower = message.toLowerCase();
|
|
75
|
+
let detectedSquad = "unknown";
|
|
76
|
+
for (const [squad, keywords] of Object.entries(squadKeywords)) {
|
|
77
|
+
if (keywords.some((k) => msgLower.includes(k))) {
|
|
78
|
+
detectedSquad = squad;
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
activity.push({
|
|
83
|
+
squad: detectedSquad,
|
|
84
|
+
message,
|
|
85
|
+
hash,
|
|
86
|
+
date: date.split("T")[0]
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
} catch {
|
|
90
|
+
}
|
|
91
|
+
return activity;
|
|
92
|
+
}
|
|
93
|
+
async function progressCommand(options = {}) {
|
|
94
|
+
writeLine();
|
|
95
|
+
writeLine(` ${gradient("squads")} ${colors.dim}progress${RESET}`);
|
|
96
|
+
writeLine();
|
|
97
|
+
const tasksData = loadTasks();
|
|
98
|
+
const recentActivity = getRecentActivity();
|
|
99
|
+
const activeTasks = tasksData.tasks.filter((t) => t.status === "active");
|
|
100
|
+
const completedToday = tasksData.tasks.filter(
|
|
101
|
+
(t) => t.status === "completed" && t.completedAt?.startsWith((/* @__PURE__ */ new Date()).toISOString().split("T")[0])
|
|
102
|
+
);
|
|
103
|
+
const stats = [
|
|
104
|
+
`${colors.cyan}${activeTasks.length}${RESET} active`,
|
|
105
|
+
`${colors.green}${completedToday.length}${RESET} done today`,
|
|
106
|
+
`${colors.purple}${recentActivity.length}${RESET} commits (24h)`
|
|
107
|
+
].join(` ${colors.dim}\u2502${RESET} `);
|
|
108
|
+
writeLine(` ${stats}`);
|
|
109
|
+
writeLine();
|
|
110
|
+
if (activeTasks.length > 0) {
|
|
111
|
+
writeLine(` ${bold}Active Tasks${RESET}`);
|
|
112
|
+
writeLine();
|
|
113
|
+
for (const task of activeTasks) {
|
|
114
|
+
const elapsed = getElapsedTime(task.startedAt);
|
|
115
|
+
writeLine(` ${icons.progress} ${colors.cyan}${task.squad}${RESET} ${truncate(task.description, 45)}`);
|
|
116
|
+
writeLine(` ${colors.dim}started ${elapsed} ago${RESET}`);
|
|
117
|
+
}
|
|
118
|
+
writeLine();
|
|
119
|
+
} else {
|
|
120
|
+
writeLine(` ${colors.dim}No active tasks${RESET}`);
|
|
121
|
+
writeLine();
|
|
122
|
+
}
|
|
123
|
+
if (recentActivity.length > 0) {
|
|
124
|
+
writeLine(` ${bold}Recent Activity${RESET} ${colors.dim}(last 24h)${RESET}`);
|
|
125
|
+
writeLine();
|
|
126
|
+
const w = { squad: 12, message: 50 };
|
|
127
|
+
const tableWidth = w.squad + w.message + 4;
|
|
128
|
+
writeLine(` ${colors.purple}${box.topLeft}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.topRight}${RESET}`);
|
|
129
|
+
writeLine(` ${colors.purple}${box.vertical}${RESET} ${bold}${padEnd("SQUAD", w.squad)}${RESET}${bold}COMMIT${RESET}${" ".repeat(w.message - 6)} ${colors.purple}${box.vertical}${RESET}`);
|
|
130
|
+
writeLine(` ${colors.purple}${box.teeRight}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.teeLeft}${RESET}`);
|
|
131
|
+
const maxRows = options.verbose ? 15 : 8;
|
|
132
|
+
for (const act of recentActivity.slice(0, maxRows)) {
|
|
133
|
+
const squadColor = act.squad === "unknown" ? colors.dim : colors.cyan;
|
|
134
|
+
const row = ` ${colors.purple}${box.vertical}${RESET} ${squadColor}${padEnd(act.squad, w.squad)}${RESET}${truncate(act.message, w.message - 2)} ${colors.purple}${box.vertical}${RESET}`;
|
|
135
|
+
writeLine(row);
|
|
136
|
+
}
|
|
137
|
+
writeLine(` ${colors.purple}${box.bottomLeft}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.bottomRight}${RESET}`);
|
|
138
|
+
if (recentActivity.length > maxRows) {
|
|
139
|
+
writeLine(` ${colors.dim}+${recentActivity.length - maxRows} more commits${RESET}`);
|
|
140
|
+
}
|
|
141
|
+
writeLine();
|
|
142
|
+
}
|
|
143
|
+
if (completedToday.length > 0) {
|
|
144
|
+
writeLine(` ${bold}Completed Today${RESET}`);
|
|
145
|
+
writeLine();
|
|
146
|
+
for (const task of completedToday.slice(0, 5)) {
|
|
147
|
+
writeLine(` ${icons.success} ${colors.cyan}${task.squad}${RESET} ${truncate(task.description, 50)}`);
|
|
148
|
+
}
|
|
149
|
+
if (completedToday.length > 5) {
|
|
150
|
+
writeLine(` ${colors.dim}+${completedToday.length - 5} more${RESET}`);
|
|
151
|
+
}
|
|
152
|
+
writeLine();
|
|
153
|
+
}
|
|
154
|
+
writeLine(` ${colors.dim}$${RESET} squads results ${colors.dim}KPI goals vs actuals${RESET}`);
|
|
155
|
+
writeLine(` ${colors.dim}$${RESET} squads dash ${colors.dim}Full dashboard${RESET}`);
|
|
156
|
+
writeLine();
|
|
157
|
+
}
|
|
158
|
+
async function progressStartCommand(squad, description) {
|
|
159
|
+
const tasksData = loadTasks();
|
|
160
|
+
const id = Math.random().toString(36).substring(2, 9);
|
|
161
|
+
tasksData.tasks.push({
|
|
162
|
+
id,
|
|
163
|
+
squad,
|
|
164
|
+
description,
|
|
165
|
+
status: "active",
|
|
166
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
167
|
+
});
|
|
168
|
+
saveTasks(tasksData);
|
|
169
|
+
writeLine(` ${icons.active} Task ${colors.cyan}${id}${RESET} started for ${colors.purple}${squad}${RESET}`);
|
|
170
|
+
}
|
|
171
|
+
async function progressCompleteCommand(taskId, options = {}) {
|
|
172
|
+
const tasksData = loadTasks();
|
|
173
|
+
const task = tasksData.tasks.find((t) => t.id === taskId);
|
|
174
|
+
if (!task) {
|
|
175
|
+
writeLine(` ${icons.error} Task ${colors.red}${taskId}${RESET} not found`);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
task.status = options.failed ? "failed" : "completed";
|
|
179
|
+
task.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
180
|
+
saveTasks(tasksData);
|
|
181
|
+
const icon = options.failed ? icons.error : icons.success;
|
|
182
|
+
const status = options.failed ? "failed" : "completed";
|
|
183
|
+
writeLine(` ${icon} Task ${colors.cyan}${taskId}${RESET} ${status}`);
|
|
184
|
+
}
|
|
185
|
+
function getElapsedTime(startTime) {
|
|
186
|
+
const start = new Date(startTime).getTime();
|
|
187
|
+
const now = Date.now();
|
|
188
|
+
const diffMs = now - start;
|
|
189
|
+
const minutes = Math.floor(diffMs / 6e4);
|
|
190
|
+
const hours = Math.floor(minutes / 60);
|
|
191
|
+
const days = Math.floor(hours / 24);
|
|
192
|
+
if (days > 0) return `${days}d`;
|
|
193
|
+
if (hours > 0) return `${hours}h`;
|
|
194
|
+
if (minutes > 0) return `${minutes}m`;
|
|
195
|
+
return "<1m";
|
|
196
|
+
}
|
|
197
|
+
export {
|
|
198
|
+
progressCommand,
|
|
199
|
+
progressCompleteCommand,
|
|
200
|
+
progressStartCommand
|
|
201
|
+
};
|
|
202
|
+
//# sourceMappingURL=progress-DAUZMT3N.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/progress.ts"],"sourcesContent":["import { execSync } from 'child_process';\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';\nimport { join } from 'path';\nimport '../lib/squad-parser.js';\nimport { findMemoryDir } from '../lib/memory.js';\nimport {\n colors,\n bold,\n RESET,\n gradient,\n box,\n padEnd,\n truncate,\n icons,\n writeLine,\n} from '../lib/terminal.js';\n\ninterface TaskEntry {\n id: string;\n squad: string;\n description: string;\n status: 'active' | 'completed' | 'failed';\n startedAt: string;\n completedAt?: string;\n commits?: string[];\n}\n\ninterface TasksFile {\n tasks: TaskEntry[];\n lastUpdated: string;\n}\n\nfunction getTasksFilePath(): string {\n const memoryDir = findMemoryDir();\n if (!memoryDir) {\n const cwd = process.cwd();\n const agentsDir = join(cwd, '.agents');\n if (!existsSync(agentsDir)) {\n mkdirSync(agentsDir, { recursive: true });\n }\n return join(agentsDir, 'tasks.json');\n }\n return join(memoryDir, '..', 'tasks.json');\n}\n\nfunction loadTasks(): TasksFile {\n const tasksPath = getTasksFilePath();\n if (existsSync(tasksPath)) {\n try {\n return JSON.parse(readFileSync(tasksPath, 'utf-8'));\n } catch {\n return { tasks: [], lastUpdated: new Date().toISOString() };\n }\n }\n return { tasks: [], lastUpdated: new Date().toISOString() };\n}\n\nfunction saveTasks(data: TasksFile): void {\n const tasksPath = getTasksFilePath();\n data.lastUpdated = new Date().toISOString();\n writeFileSync(tasksPath, JSON.stringify(data, null, 2));\n}\n\n// Get recent commits to infer activity\nfunction getRecentActivity(): { squad: string; message: string; hash: string; date: string }[] {\n const activity: { squad: string; message: string; hash: string; date: string }[] = [];\n\n const squadKeywords: Record<string, string[]> = {\n website: ['website', 'web', 'homepage', 'astro', 'page'],\n product: ['cli', 'squads-cli', 'command'],\n research: ['research', 'report', 'analysis'],\n engineering: ['infra', 'engineering', 'build'],\n intelligence: ['intel', 'monitor', 'competitor'],\n customer: ['lead', 'customer', 'outreach'],\n finance: ['cost', 'finance', 'budget'],\n company: ['company', 'strategy', 'mission'],\n marketing: ['marketing', 'content', 'social'],\n };\n\n try {\n const logOutput = execSync(\n 'git log --since=\"24 hours ago\" --format=\"%h|%aI|%s\" 2>/dev/null',\n { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }\n ).trim();\n\n if (!logOutput) return activity;\n\n for (const line of logOutput.split('\\n')) {\n const [hash, date, ...msgParts] = line.split('|');\n const message = msgParts.join('|');\n if (!hash || !message) continue;\n\n // Detect squad from commit message\n const msgLower = message.toLowerCase();\n let detectedSquad = 'unknown';\n\n for (const [squad, keywords] of Object.entries(squadKeywords)) {\n if (keywords.some(k => msgLower.includes(k))) {\n detectedSquad = squad;\n break;\n }\n }\n\n activity.push({\n squad: detectedSquad,\n message,\n hash,\n date: date.split('T')[0],\n });\n }\n } catch {\n // Not in git repo\n }\n\n return activity;\n}\n\nexport async function progressCommand(options: { verbose?: boolean } = {}): Promise<void> {\n writeLine();\n writeLine(` ${gradient('squads')} ${colors.dim}progress${RESET}`);\n writeLine();\n\n const tasksData = loadTasks();\n const recentActivity = getRecentActivity();\n\n // Active tasks\n const activeTasks = tasksData.tasks.filter(t => t.status === 'active');\n const completedToday = tasksData.tasks.filter(t =>\n t.status === 'completed' &&\n t.completedAt?.startsWith(new Date().toISOString().split('T')[0])\n );\n\n // Stats row\n const stats = [\n `${colors.cyan}${activeTasks.length}${RESET} active`,\n `${colors.green}${completedToday.length}${RESET} done today`,\n `${colors.purple}${recentActivity.length}${RESET} commits (24h)`,\n ].join(` ${colors.dim}│${RESET} `);\n writeLine(` ${stats}`);\n writeLine();\n\n // Active tasks section\n if (activeTasks.length > 0) {\n writeLine(` ${bold}Active Tasks${RESET}`);\n writeLine();\n\n for (const task of activeTasks) {\n const elapsed = getElapsedTime(task.startedAt);\n writeLine(` ${icons.progress} ${colors.cyan}${task.squad}${RESET} ${truncate(task.description, 45)}`);\n writeLine(` ${colors.dim}started ${elapsed} ago${RESET}`);\n }\n writeLine();\n } else {\n writeLine(` ${colors.dim}No active tasks${RESET}`);\n writeLine();\n }\n\n // Recent activity from git\n if (recentActivity.length > 0) {\n writeLine(` ${bold}Recent Activity${RESET} ${colors.dim}(last 24h)${RESET}`);\n writeLine();\n\n const w = { squad: 12, message: 50 };\n const tableWidth = w.squad + w.message + 4;\n\n writeLine(` ${colors.purple}${box.topLeft}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.topRight}${RESET}`);\n writeLine(` ${colors.purple}${box.vertical}${RESET} ${bold}${padEnd('SQUAD', w.squad)}${RESET}${bold}COMMIT${RESET}${' '.repeat(w.message - 6)} ${colors.purple}${box.vertical}${RESET}`);\n writeLine(` ${colors.purple}${box.teeRight}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.teeLeft}${RESET}`);\n\n const maxRows = options.verbose ? 15 : 8;\n for (const act of recentActivity.slice(0, maxRows)) {\n const squadColor = act.squad === 'unknown' ? colors.dim : colors.cyan;\n const row = ` ${colors.purple}${box.vertical}${RESET} ` +\n `${squadColor}${padEnd(act.squad, w.squad)}${RESET}` +\n `${truncate(act.message, w.message - 2)}` +\n ` ${colors.purple}${box.vertical}${RESET}`;\n writeLine(row);\n }\n\n writeLine(` ${colors.purple}${box.bottomLeft}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.bottomRight}${RESET}`);\n\n if (recentActivity.length > maxRows) {\n writeLine(` ${colors.dim}+${recentActivity.length - maxRows} more commits${RESET}`);\n }\n writeLine();\n }\n\n // Completed today\n if (completedToday.length > 0) {\n writeLine(` ${bold}Completed Today${RESET}`);\n writeLine();\n for (const task of completedToday.slice(0, 5)) {\n writeLine(` ${icons.success} ${colors.cyan}${task.squad}${RESET} ${truncate(task.description, 50)}`);\n }\n if (completedToday.length > 5) {\n writeLine(` ${colors.dim}+${completedToday.length - 5} more${RESET}`);\n }\n writeLine();\n }\n\n // Commands\n writeLine(` ${colors.dim}$${RESET} squads results ${colors.dim}KPI goals vs actuals${RESET}`);\n writeLine(` ${colors.dim}$${RESET} squads dash ${colors.dim}Full dashboard${RESET}`);\n writeLine();\n}\n\n// Register a new task (called by agents)\nexport async function progressStartCommand(\n squad: string,\n description: string\n): Promise<void> {\n const tasksData = loadTasks();\n const id = Math.random().toString(36).substring(2, 9);\n\n tasksData.tasks.push({\n id,\n squad,\n description,\n status: 'active',\n startedAt: new Date().toISOString(),\n });\n\n saveTasks(tasksData);\n writeLine(` ${icons.active} Task ${colors.cyan}${id}${RESET} started for ${colors.purple}${squad}${RESET}`);\n}\n\n// Complete a task\nexport async function progressCompleteCommand(\n taskId: string,\n options: { failed?: boolean } = {}\n): Promise<void> {\n const tasksData = loadTasks();\n const task = tasksData.tasks.find(t => t.id === taskId);\n\n if (!task) {\n writeLine(` ${icons.error} Task ${colors.red}${taskId}${RESET} not found`);\n return;\n }\n\n task.status = options.failed ? 'failed' : 'completed';\n task.completedAt = new Date().toISOString();\n\n saveTasks(tasksData);\n\n const icon = options.failed ? icons.error : icons.success;\n const status = options.failed ? 'failed' : 'completed';\n writeLine(` ${icon} Task ${colors.cyan}${taskId}${RESET} ${status}`);\n}\n\nfunction getElapsedTime(startTime: string): string {\n const start = new Date(startTime).getTime();\n const now = Date.now();\n const diffMs = now - start;\n\n const minutes = Math.floor(diffMs / 60000);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (days > 0) return `${days}d`;\n if (hours > 0) return `${hours}h`;\n if (minutes > 0) return `${minutes}m`;\n return '<1m';\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
getAllCLIStatus
|
|
4
|
+
} from "./chunk-QHNUMM4V.js";
|
|
5
|
+
import {
|
|
6
|
+
Events,
|
|
7
|
+
track
|
|
8
|
+
} from "./chunk-QJ7C7CMB.js";
|
|
9
|
+
import {
|
|
10
|
+
RESET,
|
|
11
|
+
colors,
|
|
12
|
+
gradient,
|
|
13
|
+
icons,
|
|
14
|
+
writeLine
|
|
15
|
+
} from "./chunk-M5FXNY6Y.js";
|
|
16
|
+
import "./chunk-7OCVIDC7.js";
|
|
17
|
+
|
|
18
|
+
// src/commands/providers.ts
|
|
19
|
+
async function providersCommand(options = {}) {
|
|
20
|
+
const statuses = getAllCLIStatus();
|
|
21
|
+
await track(Events.CLI_PROVIDERS, {
|
|
22
|
+
available: statuses.filter((s) => s.available).length,
|
|
23
|
+
total: statuses.length
|
|
24
|
+
});
|
|
25
|
+
if (options.json) {
|
|
26
|
+
console.log(JSON.stringify(statuses, null, 2));
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
writeLine();
|
|
30
|
+
writeLine(` ${gradient("squads")} ${colors.dim}providers${RESET}`);
|
|
31
|
+
writeLine();
|
|
32
|
+
writeLine(` ${colors.dim}Provider CLI Status${RESET}`);
|
|
33
|
+
writeLine(` ${colors.dim}${"\u2500".repeat(40)}${RESET}`);
|
|
34
|
+
const ready = [];
|
|
35
|
+
const missing = [];
|
|
36
|
+
for (const status of statuses) {
|
|
37
|
+
const statusText = status.available ? `${colors.green}${icons.success} ready${RESET}` : `${colors.red}${icons.error} not installed${RESET}`;
|
|
38
|
+
const providerCol = status.displayName.padEnd(12);
|
|
39
|
+
const commandCol = status.command.padEnd(9);
|
|
40
|
+
writeLine(` ${colors.cyan}${providerCol}${RESET} ${commandCol} ${statusText}`);
|
|
41
|
+
if (status.available) {
|
|
42
|
+
ready.push(status);
|
|
43
|
+
} else {
|
|
44
|
+
missing.push(status);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
writeLine();
|
|
48
|
+
if (ready.length === statuses.length) {
|
|
49
|
+
writeLine(` ${colors.green}${icons.success}${RESET} All providers ready`);
|
|
50
|
+
} else {
|
|
51
|
+
writeLine(` ${colors.dim}${ready.length}/${statuses.length} providers available${RESET}`);
|
|
52
|
+
}
|
|
53
|
+
if (missing.length > 0) {
|
|
54
|
+
writeLine();
|
|
55
|
+
writeLine(` ${colors.dim}Install missing:${RESET}`);
|
|
56
|
+
for (const status of missing) {
|
|
57
|
+
writeLine(` ${colors.dim}$${RESET} ${status.install}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
writeLine();
|
|
61
|
+
}
|
|
62
|
+
export {
|
|
63
|
+
providersCommand
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=providers-3P5D2XL5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/providers.ts"],"sourcesContent":["/**\n * squads providers - Show available LLM CLI providers\n *\n * Lists all supported LLM CLIs and their availability status.\n * Provides install instructions for missing CLIs.\n *\n * @see specs/multi-llm.md\n */\n\nimport {\n colors,\n RESET,\n gradient,\n icons,\n writeLine,\n} from '../lib/terminal.js';\nimport { getAllCLIStatus, CLIStatus } from '../lib/llm-clis.js';\nimport { track, Events } from '../lib/telemetry.js';\n\nexport interface ProvidersOptions {\n json?: boolean;\n}\n\n/**\n * Show status of all LLM CLI providers\n */\nexport async function providersCommand(options: ProvidersOptions = {}): Promise<void> {\n const statuses = getAllCLIStatus();\n\n // Track telemetry\n await track(Events.CLI_PROVIDERS, {\n available: statuses.filter((s) => s.available).length,\n total: statuses.length,\n });\n\n // JSON output for programmatic use\n if (options.json) {\n console.log(JSON.stringify(statuses, null, 2));\n return;\n }\n\n // Pretty output\n writeLine();\n writeLine(` ${gradient('squads')} ${colors.dim}providers${RESET}`);\n writeLine();\n\n // Header\n writeLine(` ${colors.dim}Provider CLI Status${RESET}`);\n writeLine(` ${colors.dim}${'─'.repeat(40)}${RESET}`);\n\n // Provider rows\n const ready: CLIStatus[] = [];\n const missing: CLIStatus[] = [];\n\n for (const status of statuses) {\n const statusText = status.available\n ? `${colors.green}${icons.success} ready${RESET}`\n : `${colors.red}${icons.error} not installed${RESET}`;\n\n // Pad columns for alignment\n const providerCol = status.displayName.padEnd(12);\n const commandCol = status.command.padEnd(9);\n\n writeLine(` ${colors.cyan}${providerCol}${RESET} ${commandCol} ${statusText}`);\n\n if (status.available) {\n ready.push(status);\n } else {\n missing.push(status);\n }\n }\n\n writeLine();\n\n // Summary\n if (ready.length === statuses.length) {\n writeLine(` ${colors.green}${icons.success}${RESET} All providers ready`);\n } else {\n writeLine(` ${colors.dim}${ready.length}/${statuses.length} providers available${RESET}`);\n }\n\n // Install instructions for missing\n if (missing.length > 0) {\n writeLine();\n writeLine(` ${colors.dim}Install missing:${RESET}`);\n\n for (const status of missing) {\n writeLine(` ${colors.dim}$${RESET} ${status.install}`);\n }\n }\n\n writeLine();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA0BA,eAAsB,iBAAiB,UAA4B,CAAC,GAAkB;AACpF,QAAM,WAAW,gBAAgB;AAGjC,QAAM,MAAM,OAAO,eAAe;AAAA,IAChC,WAAW,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE;AAAA,IAC/C,OAAO,SAAS;AAAA,EAClB,CAAC;AAGD,MAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAC7C;AAAA,EACF;AAGA,YAAU;AACV,YAAU,KAAK,SAAS,QAAQ,CAAC,IAAI,OAAO,GAAG,YAAY,KAAK,EAAE;AAClE,YAAU;AAGV,YAAU,KAAK,OAAO,GAAG,gCAAgC,KAAK,EAAE;AAChE,YAAU,KAAK,OAAO,GAAG,GAAG,SAAI,OAAO,EAAE,CAAC,GAAG,KAAK,EAAE;AAGpD,QAAM,QAAqB,CAAC;AAC5B,QAAM,UAAuB,CAAC;AAE9B,aAAW,UAAU,UAAU;AAC7B,UAAM,aAAa,OAAO,YACtB,GAAG,OAAO,KAAK,GAAG,MAAM,OAAO,SAAS,KAAK,KAC7C,GAAG,OAAO,GAAG,GAAG,MAAM,KAAK,iBAAiB,KAAK;AAGrD,UAAM,cAAc,OAAO,YAAY,OAAO,EAAE;AAChD,UAAM,aAAa,OAAO,QAAQ,OAAO,CAAC;AAE1C,cAAU,KAAK,OAAO,IAAI,GAAG,WAAW,GAAG,KAAK,IAAI,UAAU,IAAI,UAAU,EAAE;AAE9E,QAAI,OAAO,WAAW;AACpB,YAAM,KAAK,MAAM;AAAA,IACnB,OAAO;AACL,cAAQ,KAAK,MAAM;AAAA,IACrB;AAAA,EACF;AAEA,YAAU;AAGV,MAAI,MAAM,WAAW,SAAS,QAAQ;AACpC,cAAU,KAAK,OAAO,KAAK,GAAG,MAAM,OAAO,GAAG,KAAK,sBAAsB;AAAA,EAC3E,OAAO;AACL,cAAU,KAAK,OAAO,GAAG,GAAG,MAAM,MAAM,IAAI,SAAS,MAAM,uBAAuB,KAAK,EAAE;AAAA,EAC3F;AAGA,MAAI,QAAQ,SAAS,GAAG;AACtB,cAAU;AACV,cAAU,KAAK,OAAO,GAAG,mBAAmB,KAAK,EAAE;AAEnD,eAAW,UAAU,SAAS;AAC5B,gBAAU,OAAO,OAAO,GAAG,IAAI,KAAK,IAAI,OAAO,OAAO,EAAE;AAAA,IAC1D;AAAA,EACF;AAEA,YAAU;AACZ;","names":[]}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
findSquadsDir,
|
|
4
|
+
listSquads,
|
|
5
|
+
loadSquad
|
|
6
|
+
} from "./chunk-TYFTF53O.js";
|
|
7
|
+
import {
|
|
8
|
+
RESET,
|
|
9
|
+
bold,
|
|
10
|
+
box,
|
|
11
|
+
colors,
|
|
12
|
+
gradient,
|
|
13
|
+
icons,
|
|
14
|
+
padEnd,
|
|
15
|
+
truncate,
|
|
16
|
+
writeLine
|
|
17
|
+
} from "./chunk-M5FXNY6Y.js";
|
|
18
|
+
import "./chunk-7OCVIDC7.js";
|
|
19
|
+
|
|
20
|
+
// src/commands/results.ts
|
|
21
|
+
import { execSync } from "child_process";
|
|
22
|
+
function getGitStats(days = 7) {
|
|
23
|
+
const stats = /* @__PURE__ */ new Map();
|
|
24
|
+
const squadKeywords = {
|
|
25
|
+
website: ["agents-squads-web", "website", "homepage"],
|
|
26
|
+
product: ["squads-cli", "cli"],
|
|
27
|
+
research: ["research"],
|
|
28
|
+
engineering: ["engineering", ".agents"],
|
|
29
|
+
intelligence: ["intelligence"],
|
|
30
|
+
customer: ["customer"],
|
|
31
|
+
finance: ["finance"],
|
|
32
|
+
company: ["company"],
|
|
33
|
+
marketing: ["marketing"]
|
|
34
|
+
};
|
|
35
|
+
try {
|
|
36
|
+
const logOutput = execSync(
|
|
37
|
+
`git log --since="${days} days ago" --format="%s" --name-only 2>/dev/null`,
|
|
38
|
+
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
39
|
+
).trim();
|
|
40
|
+
if (!logOutput) return stats;
|
|
41
|
+
const entries = logOutput.split("\n\n");
|
|
42
|
+
for (const entry of entries) {
|
|
43
|
+
const lines = entry.split("\n").filter((l) => l.trim());
|
|
44
|
+
if (lines.length === 0) continue;
|
|
45
|
+
const message = lines[0];
|
|
46
|
+
const files = lines.slice(1);
|
|
47
|
+
const msgLower = message.toLowerCase();
|
|
48
|
+
let detectedSquad = "other";
|
|
49
|
+
for (const [squad, keywords] of Object.entries(squadKeywords)) {
|
|
50
|
+
const inMessage = keywords.some((k) => msgLower.includes(k));
|
|
51
|
+
const inFiles = files.some(
|
|
52
|
+
(f) => keywords.some((k) => f.toLowerCase().includes(k))
|
|
53
|
+
);
|
|
54
|
+
if (inMessage || inFiles) {
|
|
55
|
+
detectedSquad = squad;
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (!stats.has(detectedSquad)) {
|
|
60
|
+
stats.set(detectedSquad, { commits: 0, files: [] });
|
|
61
|
+
}
|
|
62
|
+
const squadStats = stats.get(detectedSquad);
|
|
63
|
+
squadStats.commits++;
|
|
64
|
+
squadStats.files.push(...files);
|
|
65
|
+
}
|
|
66
|
+
} catch {
|
|
67
|
+
}
|
|
68
|
+
return stats;
|
|
69
|
+
}
|
|
70
|
+
function getGitHubStats(days = 7) {
|
|
71
|
+
const prsOpened = /* @__PURE__ */ new Map();
|
|
72
|
+
const prsMerged = /* @__PURE__ */ new Map();
|
|
73
|
+
const issuesClosed = /* @__PURE__ */ new Map();
|
|
74
|
+
try {
|
|
75
|
+
const prsOutput = execSync(
|
|
76
|
+
`gh pr list --state all --json title,createdAt,mergedAt --limit 50 2>/dev/null`,
|
|
77
|
+
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
78
|
+
);
|
|
79
|
+
const prs = JSON.parse(prsOutput || "[]");
|
|
80
|
+
const since = new Date(Date.now() - days * 24 * 60 * 60 * 1e3);
|
|
81
|
+
for (const pr of prs) {
|
|
82
|
+
const created = new Date(pr.createdAt);
|
|
83
|
+
if (created < since) continue;
|
|
84
|
+
const squad = detectSquadFromTitle(pr.title);
|
|
85
|
+
prsOpened.set(squad, (prsOpened.get(squad) || 0) + 1);
|
|
86
|
+
if (pr.mergedAt) {
|
|
87
|
+
prsMerged.set(squad, (prsMerged.get(squad) || 0) + 1);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const issuesOutput = execSync(
|
|
91
|
+
`gh issue list --state closed --json title,closedAt --limit 50 2>/dev/null`,
|
|
92
|
+
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
93
|
+
);
|
|
94
|
+
const issues = JSON.parse(issuesOutput || "[]");
|
|
95
|
+
for (const issue of issues) {
|
|
96
|
+
const closed = new Date(issue.closedAt);
|
|
97
|
+
if (closed < since) continue;
|
|
98
|
+
const squad = detectSquadFromTitle(issue.title);
|
|
99
|
+
issuesClosed.set(squad, (issuesClosed.get(squad) || 0) + 1);
|
|
100
|
+
}
|
|
101
|
+
} catch {
|
|
102
|
+
}
|
|
103
|
+
return { prsOpened, prsMerged, issuesClosed };
|
|
104
|
+
}
|
|
105
|
+
function detectSquadFromTitle(title) {
|
|
106
|
+
const lower = title.toLowerCase();
|
|
107
|
+
const mapping = {
|
|
108
|
+
website: ["website", "web", "homepage", "page"],
|
|
109
|
+
product: ["cli", "squads", "command"],
|
|
110
|
+
research: ["research", "report"],
|
|
111
|
+
engineering: ["infra", "build", "ci"],
|
|
112
|
+
intelligence: ["intel", "monitor"],
|
|
113
|
+
customer: ["lead", "customer"],
|
|
114
|
+
finance: ["cost", "finance"],
|
|
115
|
+
marketing: ["marketing", "content"]
|
|
116
|
+
};
|
|
117
|
+
for (const [squad, keywords] of Object.entries(mapping)) {
|
|
118
|
+
if (keywords.some((k) => lower.includes(k))) {
|
|
119
|
+
return squad;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return "other";
|
|
123
|
+
}
|
|
124
|
+
function parseMetrics(goal) {
|
|
125
|
+
const metrics = [];
|
|
126
|
+
if (goal.metrics && goal.metrics.length > 0) {
|
|
127
|
+
return goal.metrics;
|
|
128
|
+
}
|
|
129
|
+
const desc = goal.description.toLowerCase();
|
|
130
|
+
if (desc.includes("revenue")) metrics.push("revenue_usd");
|
|
131
|
+
if (desc.includes("lead")) metrics.push("leads_count");
|
|
132
|
+
if (desc.includes("traffic") || desc.includes("visit")) metrics.push("page_views");
|
|
133
|
+
if (desc.includes("signup") || desc.includes("email")) metrics.push("signups");
|
|
134
|
+
if (desc.includes("cost")) metrics.push("cost_usd");
|
|
135
|
+
if (desc.includes("publish") || desc.includes("launch")) metrics.push("shipped");
|
|
136
|
+
if (desc.includes("demo")) metrics.push("demos_booked");
|
|
137
|
+
return metrics.length > 0 ? metrics : ["progress"];
|
|
138
|
+
}
|
|
139
|
+
async function resultsCommand(options = {}) {
|
|
140
|
+
const squadsDir = findSquadsDir();
|
|
141
|
+
if (!squadsDir) {
|
|
142
|
+
writeLine(`${colors.red}No .agents/squads directory found${RESET}`);
|
|
143
|
+
writeLine(`${colors.dim}Run \`squads init\` to create one.${RESET}`);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const days = parseInt(options.days || "7", 10);
|
|
147
|
+
writeLine();
|
|
148
|
+
writeLine(` ${gradient("squads")} ${colors.dim}results${RESET} ${colors.dim}(${days}d)${RESET}`);
|
|
149
|
+
writeLine();
|
|
150
|
+
const squadNames = options.squad ? [options.squad] : listSquads(squadsDir);
|
|
151
|
+
const gitStats = getGitStats(days);
|
|
152
|
+
const ghStats = getGitHubStats(days);
|
|
153
|
+
const results = [];
|
|
154
|
+
for (const name of squadNames) {
|
|
155
|
+
const squad = loadSquad(name);
|
|
156
|
+
if (!squad) continue;
|
|
157
|
+
const git = gitStats.get(name) || { commits: 0, files: [] };
|
|
158
|
+
const activeGoals = squad.goals.filter((g) => !g.completed);
|
|
159
|
+
results.push({
|
|
160
|
+
name,
|
|
161
|
+
commits: git.commits,
|
|
162
|
+
prsOpened: ghStats.prsOpened.get(name) || 0,
|
|
163
|
+
prsMerged: ghStats.prsMerged.get(name) || 0,
|
|
164
|
+
issuesClosed: ghStats.issuesClosed.get(name) || 0,
|
|
165
|
+
goals: activeGoals.map((g) => ({
|
|
166
|
+
description: g.description,
|
|
167
|
+
metrics: parseMetrics(g),
|
|
168
|
+
progress: g.progress,
|
|
169
|
+
completed: g.completed
|
|
170
|
+
}))
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
const totalCommits = results.reduce((sum, r) => sum + r.commits, 0);
|
|
174
|
+
const totalPRs = results.reduce((sum, r) => sum + r.prsMerged, 0);
|
|
175
|
+
const totalGoals = results.reduce((sum, r) => sum + r.goals.length, 0);
|
|
176
|
+
const stats = [
|
|
177
|
+
`${colors.cyan}${totalCommits}${RESET} commits`,
|
|
178
|
+
`${colors.green}${totalPRs}${RESET} PRs merged`,
|
|
179
|
+
`${colors.purple}${totalGoals}${RESET} active goals`
|
|
180
|
+
].join(` ${colors.dim}\u2502${RESET} `);
|
|
181
|
+
writeLine(` ${stats}`);
|
|
182
|
+
writeLine();
|
|
183
|
+
const w = { squad: 14, commits: 8, prs: 6, goals: 5, kpi: 20 };
|
|
184
|
+
const tableWidth = w.squad + w.commits + w.prs + w.goals + w.kpi + 8;
|
|
185
|
+
writeLine(` ${colors.purple}${box.topLeft}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.topRight}${RESET}`);
|
|
186
|
+
writeLine(` ${colors.purple}${box.vertical}${RESET} ${bold}${padEnd("SQUAD", w.squad)}${RESET}${bold}${padEnd("COMMITS", w.commits)}${RESET}${bold}${padEnd("PRs", w.prs)}${RESET}${bold}${padEnd("GOALS", w.goals)}${RESET}${bold}KEY METRIC${RESET} ${colors.purple}${box.vertical}${RESET}`);
|
|
187
|
+
writeLine(` ${colors.purple}${box.teeRight}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.teeLeft}${RESET}`);
|
|
188
|
+
for (const result of results) {
|
|
189
|
+
const keyMetric = result.goals.length > 0 ? result.goals[0].metrics[0] || "\u2014" : "\u2014";
|
|
190
|
+
const commitColor = result.commits > 0 ? colors.green : colors.dim;
|
|
191
|
+
const prColor = result.prsMerged > 0 ? colors.green : colors.dim;
|
|
192
|
+
const row = ` ${colors.purple}${box.vertical}${RESET} ${colors.cyan}${padEnd(result.name, w.squad)}${RESET}${commitColor}${padEnd(String(result.commits), w.commits)}${RESET}${prColor}${padEnd(String(result.prsMerged), w.prs)}${RESET}${padEnd(String(result.goals.length), w.goals)}${colors.dim}${truncate(keyMetric, w.kpi)}${RESET} ${colors.purple}${box.vertical}${RESET}`;
|
|
193
|
+
writeLine(row);
|
|
194
|
+
}
|
|
195
|
+
writeLine(` ${colors.purple}${box.bottomLeft}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.bottomRight}${RESET}`);
|
|
196
|
+
writeLine();
|
|
197
|
+
if (options.verbose || options.squad) {
|
|
198
|
+
writeLine(` ${bold}Goals & KPIs${RESET}`);
|
|
199
|
+
writeLine();
|
|
200
|
+
for (const result of results) {
|
|
201
|
+
if (result.goals.length === 0) continue;
|
|
202
|
+
writeLine(` ${colors.cyan}${result.name}${RESET}`);
|
|
203
|
+
for (const goal of result.goals) {
|
|
204
|
+
const statusIcon = goal.progress ? icons.progress : icons.empty;
|
|
205
|
+
writeLine(` ${statusIcon} ${truncate(goal.description, 55)}`);
|
|
206
|
+
if (goal.metrics.length > 0) {
|
|
207
|
+
const metricsStr = goal.metrics.map((m) => `${colors.purple}${m}${RESET}`).join(", ");
|
|
208
|
+
writeLine(` ${colors.dim}metrics:${RESET} ${metricsStr}`);
|
|
209
|
+
}
|
|
210
|
+
if (goal.progress) {
|
|
211
|
+
writeLine(` ${colors.dim}progress:${RESET} ${colors.green}${goal.progress}${RESET}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
writeLine();
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
writeLine(` ${colors.dim}$${RESET} squads results ${colors.cyan}<squad>${RESET} -v ${colors.dim}Detailed squad KPIs${RESET}`);
|
|
218
|
+
writeLine(` ${colors.dim}$${RESET} squads goal progress ${colors.dim}Update goal progress${RESET}`);
|
|
219
|
+
writeLine();
|
|
220
|
+
}
|
|
221
|
+
export {
|
|
222
|
+
resultsCommand
|
|
223
|
+
};
|
|
224
|
+
//# sourceMappingURL=results-UECWGLTB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/results.ts"],"sourcesContent":["import { execSync } from 'child_process';\nimport { findSquadsDir, listSquads, loadSquad, Goal } from '../lib/squad-parser.js';\nimport {\n colors,\n bold,\n RESET,\n gradient,\n box,\n padEnd,\n truncate,\n icons,\n writeLine,\n} from '../lib/terminal.js';\n\ninterface SquadResults {\n name: string;\n commits: number;\n prsOpened: number;\n prsMerged: number;\n issuesClosed: number;\n goals: GoalWithMetrics[];\n}\n\ninterface GoalWithMetrics {\n description: string;\n metrics: string[];\n progress?: string;\n completed: boolean;\n actual?: Record<string, number | string>;\n}\n\n// Get git stats for the past week per squad\nfunction getGitStats(days: number = 7): Map<string, { commits: number; files: string[] }> {\n const stats = new Map<string, { commits: number; files: string[] }>();\n\n const squadKeywords: Record<string, string[]> = {\n website: ['agents-squads-web', 'website', 'homepage'],\n product: ['squads-cli', 'cli'],\n research: ['research'],\n engineering: ['engineering', '.agents'],\n intelligence: ['intelligence'],\n customer: ['customer'],\n finance: ['finance'],\n company: ['company'],\n marketing: ['marketing'],\n };\n\n try {\n const logOutput = execSync(\n `git log --since=\"${days} days ago\" --format=\"%s\" --name-only 2>/dev/null`,\n { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }\n ).trim();\n\n if (!logOutput) return stats;\n\n const entries = logOutput.split('\\n\\n');\n for (const entry of entries) {\n const lines = entry.split('\\n').filter(l => l.trim());\n if (lines.length === 0) continue;\n\n const message = lines[0];\n const files = lines.slice(1);\n const msgLower = message.toLowerCase();\n\n // Detect squad\n let detectedSquad = 'other';\n for (const [squad, keywords] of Object.entries(squadKeywords)) {\n const inMessage = keywords.some(k => msgLower.includes(k));\n const inFiles = files.some(f =>\n keywords.some(k => f.toLowerCase().includes(k))\n );\n if (inMessage || inFiles) {\n detectedSquad = squad;\n break;\n }\n }\n\n if (!stats.has(detectedSquad)) {\n stats.set(detectedSquad, { commits: 0, files: [] });\n }\n const squadStats = stats.get(detectedSquad)!;\n squadStats.commits++;\n squadStats.files.push(...files);\n }\n } catch {\n // Not in git repo\n }\n\n return stats;\n}\n\n// Get GitHub stats via gh CLI\nfunction getGitHubStats(days: number = 7): {\n prsOpened: Map<string, number>;\n prsMerged: Map<string, number>;\n issuesClosed: Map<string, number>;\n} {\n const prsOpened = new Map<string, number>();\n const prsMerged = new Map<string, number>();\n const issuesClosed = new Map<string, number>();\n\n try {\n // Get PRs opened\n const prsOutput = execSync(\n `gh pr list --state all --json title,createdAt,mergedAt --limit 50 2>/dev/null`,\n { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }\n );\n const prs = JSON.parse(prsOutput || '[]');\n const since = new Date(Date.now() - days * 24 * 60 * 60 * 1000);\n\n for (const pr of prs) {\n const created = new Date(pr.createdAt);\n if (created < since) continue;\n\n const squad = detectSquadFromTitle(pr.title);\n prsOpened.set(squad, (prsOpened.get(squad) || 0) + 1);\n\n if (pr.mergedAt) {\n prsMerged.set(squad, (prsMerged.get(squad) || 0) + 1);\n }\n }\n\n // Get issues closed\n const issuesOutput = execSync(\n `gh issue list --state closed --json title,closedAt --limit 50 2>/dev/null`,\n { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }\n );\n const issues = JSON.parse(issuesOutput || '[]');\n\n for (const issue of issues) {\n const closed = new Date(issue.closedAt);\n if (closed < since) continue;\n\n const squad = detectSquadFromTitle(issue.title);\n issuesClosed.set(squad, (issuesClosed.get(squad) || 0) + 1);\n }\n } catch {\n // gh not available or not in repo\n }\n\n return { prsOpened, prsMerged, issuesClosed };\n}\n\nfunction detectSquadFromTitle(title: string): string {\n const lower = title.toLowerCase();\n const mapping: Record<string, string[]> = {\n website: ['website', 'web', 'homepage', 'page'],\n product: ['cli', 'squads', 'command'],\n research: ['research', 'report'],\n engineering: ['infra', 'build', 'ci'],\n intelligence: ['intel', 'monitor'],\n customer: ['lead', 'customer'],\n finance: ['cost', 'finance'],\n marketing: ['marketing', 'content'],\n };\n\n for (const [squad, keywords] of Object.entries(mapping)) {\n if (keywords.some(k => lower.includes(k))) {\n return squad;\n }\n }\n return 'other';\n}\n\n// Parse metrics from goal description\nfunction parseMetrics(goal: Goal): string[] {\n const metrics: string[] = [];\n\n // Check for explicit metrics in goal\n if (goal.metrics && goal.metrics.length > 0) {\n return goal.metrics;\n }\n\n // Infer from description\n const desc = goal.description.toLowerCase();\n\n if (desc.includes('revenue')) metrics.push('revenue_usd');\n if (desc.includes('lead')) metrics.push('leads_count');\n if (desc.includes('traffic') || desc.includes('visit')) metrics.push('page_views');\n if (desc.includes('signup') || desc.includes('email')) metrics.push('signups');\n if (desc.includes('cost')) metrics.push('cost_usd');\n if (desc.includes('publish') || desc.includes('launch')) metrics.push('shipped');\n if (desc.includes('demo')) metrics.push('demos_booked');\n\n return metrics.length > 0 ? metrics : ['progress'];\n}\n\nexport async function resultsCommand(options: {\n squad?: string;\n days?: string;\n verbose?: boolean;\n} = {}): Promise<void> {\n const squadsDir = findSquadsDir();\n if (!squadsDir) {\n writeLine(`${colors.red}No .agents/squads directory found${RESET}`);\n writeLine(`${colors.dim}Run \\`squads init\\` to create one.${RESET}`);\n return;\n }\n\n const days = parseInt(options.days || '7', 10);\n\n writeLine();\n writeLine(` ${gradient('squads')} ${colors.dim}results${RESET} ${colors.dim}(${days}d)${RESET}`);\n writeLine();\n\n const squadNames = options.squad ? [options.squad] : listSquads(squadsDir);\n const gitStats = getGitStats(days);\n const ghStats = getGitHubStats(days);\n\n const results: SquadResults[] = [];\n\n for (const name of squadNames) {\n const squad = loadSquad(name);\n if (!squad) continue;\n\n const git = gitStats.get(name) || { commits: 0, files: [] };\n const activeGoals = squad.goals.filter(g => !g.completed);\n\n results.push({\n name,\n commits: git.commits,\n prsOpened: ghStats.prsOpened.get(name) || 0,\n prsMerged: ghStats.prsMerged.get(name) || 0,\n issuesClosed: ghStats.issuesClosed.get(name) || 0,\n goals: activeGoals.map(g => ({\n description: g.description,\n metrics: parseMetrics(g),\n progress: g.progress,\n completed: g.completed,\n })),\n });\n }\n\n // Summary stats\n const totalCommits = results.reduce((sum, r) => sum + r.commits, 0);\n const totalPRs = results.reduce((sum, r) => sum + r.prsMerged, 0);\n const totalGoals = results.reduce((sum, r) => sum + r.goals.length, 0);\n\n const stats = [\n `${colors.cyan}${totalCommits}${RESET} commits`,\n `${colors.green}${totalPRs}${RESET} PRs merged`,\n `${colors.purple}${totalGoals}${RESET} active goals`,\n ].join(` ${colors.dim}│${RESET} `);\n writeLine(` ${stats}`);\n writeLine();\n\n // Results table\n const w = { squad: 14, commits: 8, prs: 6, goals: 5, kpi: 20 };\n const tableWidth = w.squad + w.commits + w.prs + w.goals + w.kpi + 8;\n\n writeLine(` ${colors.purple}${box.topLeft}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.topRight}${RESET}`);\n writeLine(` ${colors.purple}${box.vertical}${RESET} ` +\n `${bold}${padEnd('SQUAD', w.squad)}${RESET}` +\n `${bold}${padEnd('COMMITS', w.commits)}${RESET}` +\n `${bold}${padEnd('PRs', w.prs)}${RESET}` +\n `${bold}${padEnd('GOALS', w.goals)}${RESET}` +\n `${bold}KEY METRIC${RESET}` +\n ` ${colors.purple}${box.vertical}${RESET}`);\n writeLine(` ${colors.purple}${box.teeRight}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.teeLeft}${RESET}`);\n\n for (const result of results) {\n const keyMetric = result.goals.length > 0\n ? result.goals[0].metrics[0] || '—'\n : '—';\n\n const commitColor = result.commits > 0 ? colors.green : colors.dim;\n const prColor = result.prsMerged > 0 ? colors.green : colors.dim;\n\n const row = ` ${colors.purple}${box.vertical}${RESET} ` +\n `${colors.cyan}${padEnd(result.name, w.squad)}${RESET}` +\n `${commitColor}${padEnd(String(result.commits), w.commits)}${RESET}` +\n `${prColor}${padEnd(String(result.prsMerged), w.prs)}${RESET}` +\n `${padEnd(String(result.goals.length), w.goals)}` +\n `${colors.dim}${truncate(keyMetric, w.kpi)}${RESET}` +\n ` ${colors.purple}${box.vertical}${RESET}`;\n writeLine(row);\n }\n\n writeLine(` ${colors.purple}${box.bottomLeft}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.bottomRight}${RESET}`);\n writeLine();\n\n // Goal details with KPIs\n if (options.verbose || options.squad) {\n writeLine(` ${bold}Goals & KPIs${RESET}`);\n writeLine();\n\n for (const result of results) {\n if (result.goals.length === 0) continue;\n\n writeLine(` ${colors.cyan}${result.name}${RESET}`);\n\n for (const goal of result.goals) {\n const statusIcon = goal.progress ? icons.progress : icons.empty;\n writeLine(` ${statusIcon} ${truncate(goal.description, 55)}`);\n\n // Show metrics\n if (goal.metrics.length > 0) {\n const metricsStr = goal.metrics.map(m => `${colors.purple}${m}${RESET}`).join(', ');\n writeLine(` ${colors.dim}metrics:${RESET} ${metricsStr}`);\n }\n\n // Show progress if any\n if (goal.progress) {\n writeLine(` ${colors.dim}progress:${RESET} ${colors.green}${goal.progress}${RESET}`);\n }\n }\n writeLine();\n }\n }\n\n // Help\n writeLine(` ${colors.dim}$${RESET} squads results ${colors.cyan}<squad>${RESET} -v ${colors.dim}Detailed squad KPIs${RESET}`);\n writeLine(` ${colors.dim}$${RESET} squads goal progress ${colors.dim}Update goal progress${RESET}`);\n writeLine();\n}\n"],"mappings":"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","names":[]}
|