@robbiesrobotics/alice-agents 1.0.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/README.md +120 -0
- package/bin/alice-install.mjs +35 -0
- package/lib/config-merger.mjs +185 -0
- package/lib/installer.mjs +233 -0
- package/lib/manifest.mjs +33 -0
- package/lib/prompter.mjs +102 -0
- package/lib/workspace-scaffolder.mjs +112 -0
- package/package.json +29 -0
- package/templates/agents.json +487 -0
- package/templates/workspaces/_shared/AGENTS-coding.md +52 -0
- package/templates/workspaces/_shared/AGENTS-orchestrator.md +45 -0
- package/templates/workspaces/_shared/AGENTS.md +50 -0
- package/templates/workspaces/_shared/FEEDBACK.md +7 -0
- package/templates/workspaces/_shared/IDENTITY.md +6 -0
- package/templates/workspaces/_shared/LEARNINGS.md +5 -0
- package/templates/workspaces/_shared/PLAYBOOK.md +7 -0
- package/templates/workspaces/_shared/SOUL-coding.md +32 -0
- package/templates/workspaces/_shared/SOUL-orchestrator.md +31 -0
- package/templates/workspaces/_shared/SOUL.md +32 -0
- package/templates/workspaces/_shared/TOOLS-coding.md +30 -0
- package/templates/workspaces/_shared/TOOLS.md +15 -0
- package/templates/workspaces/_shared/USER.md +10 -0
package/lib/prompter.mjs
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { createInterface } from 'node:readline';
|
|
2
|
+
|
|
3
|
+
// Simple readline-based prompts. Zero deps.
|
|
4
|
+
|
|
5
|
+
let rl;
|
|
6
|
+
|
|
7
|
+
function getRL() {
|
|
8
|
+
if (!rl) {
|
|
9
|
+
rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
10
|
+
}
|
|
11
|
+
return rl;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function closePrompt() {
|
|
15
|
+
if (rl) {
|
|
16
|
+
rl.close();
|
|
17
|
+
rl = null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function ask(question) {
|
|
22
|
+
return new Promise((resolve) => {
|
|
23
|
+
getRL().question(question, (answer) => resolve(answer.trim()));
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export async function confirm(message, defaultYes = true) {
|
|
28
|
+
const hint = defaultYes ? '[Y/n]' : '[y/N]';
|
|
29
|
+
const answer = await ask(`${message} ${hint} `);
|
|
30
|
+
if (!answer) return defaultYes;
|
|
31
|
+
return answer.toLowerCase().startsWith('y');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function choose(message, options) {
|
|
35
|
+
console.log(`\n${message}\n`);
|
|
36
|
+
for (let i = 0; i < options.length; i++) {
|
|
37
|
+
console.log(` ${i + 1}. ${options[i].label}`);
|
|
38
|
+
}
|
|
39
|
+
console.log();
|
|
40
|
+
const answer = await ask(`Choice [1-${options.length}]: `);
|
|
41
|
+
const idx = parseInt(answer, 10) - 1;
|
|
42
|
+
if (idx >= 0 && idx < options.length) return options[idx].value;
|
|
43
|
+
// Default to first
|
|
44
|
+
return options[0].value;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export async function input(message, defaultValue = '') {
|
|
48
|
+
const hint = defaultValue ? ` [${defaultValue}]` : '';
|
|
49
|
+
const answer = await ask(`${message}${hint}: `);
|
|
50
|
+
return answer || defaultValue;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function detectTimezone() {
|
|
54
|
+
try {
|
|
55
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
56
|
+
} catch {
|
|
57
|
+
return 'UTC';
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function detectUserName() {
|
|
62
|
+
const { env } = process;
|
|
63
|
+
return env.USER || env.USERNAME || env.LOGNAME || 'User';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function promptInstallMode() {
|
|
67
|
+
return choose('Install mode:', [
|
|
68
|
+
{ label: 'Fresh install — replace agents section (recommended for first install)', value: 'fresh' },
|
|
69
|
+
{ label: 'Merge — add A.L.I.C.E. agents alongside existing ones', value: 'merge' },
|
|
70
|
+
{ label: 'Upgrade — update product files only (preserves user customizations)', value: 'upgrade' },
|
|
71
|
+
]);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export async function promptUserInfo() {
|
|
75
|
+
const name = await input('Your name', detectUserName());
|
|
76
|
+
const tz = await input('Timezone', detectTimezone());
|
|
77
|
+
const notes = await input('Any notes about yourself (optional)', '');
|
|
78
|
+
return { name, timezone: tz, notes };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export async function promptModelPreset() {
|
|
82
|
+
return choose('Model preset:', [
|
|
83
|
+
{ label: 'Sonnet (recommended) — claude-sonnet-4-6 for all agents', value: 'sonnet' },
|
|
84
|
+
{ label: 'Opus + Sonnet — Opus for orchestrator, Sonnet for specialists', value: 'opus-sonnet' },
|
|
85
|
+
{ label: 'OpenAI — GPT-4.1 / GPT-4.1-mini', value: 'openai' },
|
|
86
|
+
{ label: 'Local (Ollama) — requires local models', value: 'local' },
|
|
87
|
+
{ label: 'Custom — specify your own model strings', value: 'custom' },
|
|
88
|
+
]);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export async function promptCustomModel() {
|
|
92
|
+
const primary = await input('Primary model (e.g., anthropic/claude-sonnet-4-6)');
|
|
93
|
+
const orchestrator = await input('Orchestrator model (or same as primary)', primary);
|
|
94
|
+
return { primary, orchestrator };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export async function promptTier() {
|
|
98
|
+
return choose('Agent tier:', [
|
|
99
|
+
{ label: 'Starter (10 agents) — core team for most workflows', value: 'starter' },
|
|
100
|
+
{ label: 'Pro (all 28 agents) — full specialist roster', value: 'pro' },
|
|
101
|
+
]);
|
|
102
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { join, dirname } from 'node:path';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const TEMPLATES_DIR = join(__dirname, '..', 'templates', 'workspaces');
|
|
8
|
+
const OPENCLAW_DIR = join(homedir(), '.openclaw');
|
|
9
|
+
|
|
10
|
+
// Product files — always overwritten on install/upgrade
|
|
11
|
+
const PRODUCT_FILES = ['SOUL.md', 'AGENTS.md', 'IDENTITY.md', 'TOOLS.md'];
|
|
12
|
+
|
|
13
|
+
// User files — only created if missing
|
|
14
|
+
const USER_FILES = ['PLAYBOOK.md', 'LEARNINGS.md', 'FEEDBACK.md', 'USER.md'];
|
|
15
|
+
|
|
16
|
+
function renderTemplate(template, vars) {
|
|
17
|
+
let result = template;
|
|
18
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
19
|
+
result = result.replaceAll(`{{${key}}}`, value);
|
|
20
|
+
}
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function loadTemplate(filename) {
|
|
25
|
+
const sharedPath = join(TEMPLATES_DIR, '_shared', filename);
|
|
26
|
+
if (existsSync(sharedPath)) {
|
|
27
|
+
return readFileSync(sharedPath, 'utf8');
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function getTemplateVariant(baseName, agent) {
|
|
33
|
+
// Check for agent-specific override first
|
|
34
|
+
const agentOverridePath = join(TEMPLATES_DIR, agent.id, baseName);
|
|
35
|
+
if (existsSync(agentOverridePath)) {
|
|
36
|
+
return readFileSync(agentOverridePath, 'utf8');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Use variant-based naming
|
|
40
|
+
if (agent.isOrchestrator) {
|
|
41
|
+
const orchestratorTemplate = loadTemplate(`${baseName.replace('.md', '')}-orchestrator.md`);
|
|
42
|
+
if (orchestratorTemplate) return orchestratorTemplate;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (agent.coding) {
|
|
46
|
+
const codingTemplate = loadTemplate(`${baseName.replace('.md', '')}-coding.md`);
|
|
47
|
+
if (codingTemplate) return codingTemplate;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Fallback to default
|
|
51
|
+
return loadTemplate(baseName);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function scaffoldWorkspace(agent, userInfo, agentCount) {
|
|
55
|
+
const workspaceDir = join(OPENCLAW_DIR, `workspace-${agent.id}`);
|
|
56
|
+
|
|
57
|
+
// Create workspace + memory dirs
|
|
58
|
+
mkdirSync(join(workspaceDir, 'memory'), { recursive: true });
|
|
59
|
+
|
|
60
|
+
const vars = {
|
|
61
|
+
userName: userInfo.name,
|
|
62
|
+
userTimezone: userInfo.timezone,
|
|
63
|
+
userNotes: userInfo.notes ? `- **Notes:** ${userInfo.notes}` : '',
|
|
64
|
+
agentName: agent.name,
|
|
65
|
+
agentDomain: agent.domain,
|
|
66
|
+
agentEmoji: agent.emoji,
|
|
67
|
+
agentDescription: agent.description,
|
|
68
|
+
agentCount: String(agentCount),
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const written = [];
|
|
72
|
+
const skipped = [];
|
|
73
|
+
|
|
74
|
+
// Product files — always overwrite
|
|
75
|
+
for (const filename of PRODUCT_FILES) {
|
|
76
|
+
const template = getTemplateVariant(filename, agent);
|
|
77
|
+
if (template) {
|
|
78
|
+
const content = renderTemplate(template, vars);
|
|
79
|
+
writeFileSync(join(workspaceDir, filename), content, 'utf8');
|
|
80
|
+
written.push(filename);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// User files — only create if missing
|
|
85
|
+
for (const filename of USER_FILES) {
|
|
86
|
+
const filePath = join(workspaceDir, filename);
|
|
87
|
+
if (!existsSync(filePath)) {
|
|
88
|
+
const template = loadTemplate(filename);
|
|
89
|
+
if (template) {
|
|
90
|
+
const content = renderTemplate(template, vars);
|
|
91
|
+
writeFileSync(filePath, content, 'utf8');
|
|
92
|
+
written.push(filename);
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
skipped.push(filename);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return { workspaceDir, written, skipped };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function scaffoldAll(agents, userInfo) {
|
|
103
|
+
const agentCount = agents.length;
|
|
104
|
+
const results = [];
|
|
105
|
+
|
|
106
|
+
for (const agent of agents) {
|
|
107
|
+
const result = scaffoldWorkspace(agent, userInfo, agentCount);
|
|
108
|
+
results.push({ agent: agent.id, ...result });
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return results;
|
|
112
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@robbiesrobotics/alice-agents",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A.L.I.C.E. — 28 AI agents for OpenClaw. One conversation, one team.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"alice-agents": "bin/alice-install.mjs"
|
|
7
|
+
},
|
|
8
|
+
"type": "module",
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=18"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"openclaw",
|
|
14
|
+
"ai-agents",
|
|
15
|
+
"multi-agent",
|
|
16
|
+
"orchestration",
|
|
17
|
+
"alice"
|
|
18
|
+
],
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"files": [
|
|
21
|
+
"bin/",
|
|
22
|
+
"lib/",
|
|
23
|
+
"templates/",
|
|
24
|
+
"README.md"
|
|
25
|
+
],
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
}
|
|
29
|
+
}
|