@robbiesrobotics/alice-agents 1.2.9 → 1.3.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 +1 -1
- package/bin/.gitkeep +0 -0
- package/bin/alice-install.mjs +26 -1
- package/lib/.gitkeep +0 -0
- package/lib/doctor.mjs +202 -0
- package/lib/installer.mjs +56 -17
- package/lib/license.mjs +50 -0
- package/lib/prompter.mjs +15 -0
- package/lib/workspace-scaffolder.mjs +1 -1
- package/package.json +5 -1
- package/snapshots/.gitkeep +0 -0
- package/templates/skills/.gitkeep +0 -0
- package/templates/skills/claude-code/.gitkeep +0 -0
- package/templates/workspaces/.gitkeep +0 -0
- package/templates/workspaces/_shared/.gitkeep +0 -0
- package/templates/workspaces/_shared/AGENTS.md +9 -0
- package/templates/workspaces/_shared/MEMORY.md +22 -0
- package/tools/.gitkeep +0 -0
package/README.md
CHANGED
|
@@ -139,7 +139,7 @@ If you're already running NemoClaw, A.L.I.C.E. works out of the box — no extra
|
|
|
139
139
|
|
|
140
140
|
- [OpenClaw](https://openclaw.ai) or [NemoClaw](https://nemoclaw.com) installed and configured
|
|
141
141
|
- Node.js 18+
|
|
142
|
-
- At least one
|
|
142
|
+
- At least one model configured in OpenClaw or NemoClaw — no specific API key required. A.L.I.C.E. uses whatever you already have set up.
|
|
143
143
|
|
|
144
144
|
## License
|
|
145
145
|
|
package/bin/.gitkeep
ADDED
|
File without changes
|
package/bin/alice-install.mjs
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
3
5
|
import { runInstall, runUninstall } from '../lib/installer.mjs';
|
|
6
|
+
import { runDoctor } from '../lib/doctor.mjs';
|
|
4
7
|
|
|
5
8
|
const args = process.argv.slice(2);
|
|
6
9
|
const flags = new Set(args);
|
|
7
10
|
|
|
11
|
+
if (flags.has('--version') || flags.has('-v')) {
|
|
12
|
+
const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url)));
|
|
13
|
+
console.log(pkg.version);
|
|
14
|
+
process.exit(0);
|
|
15
|
+
}
|
|
16
|
+
|
|
8
17
|
if (flags.has('--help') || flags.has('-h')) {
|
|
9
18
|
console.log(`
|
|
10
19
|
alice-agents — A.L.I.C.E. Agent Framework Installer
|
|
@@ -12,17 +21,33 @@ if (flags.has('--help') || flags.has('-h')) {
|
|
|
12
21
|
Usage:
|
|
13
22
|
npx @robbiesrobotics/alice-agents Interactive install
|
|
14
23
|
npx @robbiesrobotics/alice-agents --yes Non-interactive install with defaults
|
|
24
|
+
npx @robbiesrobotics/alice-agents --update Non-interactive upgrade to latest agents
|
|
15
25
|
npx @robbiesrobotics/alice-agents --uninstall Remove A.L.I.C.E. agents from config
|
|
26
|
+
npx @robbiesrobotics/alice-agents --doctor Run diagnostics on your A.L.I.C.E. install
|
|
27
|
+
npx @robbiesrobotics/alice-agents --version Show version
|
|
16
28
|
npx @robbiesrobotics/alice-agents --help Show this help
|
|
17
29
|
|
|
18
30
|
Options:
|
|
19
31
|
--yes Skip prompts, use defaults (Sonnet, Starter tier)
|
|
32
|
+
--update Non-interactive upgrade (alias for --yes with upgrade mode)
|
|
20
33
|
--uninstall Remove A.L.I.C.E. agents (preserves non-ALICE agents)
|
|
34
|
+
--doctor Run diagnostics and check install health
|
|
35
|
+
--version Print package version
|
|
21
36
|
`);
|
|
22
37
|
process.exit(0);
|
|
23
38
|
}
|
|
24
39
|
|
|
25
|
-
if (flags.has('--
|
|
40
|
+
if (flags.has('--doctor')) {
|
|
41
|
+
runDoctor().then((ok) => process.exit(ok ? 0 : 1)).catch((err) => {
|
|
42
|
+
console.error(' ❌ Doctor failed:', err.message);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
});
|
|
45
|
+
} else if (flags.has('--update')) {
|
|
46
|
+
runInstall({ yes: true, modeOverride: 'upgrade' }).catch((err) => {
|
|
47
|
+
console.error(' ❌ Update failed:', err.message);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
});
|
|
50
|
+
} else if (flags.has('--uninstall')) {
|
|
26
51
|
runUninstall({ yes: flags.has('--yes') }).catch((err) => {
|
|
27
52
|
console.error(' ❌ Uninstall failed:', err.message);
|
|
28
53
|
process.exit(1);
|
package/lib/.gitkeep
ADDED
|
File without changes
|
package/lib/doctor.mjs
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
2
|
+
import { join, dirname } from 'node:path';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { execSync } from 'node:child_process';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const HOME = homedir();
|
|
9
|
+
const OPENCLAW_DIR = join(HOME, '.openclaw');
|
|
10
|
+
|
|
11
|
+
const STARTER_AGENTS = [
|
|
12
|
+
'olivia', 'dylan', 'selena', 'devon', 'quinn',
|
|
13
|
+
'felix', 'daphne', 'rowan', 'darius', 'sophie',
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
function check(label, ok, hint) {
|
|
17
|
+
const icon = ok ? '✓' : '✗';
|
|
18
|
+
console.log(` ${icon} ${label}`);
|
|
19
|
+
if (!ok && hint) console.log(` → ${hint}`);
|
|
20
|
+
return ok;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function getRuntime() {
|
|
24
|
+
try {
|
|
25
|
+
const v = execSync('nemoclaw --version', { stdio: 'pipe', encoding: 'utf8' }).trim();
|
|
26
|
+
return { name: 'NemoClaw', ok: true, version: v };
|
|
27
|
+
} catch {}
|
|
28
|
+
try {
|
|
29
|
+
const v = execSync('openclaw --version', { stdio: 'pipe', encoding: 'utf8' }).trim();
|
|
30
|
+
return { name: 'OpenClaw', ok: true, version: v };
|
|
31
|
+
} catch {}
|
|
32
|
+
return { name: 'openclaw/nemoclaw', ok: false, version: null };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function loadConfig() {
|
|
36
|
+
const configPath = join(OPENCLAW_DIR, 'openclaw.json');
|
|
37
|
+
if (!existsSync(configPath)) return null;
|
|
38
|
+
try {
|
|
39
|
+
return JSON.parse(readFileSync(configPath, 'utf8'));
|
|
40
|
+
} catch {
|
|
41
|
+
return 'invalid';
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function runDoctor() {
|
|
46
|
+
console.log('\n 🩺 A.L.I.C.E. Doctor — Diagnostic Report\n');
|
|
47
|
+
let allOk = true;
|
|
48
|
+
|
|
49
|
+
// 1. Runtime check
|
|
50
|
+
const runtime = getRuntime();
|
|
51
|
+
const runtimeOk = check(
|
|
52
|
+
runtime.ok
|
|
53
|
+
? `${runtime.name} installed (${runtime.version})`
|
|
54
|
+
: `${runtime.name} not found`,
|
|
55
|
+
runtime.ok,
|
|
56
|
+
'Install OpenClaw: npm install -g openclaw'
|
|
57
|
+
);
|
|
58
|
+
allOk = allOk && runtimeOk;
|
|
59
|
+
|
|
60
|
+
// 2. Config exists and valid JSON
|
|
61
|
+
const configPath = join(OPENCLAW_DIR, 'openclaw.json');
|
|
62
|
+
const configExists = existsSync(configPath);
|
|
63
|
+
check('openclaw.json exists', configExists, 'Run: openclaw configure');
|
|
64
|
+
|
|
65
|
+
if (!configExists) {
|
|
66
|
+
allOk = false;
|
|
67
|
+
console.log('\n ⚠️ Cannot continue checks — openclaw.json missing.\n');
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const config = loadConfig();
|
|
72
|
+
const configValid = config !== null && config !== 'invalid';
|
|
73
|
+
check(
|
|
74
|
+
'openclaw.json is valid JSON',
|
|
75
|
+
configValid,
|
|
76
|
+
`Fix JSON syntax in ${configPath}`
|
|
77
|
+
);
|
|
78
|
+
if (!configValid) {
|
|
79
|
+
allOk = false;
|
|
80
|
+
console.log('\n ⚠️ Cannot continue checks — config is invalid JSON.\n');
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// 3. A.L.I.C.E. agents in config
|
|
85
|
+
const configAgents = Array.isArray(config.agents) ? config.agents : [];
|
|
86
|
+
const agentsInConfig = configAgents
|
|
87
|
+
.filter((a) => a && STARTER_AGENTS.includes(a.id))
|
|
88
|
+
.map((a) => a.id);
|
|
89
|
+
|
|
90
|
+
const agentsOk = agentsInConfig.length > 0;
|
|
91
|
+
check(
|
|
92
|
+
agentsOk
|
|
93
|
+
? `A.L.I.C.E. agents in config: ${agentsInConfig.join(', ')}`
|
|
94
|
+
: 'No A.L.I.C.E. agents found in config',
|
|
95
|
+
agentsOk,
|
|
96
|
+
'Run: npx @robbiesrobotics/alice-agents to install'
|
|
97
|
+
);
|
|
98
|
+
allOk = allOk && agentsOk;
|
|
99
|
+
|
|
100
|
+
// Check for missing agents from full starter set
|
|
101
|
+
if (agentsInConfig.length > 0 && agentsInConfig.length < STARTER_AGENTS.length) {
|
|
102
|
+
const missing = STARTER_AGENTS.filter((id) => !agentsInConfig.includes(id));
|
|
103
|
+
check(
|
|
104
|
+
`All starter agents present (missing: ${missing.join(', ')})`,
|
|
105
|
+
false,
|
|
106
|
+
'Run: npx @robbiesrobotics/alice-agents --update'
|
|
107
|
+
);
|
|
108
|
+
allOk = false;
|
|
109
|
+
} else if (agentsInConfig.length === STARTER_AGENTS.length) {
|
|
110
|
+
check('All starter agents present', true);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// 4. Agent workspaces exist on disk
|
|
114
|
+
if (agentsInConfig.length > 0) {
|
|
115
|
+
let missingWorkspaces = [];
|
|
116
|
+
for (const id of agentsInConfig) {
|
|
117
|
+
const wsDir = join(OPENCLAW_DIR, `workspace-${id}`);
|
|
118
|
+
if (!existsSync(wsDir)) {
|
|
119
|
+
missingWorkspaces.push(id);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const workspacesOk = missingWorkspaces.length === 0;
|
|
123
|
+
check(
|
|
124
|
+
workspacesOk
|
|
125
|
+
? `Agent workspaces exist (${agentsInConfig.length})`
|
|
126
|
+
: `Agent workspaces missing: ${missingWorkspaces.join(', ')}`,
|
|
127
|
+
workspacesOk,
|
|
128
|
+
'Run: npx @robbiesrobotics/alice-agents --update to scaffold missing workspaces'
|
|
129
|
+
);
|
|
130
|
+
allOk = allOk && workspacesOk;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// 5. At least one model/provider configured
|
|
134
|
+
let modelOk = false;
|
|
135
|
+
let modelLabel = null;
|
|
136
|
+
|
|
137
|
+
if (config.default_model) {
|
|
138
|
+
modelOk = true;
|
|
139
|
+
modelLabel = config.default_model;
|
|
140
|
+
} else if (config.models && Object.keys(config.models).length > 0) {
|
|
141
|
+
modelOk = true;
|
|
142
|
+
modelLabel = Object.keys(config.models)[0];
|
|
143
|
+
} else if (config.providers && Object.keys(config.providers).length > 0) {
|
|
144
|
+
modelOk = true;
|
|
145
|
+
modelLabel = Object.keys(config.providers)[0];
|
|
146
|
+
} else if (config.llm && Object.keys(config.llm).length > 0) {
|
|
147
|
+
modelOk = true;
|
|
148
|
+
modelLabel = Object.keys(config.llm)[0];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
check(
|
|
152
|
+
modelOk
|
|
153
|
+
? `Model/provider configured: ${modelLabel}`
|
|
154
|
+
: 'No model/provider configured',
|
|
155
|
+
modelOk,
|
|
156
|
+
'Run: openclaw configure to set up a model provider'
|
|
157
|
+
);
|
|
158
|
+
allOk = allOk && modelOk;
|
|
159
|
+
|
|
160
|
+
// 6. License check
|
|
161
|
+
const { checkProLicense } = await import('./license.mjs');
|
|
162
|
+
const manifest = (() => {
|
|
163
|
+
try {
|
|
164
|
+
const mPath = join(OPENCLAW_DIR, '.alice-manifest.json');
|
|
165
|
+
if (!existsSync(mPath)) return null;
|
|
166
|
+
return JSON.parse(readFileSync(mPath, 'utf8'));
|
|
167
|
+
} catch {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
})();
|
|
171
|
+
|
|
172
|
+
const licenseResult = await checkProLicense();
|
|
173
|
+
if (manifest?.tier === 'pro' || licenseResult.licensed) {
|
|
174
|
+
if (licenseResult.licensed) {
|
|
175
|
+
const maskedKey = licenseResult.key.slice(0, 13) + '****';
|
|
176
|
+
check(
|
|
177
|
+
`Pro license: ${maskedKey} (stored at ~/.alice/license)`,
|
|
178
|
+
true
|
|
179
|
+
);
|
|
180
|
+
} else {
|
|
181
|
+
check(
|
|
182
|
+
'Pro license: not found (running Starter tier)',
|
|
183
|
+
false,
|
|
184
|
+
'Purchase a Pro license at: https://getalice.av3.ai/pricing'
|
|
185
|
+
);
|
|
186
|
+
allOk = false;
|
|
187
|
+
}
|
|
188
|
+
} else {
|
|
189
|
+
// Starter tier — just note no license needed
|
|
190
|
+
check('License: Starter tier (no license required)', true);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Summary
|
|
194
|
+
console.log();
|
|
195
|
+
if (allOk) {
|
|
196
|
+
console.log(' ✅ A.L.I.C.E. is healthy!\n');
|
|
197
|
+
} else {
|
|
198
|
+
console.log(' ⚠️ Issues found — follow the hints above to fix them.\n');
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return allOk;
|
|
202
|
+
}
|
package/lib/installer.mjs
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
promptModelPreset,
|
|
12
12
|
promptCustomModel,
|
|
13
13
|
promptTier,
|
|
14
|
+
promptLicenseKey,
|
|
14
15
|
confirm,
|
|
15
16
|
choose,
|
|
16
17
|
input,
|
|
@@ -253,7 +254,9 @@ export async function runInstall(options = {}) {
|
|
|
253
254
|
|
|
254
255
|
// 2. Install mode
|
|
255
256
|
let mode;
|
|
256
|
-
if (
|
|
257
|
+
if (options.modeOverride) {
|
|
258
|
+
mode = options.modeOverride;
|
|
259
|
+
} else if (auto) {
|
|
257
260
|
const manifest = readManifest();
|
|
258
261
|
mode = manifest ? 'upgrade' : 'fresh';
|
|
259
262
|
} else {
|
|
@@ -309,22 +312,58 @@ export async function runInstall(options = {}) {
|
|
|
309
312
|
}
|
|
310
313
|
|
|
311
314
|
if (tier === 'pro') {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
315
|
+
const { checkProLicense, validateLicenseRemote, storeLicense, isValidFormat } = await import('./license.mjs');
|
|
316
|
+
|
|
317
|
+
const existing = await checkProLicense();
|
|
318
|
+
|
|
319
|
+
if (existing.licensed) {
|
|
320
|
+
console.log(` ✅ Pro license found (${existing.key.slice(0, 12)}...)`);
|
|
321
|
+
} else if (auto) {
|
|
322
|
+
// --yes flag: skip interactive prompt, fallback to Starter if no stored license
|
|
323
|
+
console.log('');
|
|
324
|
+
console.log(' ℹ️ Pro tier requires a license key.');
|
|
325
|
+
console.log(' Run without --yes to enter your license key.');
|
|
326
|
+
console.log(' Falling back to Starter tier.');
|
|
327
|
+
console.log(' Purchase a license at: https://getalice.av3.ai/pricing');
|
|
328
|
+
tier = 'starter';
|
|
329
|
+
} else {
|
|
330
|
+
// No stored license — prompt for key
|
|
331
|
+
let key = '';
|
|
332
|
+
let attempts = 0;
|
|
333
|
+
|
|
334
|
+
while (attempts < 3) {
|
|
335
|
+
key = await promptLicenseKey();
|
|
336
|
+
|
|
337
|
+
if (!isValidFormat(key)) {
|
|
338
|
+
console.log(' ❌ Invalid format. Key must be ALICE-XXXX-XXXX-XXXX');
|
|
339
|
+
attempts++;
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
console.log(' Validating key...');
|
|
344
|
+
const result = await validateLicenseRemote(key);
|
|
345
|
+
|
|
346
|
+
if (result.valid) {
|
|
347
|
+
storeLicense(key);
|
|
348
|
+
if (result.message === 'offline') {
|
|
349
|
+
console.log(' ✅ Key stored (offline — will validate on next run)');
|
|
350
|
+
} else {
|
|
351
|
+
console.log(' ✅ License verified! Welcome to A.L.I.C.E. Pro.');
|
|
352
|
+
}
|
|
353
|
+
break;
|
|
354
|
+
} else {
|
|
355
|
+
console.log(` ❌ Invalid key: ${result.message ?? 'Not recognized'}`);
|
|
356
|
+
attempts++;
|
|
357
|
+
|
|
358
|
+
if (attempts >= 3) {
|
|
359
|
+
console.log('');
|
|
360
|
+
console.log(' Too many invalid attempts. Falling back to Starter tier.');
|
|
361
|
+
console.log(' Purchase a license at: https://getalice.av3.ai/pricing');
|
|
362
|
+
tier = 'starter'; // fallback gracefully
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
328
367
|
}
|
|
329
368
|
|
|
330
369
|
const agents = allAgents;
|
package/lib/license.mjs
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// lib/license.mjs
|
|
2
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { homedir } from 'node:os';
|
|
5
|
+
|
|
6
|
+
const LICENSE_DIR = join(homedir(), '.alice');
|
|
7
|
+
const LICENSE_FILE = join(LICENSE_DIR, 'license');
|
|
8
|
+
const VALIDATE_URL = 'https://getalice.av3.ai/api/license/validate';
|
|
9
|
+
const KEY_REGEX = /^ALICE-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}$/;
|
|
10
|
+
|
|
11
|
+
export function readStoredLicense() {
|
|
12
|
+
try {
|
|
13
|
+
if (!existsSync(LICENSE_FILE)) return null;
|
|
14
|
+
return readFileSync(LICENSE_FILE, 'utf8').trim();
|
|
15
|
+
} catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function storeLicense(key) {
|
|
21
|
+
mkdirSync(LICENSE_DIR, { recursive: true });
|
|
22
|
+
writeFileSync(LICENSE_FILE, key.trim(), 'utf8');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function isValidFormat(key) {
|
|
26
|
+
return KEY_REGEX.test(key?.trim()?.toUpperCase());
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function validateLicenseRemote(key) {
|
|
30
|
+
// Returns { valid: boolean, plan: string, message?: string }
|
|
31
|
+
try {
|
|
32
|
+
const res = await fetch(`${VALIDATE_URL}?key=${encodeURIComponent(key)}`, {
|
|
33
|
+
signal: AbortSignal.timeout(5000),
|
|
34
|
+
});
|
|
35
|
+
if (!res.ok) return { valid: false, message: 'Validation service unavailable' };
|
|
36
|
+
return await res.json();
|
|
37
|
+
} catch {
|
|
38
|
+
// Network error — fail open (allow install, validate next time)
|
|
39
|
+
return { valid: true, plan: 'pro', message: 'offline' };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function checkProLicense() {
|
|
44
|
+
// Returns: { licensed: boolean, key: string|null, source: 'stored'|'none' }
|
|
45
|
+
const stored = readStoredLicense();
|
|
46
|
+
if (stored && isValidFormat(stored)) {
|
|
47
|
+
return { licensed: true, key: stored, source: 'stored' };
|
|
48
|
+
}
|
|
49
|
+
return { licensed: false, key: null, source: 'none' };
|
|
50
|
+
}
|
package/lib/prompter.mjs
CHANGED
|
@@ -110,3 +110,18 @@ export async function promptTier() {
|
|
|
110
110
|
{ label: 'Pro (18 more agents) — sign up at getalice.av3.ai/signup?plan=pro', value: 'pro' },
|
|
111
111
|
]);
|
|
112
112
|
}
|
|
113
|
+
|
|
114
|
+
export async function promptLicenseKey() {
|
|
115
|
+
// Show instructions, prompt for key, validate format
|
|
116
|
+
console.log('');
|
|
117
|
+
console.log(' A.L.I.C.E. Pro requires a license key.');
|
|
118
|
+
console.log(' Purchase at: https://getalice.av3.ai/pricing');
|
|
119
|
+
console.log(' Already have a key? Enter it below.');
|
|
120
|
+
console.log('');
|
|
121
|
+
|
|
122
|
+
return new Promise((resolve) => {
|
|
123
|
+
getRL().question(' License key (ALICE-XXXX-XXXX-XXXX): ', (answer) => {
|
|
124
|
+
resolve(answer.trim().toUpperCase());
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
}
|
|
@@ -12,7 +12,7 @@ const SKILLS_DIR = join(OPENCLAW_DIR, 'skills');
|
|
|
12
12
|
const PRODUCT_FILES = ['SOUL.md', 'AGENTS.md', 'IDENTITY.md', 'TOOLS.md'];
|
|
13
13
|
|
|
14
14
|
// User files — only created if missing
|
|
15
|
-
const USER_FILES = ['PLAYBOOK.md', 'LEARNINGS.md', 'FEEDBACK.md', 'USER.md'];
|
|
15
|
+
const USER_FILES = ['PLAYBOOK.md', 'LEARNINGS.md', 'FEEDBACK.md', 'USER.md', 'MEMORY.md'];
|
|
16
16
|
|
|
17
17
|
function renderTemplate(template, vars) {
|
|
18
18
|
let result = template;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@robbiesrobotics/alice-agents",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "A.L.I.C.E. — 28 AI agents for OpenClaw. One conversation, one team.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"alice-agents": "bin/alice-install.mjs"
|
|
@@ -28,6 +28,10 @@
|
|
|
28
28
|
"SELF-HEALING-SPEC.md",
|
|
29
29
|
"README.md"
|
|
30
30
|
],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"test": "node --test test/*.test.mjs",
|
|
33
|
+
"test:check": "node --check lib/*.mjs bin/*.mjs"
|
|
34
|
+
},
|
|
31
35
|
"publishConfig": {
|
|
32
36
|
"access": "public"
|
|
33
37
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -48,3 +48,12 @@ Skip this for trivial lookups or single-command tasks. Write it for anything inv
|
|
|
48
48
|
- Don't exceed your domain without flagging it
|
|
49
49
|
- Don't run destructive commands without explicit risk callout
|
|
50
50
|
- `trash` > `rm`
|
|
51
|
+
|
|
52
|
+
## Tier Note
|
|
53
|
+
|
|
54
|
+
{{#if isPro}}
|
|
55
|
+
You are a **Pro tier** agent. Pro tier requires a valid A.L.I.C.E. Pro license key stored at `~/.alice/license`.
|
|
56
|
+
If you were installed without a license key, run the installer interactively to enter your key:
|
|
57
|
+
`npx @robbiesrobotics/alice-agents`
|
|
58
|
+
Purchase or manage your license at: https://getalice.av3.ai/pricing
|
|
59
|
+
{{/if}}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# MEMORY.md — {{agentName}}
|
|
2
|
+
|
|
3
|
+
> Persistent memory for {{agentName}}, {{agentDomain}} specialist.
|
|
4
|
+
> This file is yours — add notes, context, and learnings that should persist across sessions.
|
|
5
|
+
|
|
6
|
+
## Identity
|
|
7
|
+
|
|
8
|
+
- **Name:** {{agentName}}
|
|
9
|
+
- **Domain:** {{agentDomain}}
|
|
10
|
+
- **Team:** A.L.I.C.E.
|
|
11
|
+
|
|
12
|
+
## Active Projects
|
|
13
|
+
|
|
14
|
+
<!-- Add ongoing projects and their current status here -->
|
|
15
|
+
|
|
16
|
+
## Key Notes
|
|
17
|
+
|
|
18
|
+
<!-- Jot down anything important to remember across sessions -->
|
|
19
|
+
|
|
20
|
+
## Decisions Made
|
|
21
|
+
|
|
22
|
+
<!-- Record significant decisions and their rationale -->
|
package/tools/.gitkeep
ADDED
|
File without changes
|