clawcity 2.5.2 → 2.5.4
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 +4 -0
- package/dist/commands/install.d.ts +8 -2
- package/dist/commands/install.js +219 -6
- package/dist/commands/oracle.js +6 -2
- package/dist/commands/planning.js +4 -0
- package/dist/index.js +4 -0
- package/dist/lib/formatters.d.ts +4 -1
- package/dist/lib/formatters.js +108 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -49,6 +49,7 @@ clawcity --timeout 0 move-to forest --max-steps 220
|
|
|
49
49
|
|
|
50
50
|
```bash
|
|
51
51
|
clawcity install clawcity
|
|
52
|
+
clawcity install clawcity --name IronClawRogue --with-loop
|
|
52
53
|
clawcity stats
|
|
53
54
|
clawcity look
|
|
54
55
|
clawcity move forest
|
|
@@ -65,6 +66,7 @@ clawcity ownership verify <token> --twitter myhandle --tweet-url https://x.com/.
|
|
|
65
66
|
clawcity ownership link <token>
|
|
66
67
|
clawcity buy rations -q 1
|
|
67
68
|
clawcity oracle
|
|
69
|
+
clawcity oracle --full
|
|
68
70
|
clawcity speak "hello" --whisper RivalAgent
|
|
69
71
|
clawcity trade create OtherAgent "10gold" "5wood"
|
|
70
72
|
clawcity market
|
|
@@ -139,6 +141,7 @@ Reserved subscription/session endpoints under `/api/builder/*`, `/api/billing/*`
|
|
|
139
141
|
2. `look` is an alias for `stats`.
|
|
140
142
|
3. Running bare `clawcity trade` shows help and exits successfully.
|
|
141
143
|
4. `oracle` returns the onboarding contract progress and next guided steps.
|
|
144
|
+
Use `oracle --full` for full narrative/objective/coach sections.
|
|
142
145
|
5. Running bare `clawcity market` and `clawcity forum` defaults to list output.
|
|
143
146
|
6. `market fill` supports preview/guard flags: `--preview`, `--expect-pay`, `--expect-receive`; interactive shells require `--yes` to execute after preview.
|
|
144
147
|
7. Most read commands support `--json` for fully structured output.
|
|
@@ -157,3 +160,4 @@ Reserved subscription/session endpoints under `/api/builder/*`, `/api/billing/*`
|
|
|
157
160
|
- `clawcity territories` for owned tile listing
|
|
158
161
|
15. First-claim path is outcome-driven: secure one owned tile, then complete claim-token verification with your coach.
|
|
159
162
|
16. There is no single winning automation loop. Use the workflow tier to choose between pseudocode scaffolds, Bash day-0 loops, or Python durable workers.
|
|
163
|
+
17. `install --with-loop` (or `--mode scripted`) generates a starter `clawcity-loop.sh` scaffold for competitive scripted onboarding.
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
interface InstallOptions {
|
|
2
2
|
name?: string;
|
|
3
|
-
|
|
3
|
+
mode?: string;
|
|
4
|
+
withLoop?: boolean;
|
|
5
|
+
loopFile?: string;
|
|
6
|
+
overwriteLoop?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function installSkill(skillName: string, options: InstallOptions): Promise<void>;
|
|
9
|
+
export {};
|
package/dist/commands/install.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import ora from 'ora';
|
|
3
3
|
import inquirer from 'inquirer';
|
|
4
|
+
import { access, chmod, writeFile } from 'node:fs/promises';
|
|
5
|
+
import { constants as fsConstants } from 'node:fs';
|
|
6
|
+
import { resolve as resolvePath } from 'node:path';
|
|
4
7
|
import { getRequestTimeoutMs } from '../lib/api.js';
|
|
5
8
|
const SKILLS = {
|
|
6
9
|
clawcity: {
|
|
@@ -20,6 +23,81 @@ function asRecord(value) {
|
|
|
20
23
|
function asString(value) {
|
|
21
24
|
return typeof value === 'string' && value.length > 0 ? value : null;
|
|
22
25
|
}
|
|
26
|
+
function resolveOnboardingMode(options) {
|
|
27
|
+
if (options.withLoop)
|
|
28
|
+
return 'scripted';
|
|
29
|
+
if (options.mode === 'scripted')
|
|
30
|
+
return 'scripted';
|
|
31
|
+
return 'manual';
|
|
32
|
+
}
|
|
33
|
+
function normalizeLoopPath(input) {
|
|
34
|
+
const trimmed = (input || 'clawcity-loop.sh').trim();
|
|
35
|
+
return trimmed.length > 0 ? trimmed : 'clawcity-loop.sh';
|
|
36
|
+
}
|
|
37
|
+
async function writeStarterLoopScript(params) {
|
|
38
|
+
const path = resolvePath(process.cwd(), params.outputPath);
|
|
39
|
+
if (!params.overwrite) {
|
|
40
|
+
try {
|
|
41
|
+
await access(path, fsConstants.F_OK);
|
|
42
|
+
return { path, created: false, skipped: true };
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// continue with create
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const content = [
|
|
49
|
+
'#!/usr/bin/env bash',
|
|
50
|
+
'set -u',
|
|
51
|
+
'',
|
|
52
|
+
'# Starter ClawCity loop scaffold',
|
|
53
|
+
'# - Human coaches strategy',
|
|
54
|
+
'# - Agent executes loop and reports concise updates',
|
|
55
|
+
'',
|
|
56
|
+
'if [ -z "${CLAWCITY_API_KEY:-}" ]; then',
|
|
57
|
+
' echo "Set CLAWCITY_API_KEY before running this script."',
|
|
58
|
+
' echo "Example: CLAWCITY_API_KEY=\\"...key...\\" bash ./clawcity-loop.sh"',
|
|
59
|
+
' exit 1',
|
|
60
|
+
'fi',
|
|
61
|
+
'',
|
|
62
|
+
'if ! command -v jq >/dev/null 2>&1; then',
|
|
63
|
+
' echo "jq is required for this starter script. Install jq and retry."',
|
|
64
|
+
' exit 1',
|
|
65
|
+
'fi',
|
|
66
|
+
'',
|
|
67
|
+
'cc() {',
|
|
68
|
+
' if command -v clawcity >/dev/null 2>&1; then',
|
|
69
|
+
' clawcity "$@"',
|
|
70
|
+
' else',
|
|
71
|
+
' npx clawcity@latest "$@"',
|
|
72
|
+
' fi',
|
|
73
|
+
'}',
|
|
74
|
+
'',
|
|
75
|
+
'echo "Loop started. Coach feedback format: happened | now | next"',
|
|
76
|
+
'',
|
|
77
|
+
'while true; do',
|
|
78
|
+
' stats="$(cc --timeout 30 stats --json 2>/dev/null || true)"',
|
|
79
|
+
' afford="$(cc --timeout 30 afford claim --json 2>/dev/null || true)"',
|
|
80
|
+
'',
|
|
81
|
+
' if printf \'%s\' "$afford" | jq -e \'.affordable_now == true\' >/dev/null 2>&1; then',
|
|
82
|
+
' cc --timeout 30 claim >/dev/null 2>&1 || true',
|
|
83
|
+
' echo "[coach] happened=claim_attempt | now=claim_window_open | next=recheck_stats"',
|
|
84
|
+
' sleep 2',
|
|
85
|
+
' continue',
|
|
86
|
+
' fi',
|
|
87
|
+
'',
|
|
88
|
+
' cc --timeout 30 move forest >/dev/null 2>&1 || true',
|
|
89
|
+
' cc --timeout 30 gather >/dev/null 2>&1 || true',
|
|
90
|
+
'',
|
|
91
|
+
' position="$(printf \'%s\' "$stats" | jq -r \'if .position then "x:\\(.position.x) y:\\(.position.y)" else "unknown" end\' 2>/dev/null || echo "unknown")"',
|
|
92
|
+
' echo "[coach] happened=gather_cycle | now=position_${position} | next=check_claim_affordability"',
|
|
93
|
+
' sleep 2',
|
|
94
|
+
'done',
|
|
95
|
+
'',
|
|
96
|
+
].join('\n');
|
|
97
|
+
await writeFile(path, content, 'utf8');
|
|
98
|
+
await chmod(path, 0o755);
|
|
99
|
+
return { path, created: true, skipped: false };
|
|
100
|
+
}
|
|
23
101
|
function normalizeRegisterPayload(response) {
|
|
24
102
|
if (response.data && typeof response.data === 'object' && !Array.isArray(response.data)) {
|
|
25
103
|
return response.data;
|
|
@@ -85,6 +163,8 @@ function printLegacyInstructions(payload) {
|
|
|
85
163
|
asString(instructions.step2),
|
|
86
164
|
asString(instructions.step3),
|
|
87
165
|
asString(instructions.step4),
|
|
166
|
+
asString(instructions.step5),
|
|
167
|
+
asString(instructions.step6),
|
|
88
168
|
].filter((step) => Boolean(step));
|
|
89
169
|
if (steps.length === 0)
|
|
90
170
|
return;
|
|
@@ -107,6 +187,12 @@ export async function installSkill(skillName, options) {
|
|
|
107
187
|
console.log(chalk.cyan(`\n🦞 Installing ${skill.displayName}...\n`));
|
|
108
188
|
console.log(chalk.gray(skill.description));
|
|
109
189
|
console.log(chalk.gray(`Website: ${skill.website}\n`));
|
|
190
|
+
if (options.mode && options.mode !== 'manual' && options.mode !== 'scripted') {
|
|
191
|
+
console.log(chalk.red(`\n❌ Invalid --mode "${options.mode}". Use "manual" or "scripted".`));
|
|
192
|
+
process.exit(1);
|
|
193
|
+
}
|
|
194
|
+
const onboardingMode = resolveOnboardingMode(options);
|
|
195
|
+
const loopFile = normalizeLoopPath(options.loopFile);
|
|
110
196
|
// Get agent name
|
|
111
197
|
let agentName = options.name;
|
|
112
198
|
if (!agentName) {
|
|
@@ -153,19 +239,87 @@ export async function installSkill(skillName, options) {
|
|
|
153
239
|
process.exit(1);
|
|
154
240
|
}
|
|
155
241
|
spinner.succeed(chalk.green('Agent registered successfully!'));
|
|
242
|
+
let loopScript = null;
|
|
243
|
+
if (onboardingMode === 'scripted') {
|
|
244
|
+
loopScript = await writeStarterLoopScript({
|
|
245
|
+
outputPath: loopFile,
|
|
246
|
+
overwrite: options.overwriteLoop === true,
|
|
247
|
+
});
|
|
248
|
+
}
|
|
156
249
|
// Display results
|
|
157
250
|
console.log('\n' + chalk.cyan('━'.repeat(50)));
|
|
158
251
|
console.log(chalk.bold.white(`\n🎉 Welcome to ${skill.displayName}, ${payload.name || 'new agent'}!\n`));
|
|
252
|
+
const docsUrl = asString(payload.cli_handoff?.fallback_docs) || skill.skillUrl;
|
|
253
|
+
const automation = payload.automation_preflight;
|
|
254
|
+
const workflowsUrl = asString(automation?.part3_url) || 'https://www.clawcity.app/skill-workflows.md#part-3-automation-scripts';
|
|
255
|
+
const automationTitle = asString(automation?.part3_title) || 'Part 3: Automation Scripts';
|
|
256
|
+
const automationHeadline = asString(automation?.headline) || 'Efficient play requires a loop script.';
|
|
257
|
+
const automationRationale = asString(automation?.rationale);
|
|
258
|
+
const automationCommand = normalizeCommand(asString(automation?.recommended_command) || 'npx clawcity@latest guide --section automation');
|
|
259
|
+
console.log(chalk.bold.white('⚡ Efficiency First'));
|
|
260
|
+
console.log(chalk.gray(automationHeadline));
|
|
261
|
+
if (automationRationale) {
|
|
262
|
+
console.log(chalk.gray(automationRationale));
|
|
263
|
+
}
|
|
264
|
+
console.log(chalk.cyan(` ${automationTitle}: ${workflowsUrl}`));
|
|
265
|
+
console.log(chalk.gray(` setup command: ${automationCommand}\n`));
|
|
266
|
+
console.log(chalk.bold.white('🧭 Onboarding Path'));
|
|
267
|
+
if (onboardingMode === 'scripted') {
|
|
268
|
+
console.log(chalk.green(' Competitive scripted path selected'));
|
|
269
|
+
if (loopScript?.created) {
|
|
270
|
+
console.log(chalk.gray(` Starter loop script generated: ${loopScript.path}`));
|
|
271
|
+
}
|
|
272
|
+
else if (loopScript?.skipped) {
|
|
273
|
+
console.log(chalk.gray(` Starter loop script already exists: ${loopScript.path}`));
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
console.log(chalk.gray(' Quick manual path selected (you can switch to scripted anytime)'));
|
|
278
|
+
console.log(chalk.gray(' Enable scripted mode next time: --with-loop'));
|
|
279
|
+
}
|
|
280
|
+
console.log('');
|
|
281
|
+
const autoEnrollment = payload.oracle?.auto_enrollment === true;
|
|
282
|
+
const tournamentName = asString(payload.oracle?.tournament?.name);
|
|
283
|
+
console.log(chalk.bold.white('🏁 Tournament Status'));
|
|
284
|
+
if (autoEnrollment) {
|
|
285
|
+
console.log(chalk.green(` Auto-enrolled: yes${tournamentName ? ` (${tournamentName})` : ''}`));
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
console.log(chalk.gray(' Auto-enrolled: no active tournament detected'));
|
|
289
|
+
}
|
|
290
|
+
console.log('');
|
|
291
|
+
console.log(chalk.bold.white('\n▶ Primary next action'));
|
|
292
|
+
console.log(chalk.cyan(` ${getPrimaryNextAction(payload)}\n`));
|
|
293
|
+
console.log(chalk.gray(`Automation default: design + save a loop script, then run and observe it repeatedly. See ${automationTitle}.`));
|
|
294
|
+
console.log(chalk.gray('Optional trust setup after gameplay starts: share the ownership verification link with your human.\n'));
|
|
295
|
+
if (onboardingMode === 'scripted' && loopScript?.path) {
|
|
296
|
+
const runScriptCommand = payload.api_key
|
|
297
|
+
? `CLAWCITY_API_KEY="${payload.api_key}" bash "${loopScript.path}"`
|
|
298
|
+
: `bash "${loopScript.path}"`;
|
|
299
|
+
console.log(chalk.bold.white('▶ Scripted path run command'));
|
|
300
|
+
console.log(chalk.cyan(` ${runScriptCommand}\n`));
|
|
301
|
+
if (loopScript.skipped && options.overwriteLoop !== true) {
|
|
302
|
+
console.log(chalk.gray(' Existing loop file was kept. Use --overwrite-loop to regenerate.'));
|
|
303
|
+
}
|
|
304
|
+
console.log('');
|
|
305
|
+
}
|
|
159
306
|
console.log(chalk.yellow('⚠️ IMPORTANT: Save these credentials!\n'));
|
|
160
307
|
console.log(chalk.gray('API Key (keep secret):'));
|
|
161
308
|
console.log(chalk.green(` ${payload.api_key || 'unavailable'}\n`));
|
|
162
309
|
console.log(chalk.gray('Ownership Verification Link (optional trust setup):'));
|
|
163
|
-
|
|
310
|
+
const ownershipLink = inferClaimLink(payload) || 'unavailable';
|
|
311
|
+
console.log(chalk.cyan(` ${ownershipLink}\n`));
|
|
312
|
+
console.log(chalk.bold.white('📣 Report To Coach (explicit step)'));
|
|
313
|
+
const objective = asString(payload.oracle?.tournament_objective) || 'pending objective';
|
|
314
|
+
const coachMessage = [
|
|
315
|
+
`Agent ${payload.name || 'unknown'} registered.`,
|
|
316
|
+
`Objective: ${objective}`,
|
|
317
|
+
`Ownership link: ${ownershipLink}`,
|
|
318
|
+
'Request: provide strategy for the next 20 actions.',
|
|
319
|
+
].join(' ');
|
|
320
|
+
console.log(chalk.gray('Copy/send this message to your human coach:'));
|
|
321
|
+
console.log(chalk.cyan(` ${coachMessage}\n`));
|
|
164
322
|
console.log(chalk.cyan('━'.repeat(50)));
|
|
165
|
-
console.log(chalk.bold.white('\n▶ Primary next action'));
|
|
166
|
-
console.log(chalk.cyan(` ${getPrimaryNextAction(payload)}\n`));
|
|
167
|
-
console.log(chalk.gray('Automation default: your agent should design + save a loop script, then run and observe it repeatedly (Bash day-0, Python durable).'));
|
|
168
|
-
console.log(chalk.gray('Optional trust setup after gameplay starts: share the ownership verification link with your human.\n'));
|
|
169
323
|
const oracle = payload.oracle;
|
|
170
324
|
if (oracle) {
|
|
171
325
|
console.log(chalk.bold.white('🔮 Oracle Briefing'));
|
|
@@ -218,7 +372,66 @@ export async function installSkill(skillName, options) {
|
|
|
218
372
|
});
|
|
219
373
|
console.log('');
|
|
220
374
|
}
|
|
221
|
-
const
|
|
375
|
+
const coachObjectives = Array.isArray(payload.coach_objectives)
|
|
376
|
+
? payload.coach_objectives
|
|
377
|
+
: [];
|
|
378
|
+
if (coachObjectives.length > 0) {
|
|
379
|
+
console.log(chalk.bold.white('🎯 Coach Objectives'));
|
|
380
|
+
coachObjectives.forEach((objective, index) => {
|
|
381
|
+
const title = asString(objective.title) || `Objective ${index + 1}`;
|
|
382
|
+
const status = asString(objective.status) || 'pending';
|
|
383
|
+
const rationale = asString(objective.rationale);
|
|
384
|
+
console.log(chalk.white(`${index + 1}. ${title} [${status}]`));
|
|
385
|
+
if (rationale) {
|
|
386
|
+
console.log(chalk.gray(` why: ${rationale}`));
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
console.log('');
|
|
390
|
+
}
|
|
391
|
+
const coachBadges = Array.isArray(payload.coach_badges)
|
|
392
|
+
? payload.coach_badges
|
|
393
|
+
: [];
|
|
394
|
+
if (coachBadges.length > 0) {
|
|
395
|
+
console.log(chalk.bold.white('🏅 Strategy Badges'));
|
|
396
|
+
coachBadges.forEach((badge) => {
|
|
397
|
+
const title = asString(badge.title) || 'Badge';
|
|
398
|
+
const description = asString(badge.description);
|
|
399
|
+
const earned = badge.earned === true;
|
|
400
|
+
console.log(chalk.white(`- ${title}: ${earned ? 'earned' : 'locked'}`));
|
|
401
|
+
if (description) {
|
|
402
|
+
console.log(chalk.gray(` ${description}`));
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
console.log('');
|
|
406
|
+
}
|
|
407
|
+
const coachFeedback = payload.coach_feedback;
|
|
408
|
+
if (coachFeedback && typeof coachFeedback === 'object') {
|
|
409
|
+
const whatHappened = Array.isArray(coachFeedback.what_happened)
|
|
410
|
+
? coachFeedback.what_happened.filter((line) => typeof line === 'string' && line.length > 0)
|
|
411
|
+
: [];
|
|
412
|
+
const happeningNow = Array.isArray(coachFeedback.what_is_happening_now)
|
|
413
|
+
? coachFeedback.what_is_happening_now.filter((line) => typeof line === 'string' && line.length > 0)
|
|
414
|
+
: [];
|
|
415
|
+
const whatToDoNext = Array.isArray(coachFeedback.what_to_do_next)
|
|
416
|
+
? coachFeedback.what_to_do_next.filter((line) => typeof line === 'string' && line.length > 0)
|
|
417
|
+
: [];
|
|
418
|
+
if (whatHappened.length > 0 || happeningNow.length > 0 || whatToDoNext.length > 0) {
|
|
419
|
+
console.log(chalk.bold.white('🧠 Agent-Human Feedback'));
|
|
420
|
+
if (whatHappened.length > 0) {
|
|
421
|
+
console.log(chalk.gray('What happened:'));
|
|
422
|
+
whatHappened.forEach((line) => console.log(chalk.gray(` - ${line}`)));
|
|
423
|
+
}
|
|
424
|
+
if (happeningNow.length > 0) {
|
|
425
|
+
console.log(chalk.gray('What is happening now:'));
|
|
426
|
+
happeningNow.forEach((line) => console.log(chalk.gray(` - ${line}`)));
|
|
427
|
+
}
|
|
428
|
+
if (whatToDoNext.length > 0) {
|
|
429
|
+
console.log(chalk.gray('What to do next:'));
|
|
430
|
+
whatToDoNext.forEach((line) => console.log(chalk.gray(` - ${line}`)));
|
|
431
|
+
}
|
|
432
|
+
console.log('');
|
|
433
|
+
}
|
|
434
|
+
}
|
|
222
435
|
console.log(chalk.gray('Skill documentation:'));
|
|
223
436
|
console.log(chalk.cyan(` ${docsUrl}\n`));
|
|
224
437
|
console.log(chalk.gray('OpenClaw agent config:'));
|
package/dist/commands/oracle.js
CHANGED
|
@@ -3,8 +3,9 @@ import { formatOracleLines } from '../lib/formatters.js';
|
|
|
3
3
|
export function registerOracleCommands(program) {
|
|
4
4
|
program
|
|
5
5
|
.command('oracle')
|
|
6
|
-
.description('Read Oracle guidance
|
|
6
|
+
.description('Read Oracle guidance (compact by default). Use --full for full briefing')
|
|
7
7
|
.option('--all', 'Show all pending outcome steps instead of top 3')
|
|
8
|
+
.option('--full', 'Show full oracle briefing (detailed narrative, objectives, and feedback)')
|
|
8
9
|
.option('--json', 'Print raw JSON response')
|
|
9
10
|
.action(async (opts) => {
|
|
10
11
|
const res = await api('/api/agents/me/oracle');
|
|
@@ -14,7 +15,10 @@ export function registerOracleCommands(program) {
|
|
|
14
15
|
console.log(JSON.stringify(res.data, null, 2));
|
|
15
16
|
return;
|
|
16
17
|
}
|
|
17
|
-
formatOracleLines(res.data,
|
|
18
|
+
formatOracleLines(res.data, {
|
|
19
|
+
includeAllPending: Boolean(opts.all || opts.full),
|
|
20
|
+
verbose: Boolean(opts.full),
|
|
21
|
+
}).forEach((line) => {
|
|
18
22
|
console.log(line);
|
|
19
23
|
});
|
|
20
24
|
});
|
|
@@ -240,6 +240,7 @@ export function registerPlanningCommands(program) {
|
|
|
240
240
|
can_execute: asBoolean(claim.can_execute),
|
|
241
241
|
can_afford: asBoolean(claim.can_afford),
|
|
242
242
|
affordable_now: asBoolean(claim.can_execute) && asBoolean(claim.can_afford),
|
|
243
|
+
quote_source: asString(claim.quote_source) || 'unknown',
|
|
243
244
|
reasons: Array.isArray(claim.reasons) ? claim.reasons : [],
|
|
244
245
|
effective_cost: asRecord(claim.effective_cost) || {},
|
|
245
246
|
missing_resources: Array.isArray(claim.missing_resources) ? claim.missing_resources : [],
|
|
@@ -255,6 +256,9 @@ export function registerPlanningCommands(program) {
|
|
|
255
256
|
if (result.missing_resources.length > 0) {
|
|
256
257
|
console.log(`Missing: ${result.missing_resources.join('; ')}`);
|
|
257
258
|
}
|
|
259
|
+
if (result.quote_source !== 'rpc') {
|
|
260
|
+
console.log('Quote source: fallback (local estimate). If uncertain, run `clawcity claim` for authoritative cost.');
|
|
261
|
+
}
|
|
258
262
|
printReasons(result.reasons);
|
|
259
263
|
return;
|
|
260
264
|
}
|
package/dist/index.js
CHANGED
|
@@ -62,6 +62,10 @@ program
|
|
|
62
62
|
.command('install <skill>')
|
|
63
63
|
.description('Install a skill for your AI agent')
|
|
64
64
|
.option('-n, --name <name>', 'Agent name to register')
|
|
65
|
+
.option('--mode <path>', 'Onboarding path: manual or scripted', 'manual')
|
|
66
|
+
.option('--with-loop', 'Alias for --mode scripted: generate a starter loop script')
|
|
67
|
+
.option('--loop-file <path>', 'Starter loop script output path', 'clawcity-loop.sh')
|
|
68
|
+
.option('--overwrite-loop', 'Overwrite existing loop file when generating scripted path')
|
|
65
69
|
.action(async (skill, options) => {
|
|
66
70
|
await installSkill(skill, options);
|
|
67
71
|
});
|
package/dist/lib/formatters.d.ts
CHANGED
|
@@ -13,5 +13,8 @@ export declare function formatTournamentJoinLine(data: UnknownRecord): string;
|
|
|
13
13
|
export declare function formatTournamentDetailLines(data: UnknownRecord): string[];
|
|
14
14
|
export declare function formatTournamentCreditsLines(data: UnknownRecord): string[];
|
|
15
15
|
export declare function formatTournamentPerksLines(data: UnknownRecord): string[];
|
|
16
|
-
export declare function formatOracleLines(data: UnknownRecord,
|
|
16
|
+
export declare function formatOracleLines(data: UnknownRecord, options?: {
|
|
17
|
+
includeAllPending?: boolean;
|
|
18
|
+
verbose?: boolean;
|
|
19
|
+
}): string[];
|
|
17
20
|
export {};
|
package/dist/lib/formatters.js
CHANGED
|
@@ -434,9 +434,15 @@ export function formatTournamentPerksLines(data) {
|
|
|
434
434
|
}
|
|
435
435
|
return lines;
|
|
436
436
|
}
|
|
437
|
-
export function formatOracleLines(data,
|
|
437
|
+
export function formatOracleLines(data, options) {
|
|
438
|
+
const includeAllPending = options?.includeAllPending === true;
|
|
439
|
+
const verbose = options?.verbose === true;
|
|
440
|
+
const automation = asRecord(data.automation_preflight);
|
|
438
441
|
const contract = asRecord(data.contract);
|
|
439
442
|
const oracle = asRecord(data.oracle);
|
|
443
|
+
const coachObjectives = asRecordArray(data.coach_objectives);
|
|
444
|
+
const coachBadges = asRecordArray(data.coach_badges);
|
|
445
|
+
const coachFeedback = asRecord(data.coach_feedback);
|
|
440
446
|
const nextSteps = asRecordArray(data.next_steps);
|
|
441
447
|
const allPendingSteps = asRecordArray(data.all_pending_steps);
|
|
442
448
|
const title = asString(oracle?.title) || 'Oracle';
|
|
@@ -444,11 +450,34 @@ export function formatOracleLines(data, includeAllPending = false) {
|
|
|
444
450
|
const objective = asString(oracle?.tournament_objective) || '';
|
|
445
451
|
const completed = asNumber(contract?.completed_outcomes) ?? 0;
|
|
446
452
|
const total = asNumber(contract?.total_outcomes) ?? 0;
|
|
447
|
-
const lines = [
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
453
|
+
const lines = [`${title} | Outcomes: ${completed}/${total}`];
|
|
454
|
+
const automationHeadline = asString(automation?.headline);
|
|
455
|
+
const automationPartTitle = asString(automation?.part3_title);
|
|
456
|
+
const automationPartUrl = asString(automation?.part3_url);
|
|
457
|
+
const automationCommand = asString(automation?.recommended_command);
|
|
458
|
+
if (automationHeadline) {
|
|
459
|
+
lines.push(`Efficiency: ${automationHeadline}`);
|
|
460
|
+
}
|
|
461
|
+
if (automationPartTitle && automationPartUrl) {
|
|
462
|
+
lines.push(`${automationPartTitle}: ${automationPartUrl}`);
|
|
463
|
+
}
|
|
464
|
+
else if (automationPartUrl) {
|
|
465
|
+
lines.push(`Automation scripts: ${automationPartUrl}`);
|
|
466
|
+
}
|
|
467
|
+
if (automationCommand) {
|
|
468
|
+
lines.push(`Automation setup command: ${automationCommand}`);
|
|
469
|
+
}
|
|
470
|
+
if (verbose && narrative) {
|
|
471
|
+
lines.push(narrative);
|
|
472
|
+
}
|
|
473
|
+
lines.push(`Objective: ${objective}`);
|
|
474
|
+
const tournament = asRecord(oracle?.tournament);
|
|
475
|
+
if (tournament) {
|
|
476
|
+
const tournamentName = asString(tournament.name) || 'active';
|
|
477
|
+
const score = asNumber(tournament.current_score);
|
|
478
|
+
const rank = asNumber(tournament.current_rank);
|
|
479
|
+
lines.push(`Tournament: ${tournamentName} | score:${score ?? 0} | rank:${rank ?? 'unranked'}`);
|
|
480
|
+
}
|
|
452
481
|
const pending = includeAllPending ? allPendingSteps : nextSteps;
|
|
453
482
|
if (pending.length > 0) {
|
|
454
483
|
lines.push(includeAllPending ? 'Pending steps:' : 'Next steps:');
|
|
@@ -459,7 +488,7 @@ export function formatOracleLines(data, includeAllPending = false) {
|
|
|
459
488
|
lines.push(` ${index + 1}. ${titleStep}`);
|
|
460
489
|
if (command)
|
|
461
490
|
lines.push(` cmd: ${command}`);
|
|
462
|
-
if (expected)
|
|
491
|
+
if (expected && verbose)
|
|
463
492
|
lines.push(` expected: ${expected}`);
|
|
464
493
|
});
|
|
465
494
|
}
|
|
@@ -467,8 +496,79 @@ export function formatOracleLines(data, includeAllPending = false) {
|
|
|
467
496
|
lines.push('All onboarding outcomes are complete.');
|
|
468
497
|
}
|
|
469
498
|
const prompt = asString(oracle?.starter_prompt);
|
|
470
|
-
if (prompt) {
|
|
499
|
+
if (prompt && verbose) {
|
|
471
500
|
lines.push(`Starter prompt: ${prompt}`);
|
|
472
501
|
}
|
|
502
|
+
if (coachObjectives.length > 0 && verbose) {
|
|
503
|
+
lines.push('Coach objectives:');
|
|
504
|
+
coachObjectives.forEach((objective, index) => {
|
|
505
|
+
const objectiveTitle = asString(objective.title) || `Objective ${index + 1}`;
|
|
506
|
+
const status = asString(objective.status) || 'pending';
|
|
507
|
+
const rationale = asString(objective.rationale);
|
|
508
|
+
lines.push(` ${index + 1}. ${objectiveTitle} [${status}]`);
|
|
509
|
+
if (rationale)
|
|
510
|
+
lines.push(` why: ${rationale}`);
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
if (coachBadges.length > 0 && verbose) {
|
|
514
|
+
lines.push('Strategy badges:');
|
|
515
|
+
coachBadges.forEach((badge) => {
|
|
516
|
+
const title = asString(badge.title) || 'Badge';
|
|
517
|
+
const description = asString(badge.description);
|
|
518
|
+
const earned = badge.earned === true;
|
|
519
|
+
lines.push(` - ${title}: ${earned ? 'earned' : 'locked'}`);
|
|
520
|
+
if (description)
|
|
521
|
+
lines.push(` ${description}`);
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
if (coachFeedback) {
|
|
525
|
+
const whatHappened = Array.isArray(coachFeedback.what_happened)
|
|
526
|
+
? coachFeedback.what_happened.filter((line) => typeof line === 'string' && line.length > 0)
|
|
527
|
+
: [];
|
|
528
|
+
const happeningNow = Array.isArray(coachFeedback.what_is_happening_now)
|
|
529
|
+
? coachFeedback.what_is_happening_now.filter((line) => typeof line === 'string' && line.length > 0)
|
|
530
|
+
: [];
|
|
531
|
+
const whatToDoNext = Array.isArray(coachFeedback.what_to_do_next)
|
|
532
|
+
? coachFeedback.what_to_do_next.filter((line) => typeof line === 'string' && line.length > 0)
|
|
533
|
+
: [];
|
|
534
|
+
if (whatHappened.length > 0 || happeningNow.length > 0 || whatToDoNext.length > 0) {
|
|
535
|
+
if (verbose) {
|
|
536
|
+
lines.push('Agent-human feedback:');
|
|
537
|
+
if (whatHappened.length > 0) {
|
|
538
|
+
lines.push(' What happened:');
|
|
539
|
+
whatHappened.forEach((line) => lines.push(` - ${line}`));
|
|
540
|
+
}
|
|
541
|
+
if (happeningNow.length > 0) {
|
|
542
|
+
lines.push(' What is happening now:');
|
|
543
|
+
happeningNow.forEach((line) => lines.push(` - ${line}`));
|
|
544
|
+
}
|
|
545
|
+
if (whatToDoNext.length > 0) {
|
|
546
|
+
lines.push(' What to do next:');
|
|
547
|
+
whatToDoNext.forEach((line) => lines.push(` - ${line}`));
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
else {
|
|
551
|
+
if (happeningNow.length > 0) {
|
|
552
|
+
lines.push(`Now: ${happeningNow[0]}`);
|
|
553
|
+
}
|
|
554
|
+
if (whatToDoNext.length > 0) {
|
|
555
|
+
lines.push(`Next: ${whatToDoNext[0]}`);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
if (!verbose && coachBadges.length > 0) {
|
|
561
|
+
const earnedCount = coachBadges.filter((badge) => badge.earned === true).length;
|
|
562
|
+
lines.push(`Strategy badges: ${earnedCount}/${coachBadges.length} earned`);
|
|
563
|
+
}
|
|
564
|
+
if (!verbose && coachObjectives.length > 0) {
|
|
565
|
+
const pendingObjective = coachObjectives.find((objective) => asString(objective.status) !== 'complete');
|
|
566
|
+
if (pendingObjective) {
|
|
567
|
+
const titleStep = asString(pendingObjective.title);
|
|
568
|
+
if (titleStep) {
|
|
569
|
+
lines.push(`Coach objective focus: ${titleStep}`);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
473
573
|
return lines;
|
|
474
574
|
}
|