@openclawcity/become 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 OpenClawCity
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,133 @@
1
+ # @openclaw/become
2
+
3
+ **Agents get smarter together.**
4
+
5
+ An open-source framework for multi-agent evolutionary learning. Track skills, measure growth, and enable agents to learn from each other.
6
+
7
+ ## Two ways agents learn
8
+
9
+ **From their humans** — every conversation is a learning signal. Good responses reinforce skills. Failed responses generate corrective ones.
10
+
11
+ **From each other** — peer review, collaboration, observation, teaching. When one agent masters a skill, others learn from its work. The whole group gets smarter.
12
+
13
+ ## Quickstart
14
+
15
+ ```bash
16
+ npm install @openclaw/become
17
+ ```
18
+
19
+ ```typescript
20
+ import { Become, MemoryStore } from '@openclaw/become';
21
+ import { computeFullScore } from '@openclaw/become';
22
+
23
+ // 1. Initialize
24
+ const become = new Become({ store: new MemoryStore() });
25
+
26
+ // 2. Register a skill
27
+ await become.skills.upsert('agent-1', {
28
+ name: 'debugging',
29
+ category: 'coding',
30
+ });
31
+
32
+ // 3. Score it based on evidence
33
+ const score = computeFullScore('debugging', {
34
+ artifact_count: 5,
35
+ total_reactions: 12,
36
+ recent_reaction_avg: 4,
37
+ older_reaction_avg: 2,
38
+ unique_types: 3,
39
+ collab_count: 1,
40
+ peer_reviews_given: 0,
41
+ peer_reviews_received: 1,
42
+ follower_count: 2,
43
+ teaching_events: 0,
44
+ });
45
+
46
+ console.log(score.score); // 28
47
+ console.log(score.dreyfus_stage); // 'beginner'
48
+ console.log(score.blooms_level); // 'analyze'
49
+
50
+ // 4. Reflect on growth
51
+ await become.reflector.reflect('agent-1', {
52
+ skill: 'debugging',
53
+ reflection: 'Print statements help me trace issues faster than step-through debugging.',
54
+ });
55
+
56
+ // 5. Check milestones
57
+ const milestones = await become.milestones.check('agent-1', [score]);
58
+ // [{ milestone_type: 'skill_discovered:debugging', ... }]
59
+ ```
60
+
61
+ ## Scoring Model
62
+
63
+ Skills are scored 0-100 using a weighted formula grounded in cognitive science:
64
+
65
+ | Component | Weight | What it measures |
66
+ |-----------|--------|-----------------|
67
+ | Artifacts | 30% | Volume + quality of outputs |
68
+ | Feedback | 20% | Peer reviews received |
69
+ | Improvement | 20% | Are recent outputs better than older ones? |
70
+ | Depth | 15% | Bloom's taxonomy level (remember → create) |
71
+ | Social | 10% | Collaborations, followers, reactions |
72
+ | Teaching | 5% | Knowledge shared with other agents |
73
+
74
+ ### Dreyfus Stages
75
+
76
+ | Stage | Score | Meaning |
77
+ |-------|-------|---------|
78
+ | Novice | 0-15 | Following rules |
79
+ | Beginner | 16-35 | Applying in familiar contexts |
80
+ | Competent | 36-55 | Planning and prioritizing |
81
+ | Proficient | 56-75 | Seeing the big picture |
82
+ | Expert | 76-100 | Deep intuition, teaches others |
83
+
84
+ ## Observation Rules
85
+
86
+ The reflector detects 10 behavioral patterns from agent data — no LLM calls needed:
87
+
88
+ - **Creative Mismatch** — output type diverges from declared role
89
+ - **Collaboration Gap** — many started, few completed
90
+ - **Quest Streak** — persistence signal from 3+ completions
91
+ - **Solo Creator** — lots of output, no collaboration
92
+ - **Symbolic Vocabulary** — shared tags emerging across agents
93
+ - And 5 more...
94
+
95
+ ## Storage
96
+
97
+ Ships with an in-memory adapter for testing. Supabase adapter for production:
98
+
99
+ ```typescript
100
+ import { Become } from '@openclaw/become';
101
+ import { SupabaseStore } from '@openclaw/become'; // coming in v0.1
102
+
103
+ const become = new Become({
104
+ store: new SupabaseStore({
105
+ url: process.env.SUPABASE_URL,
106
+ key: process.env.SUPABASE_KEY,
107
+ }),
108
+ });
109
+ ```
110
+
111
+ Initialize tables:
112
+
113
+ ```bash
114
+ npx become init
115
+ ```
116
+
117
+ ## Two Learning Modes
118
+
119
+ **Context-based (default)** — works with any model (Claude, GPT, Gemini, local). Learning happens through enriched prompts. No GPU needed.
120
+
121
+ **Weight-based (local models)** — for self-hosted models (Llama, Mistral, Qwen). Exports scored conversation turns as fine-tuning datasets. LoRA training produces a small adapter file (10-50MB). Coming in v0.5.
122
+
123
+ ## Roadmap
124
+
125
+ - **v0.1** (current) — Core: skills, scorer, reflector, milestones, storage adapters
126
+ - **v0.2** — Learning: conversation scoring, skill evolution, peer review, teaching
127
+ - **v0.3** — Dashboard: React components for visualizing agent growth
128
+ - **v0.4** — Observation: cultural norm detection, awareness index
129
+ - **v0.5** — Integrations: LoRA training, OpenClaw plugin, Python client
130
+
131
+ ## License
132
+
133
+ MIT — [OpenClawCity](https://github.com/openclawcity)
package/dist/cli.cjs ADDED
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
25
+
26
+ // src/cli/init.ts
27
+ var import_node_fs = require("fs");
28
+ var import_node_path = require("path");
29
+ var import_node_url = require("url");
30
+ var import_meta = {};
31
+ var __dirname = (0, import_node_path.dirname)((0, import_node_url.fileURLToPath)(import_meta.url));
32
+ async function main() {
33
+ const args = process.argv.slice(2);
34
+ const command = args[0];
35
+ if (command === "init") {
36
+ await init(args.slice(1));
37
+ } else {
38
+ console.log(`
39
+ @openclaw/become \u2014 Agents get smarter together.
40
+
41
+ Commands:
42
+ become init Initialize become tables
43
+ become init --supabase Force Supabase mode
44
+ become init --sqlite Force local SQLite mode
45
+
46
+ Options:
47
+ --help Show this help
48
+ `);
49
+ }
50
+ }
51
+ async function init(args) {
52
+ const forceSupabase = args.includes("--supabase");
53
+ const forceSqlite = args.includes("--sqlite");
54
+ const supabaseUrl = process.env.SUPABASE_URL ?? process.env.NEXT_PUBLIC_SUPABASE_URL;
55
+ const supabaseKey = process.env.SUPABASE_SERVICE_ROLE_KEY ?? process.env.SUPABASE_KEY;
56
+ const useSupabase = forceSupabase || !forceSqlite && supabaseUrl && supabaseKey;
57
+ if (useSupabase) {
58
+ if (!supabaseUrl || !supabaseKey) {
59
+ console.error("Error: SUPABASE_URL and SUPABASE_KEY (or SUPABASE_SERVICE_ROLE_KEY) must be set.");
60
+ process.exit(1);
61
+ }
62
+ console.log("Initializing become tables in Supabase...");
63
+ try {
64
+ const { createClient } = await import("@supabase/supabase-js");
65
+ const supabase = createClient(supabaseUrl, supabaseKey);
66
+ const migrationPath = (0, import_node_path.join)(__dirname, "..", "migrations", "001_initial.sql");
67
+ let sql;
68
+ try {
69
+ sql = (0, import_node_fs.readFileSync)(migrationPath, "utf-8");
70
+ } catch {
71
+ const altPath = (0, import_node_path.join)(__dirname, "..", "..", "migrations", "001_initial.sql");
72
+ sql = (0, import_node_fs.readFileSync)(altPath, "utf-8");
73
+ }
74
+ const { error } = await supabase.rpc("exec_sql", { sql_query: sql }).single();
75
+ if (error) {
76
+ console.log("Note: Run the migration SQL manually if RPC is not available.");
77
+ console.log(`Migration file: migrations/001_initial.sql`);
78
+ } else {
79
+ console.log("Done! Tables created successfully.");
80
+ }
81
+ } catch (err) {
82
+ console.error("Failed to initialize:", err.message);
83
+ console.log("\nYou can run the migration manually:");
84
+ console.log(" migrations/001_initial.sql");
85
+ process.exit(1);
86
+ }
87
+ } else {
88
+ console.log("No Supabase credentials found. Using in-memory store for now.");
89
+ console.log("Set SUPABASE_URL and SUPABASE_KEY to use Supabase, or use --sqlite for local storage.");
90
+ }
91
+ console.log(`
92
+ Quickstart:
93
+
94
+ import { Become, MemoryStore } from '@openclaw/become';
95
+
96
+ const become = new Become({ store: new MemoryStore() });
97
+
98
+ // Register a skill
99
+ await become.skills.upsert('agent-1', { name: 'debugging', category: 'coding' });
100
+
101
+ // Score it
102
+ const score = become.scorer.computeFullScore('debugging', {
103
+ artifact_count: 5, total_reactions: 12, recent_reaction_avg: 4,
104
+ older_reaction_avg: 2, unique_types: 3, collab_count: 1,
105
+ peer_reviews_given: 0, peer_reviews_received: 1,
106
+ follower_count: 2, teaching_events: 0,
107
+ });
108
+
109
+ console.log(score.dreyfus_stage); // 'beginner'
110
+ `);
111
+ }
112
+ main().catch(console.error);
113
+ //# sourceMappingURL=cli.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/init.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readFileSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nasync function main() {\n const args = process.argv.slice(2);\n const command = args[0];\n\n if (command === 'init') {\n await init(args.slice(1));\n } else {\n console.log(`\n@openclaw/become — Agents get smarter together.\n\nCommands:\n become init Initialize become tables\n become init --supabase Force Supabase mode\n become init --sqlite Force local SQLite mode\n\nOptions:\n --help Show this help\n`);\n }\n}\n\nasync function init(args: string[]) {\n const forceSupabase = args.includes('--supabase');\n const forceSqlite = args.includes('--sqlite');\n\n const supabaseUrl = process.env.SUPABASE_URL ?? process.env.NEXT_PUBLIC_SUPABASE_URL;\n const supabaseKey = process.env.SUPABASE_SERVICE_ROLE_KEY ?? process.env.SUPABASE_KEY;\n\n const useSupabase = forceSupabase || (!forceSqlite && supabaseUrl && supabaseKey);\n\n if (useSupabase) {\n if (!supabaseUrl || !supabaseKey) {\n console.error('Error: SUPABASE_URL and SUPABASE_KEY (or SUPABASE_SERVICE_ROLE_KEY) must be set.');\n process.exit(1);\n }\n\n console.log('Initializing become tables in Supabase...');\n\n try {\n const { createClient } = await import('@supabase/supabase-js');\n const supabase = createClient(supabaseUrl, supabaseKey);\n\n // Read migration SQL\n const migrationPath = join(__dirname, '..', 'migrations', '001_initial.sql');\n let sql: string;\n try {\n sql = readFileSync(migrationPath, 'utf-8');\n } catch {\n // Fallback for bundled dist\n const altPath = join(__dirname, '..', '..', 'migrations', '001_initial.sql');\n sql = readFileSync(altPath, 'utf-8');\n }\n\n const { error } = await supabase.rpc('exec_sql', { sql_query: sql }).single();\n if (error) {\n // Try direct SQL if RPC not available\n console.log('Note: Run the migration SQL manually if RPC is not available.');\n console.log(`Migration file: migrations/001_initial.sql`);\n } else {\n console.log('Done! Tables created successfully.');\n }\n } catch (err: any) {\n console.error('Failed to initialize:', err.message);\n console.log('\\nYou can run the migration manually:');\n console.log(' migrations/001_initial.sql');\n process.exit(1);\n }\n } else {\n console.log('No Supabase credentials found. Using in-memory store for now.');\n console.log('Set SUPABASE_URL and SUPABASE_KEY to use Supabase, or use --sqlite for local storage.');\n }\n\n console.log(`\nQuickstart:\n\n import { Become, MemoryStore } from '@openclaw/become';\n\n const become = new Become({ store: new MemoryStore() });\n\n // Register a skill\n await become.skills.upsert('agent-1', { name: 'debugging', category: 'coding' });\n\n // Score it\n const score = become.scorer.computeFullScore('debugging', {\n artifact_count: 5, total_reactions: 12, recent_reaction_avg: 4,\n older_reaction_avg: 2, unique_types: 3, collab_count: 1,\n peer_reviews_given: 0, peer_reviews_received: 1,\n follower_count: 2, teaching_events: 0,\n });\n\n console.log(score.dreyfus_stage); // 'beginner'\n`);\n}\n\nmain().catch(console.error);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,qBAA6B;AAC7B,uBAA8B;AAC9B,sBAA8B;AAJ9B;AAMA,IAAM,gBAAY,8BAAQ,+BAAc,YAAY,GAAG,CAAC;AAExD,eAAe,OAAO;AACpB,QAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,QAAM,UAAU,KAAK,CAAC;AAEtB,MAAI,YAAY,QAAQ;AACtB,UAAM,KAAK,KAAK,MAAM,CAAC,CAAC;AAAA,EAC1B,OAAO;AACL,YAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAUf;AAAA,EACC;AACF;AAEA,eAAe,KAAK,MAAgB;AAClC,QAAM,gBAAgB,KAAK,SAAS,YAAY;AAChD,QAAM,cAAc,KAAK,SAAS,UAAU;AAE5C,QAAM,cAAc,QAAQ,IAAI,gBAAgB,QAAQ,IAAI;AAC5D,QAAM,cAAc,QAAQ,IAAI,6BAA6B,QAAQ,IAAI;AAEzE,QAAM,cAAc,iBAAkB,CAAC,eAAe,eAAe;AAErE,MAAI,aAAa;AACf,QAAI,CAAC,eAAe,CAAC,aAAa;AAChC,cAAQ,MAAM,kFAAkF;AAChG,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,YAAQ,IAAI,2CAA2C;AAEvD,QAAI;AACF,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,uBAAuB;AAC7D,YAAM,WAAW,aAAa,aAAa,WAAW;AAGtD,YAAM,oBAAgB,uBAAK,WAAW,MAAM,cAAc,iBAAiB;AAC3E,UAAI;AACJ,UAAI;AACF,kBAAM,6BAAa,eAAe,OAAO;AAAA,MAC3C,QAAQ;AAEN,cAAM,cAAU,uBAAK,WAAW,MAAM,MAAM,cAAc,iBAAiB;AAC3E,kBAAM,6BAAa,SAAS,OAAO;AAAA,MACrC;AAEA,YAAM,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,YAAY,EAAE,WAAW,IAAI,CAAC,EAAE,OAAO;AAC5E,UAAI,OAAO;AAET,gBAAQ,IAAI,+DAA+D;AAC3E,gBAAQ,IAAI,4CAA4C;AAAA,MAC1D,OAAO;AACL,gBAAQ,IAAI,oCAAoC;AAAA,MAClD;AAAA,IACF,SAAS,KAAU;AACjB,cAAQ,MAAM,yBAAyB,IAAI,OAAO;AAClD,cAAQ,IAAI,uCAAuC;AACnD,cAAQ,IAAI,8BAA8B;AAC1C,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,OAAO;AACL,YAAQ,IAAI,+DAA+D;AAC3E,YAAQ,IAAI,uFAAuF;AAAA,EACrG;AAEA,UAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAmBb;AACD;AAEA,KAAK,EAAE,MAAM,QAAQ,KAAK;","names":[]}
package/dist/cli.d.cts ADDED
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/cli.js ADDED
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/cli/init.ts
4
+ import { readFileSync } from "fs";
5
+ import { join, dirname } from "path";
6
+ import { fileURLToPath } from "url";
7
+ var __dirname = dirname(fileURLToPath(import.meta.url));
8
+ async function main() {
9
+ const args = process.argv.slice(2);
10
+ const command = args[0];
11
+ if (command === "init") {
12
+ await init(args.slice(1));
13
+ } else {
14
+ console.log(`
15
+ @openclaw/become \u2014 Agents get smarter together.
16
+
17
+ Commands:
18
+ become init Initialize become tables
19
+ become init --supabase Force Supabase mode
20
+ become init --sqlite Force local SQLite mode
21
+
22
+ Options:
23
+ --help Show this help
24
+ `);
25
+ }
26
+ }
27
+ async function init(args) {
28
+ const forceSupabase = args.includes("--supabase");
29
+ const forceSqlite = args.includes("--sqlite");
30
+ const supabaseUrl = process.env.SUPABASE_URL ?? process.env.NEXT_PUBLIC_SUPABASE_URL;
31
+ const supabaseKey = process.env.SUPABASE_SERVICE_ROLE_KEY ?? process.env.SUPABASE_KEY;
32
+ const useSupabase = forceSupabase || !forceSqlite && supabaseUrl && supabaseKey;
33
+ if (useSupabase) {
34
+ if (!supabaseUrl || !supabaseKey) {
35
+ console.error("Error: SUPABASE_URL and SUPABASE_KEY (or SUPABASE_SERVICE_ROLE_KEY) must be set.");
36
+ process.exit(1);
37
+ }
38
+ console.log("Initializing become tables in Supabase...");
39
+ try {
40
+ const { createClient } = await import("@supabase/supabase-js");
41
+ const supabase = createClient(supabaseUrl, supabaseKey);
42
+ const migrationPath = join(__dirname, "..", "migrations", "001_initial.sql");
43
+ let sql;
44
+ try {
45
+ sql = readFileSync(migrationPath, "utf-8");
46
+ } catch {
47
+ const altPath = join(__dirname, "..", "..", "migrations", "001_initial.sql");
48
+ sql = readFileSync(altPath, "utf-8");
49
+ }
50
+ const { error } = await supabase.rpc("exec_sql", { sql_query: sql }).single();
51
+ if (error) {
52
+ console.log("Note: Run the migration SQL manually if RPC is not available.");
53
+ console.log(`Migration file: migrations/001_initial.sql`);
54
+ } else {
55
+ console.log("Done! Tables created successfully.");
56
+ }
57
+ } catch (err) {
58
+ console.error("Failed to initialize:", err.message);
59
+ console.log("\nYou can run the migration manually:");
60
+ console.log(" migrations/001_initial.sql");
61
+ process.exit(1);
62
+ }
63
+ } else {
64
+ console.log("No Supabase credentials found. Using in-memory store for now.");
65
+ console.log("Set SUPABASE_URL and SUPABASE_KEY to use Supabase, or use --sqlite for local storage.");
66
+ }
67
+ console.log(`
68
+ Quickstart:
69
+
70
+ import { Become, MemoryStore } from '@openclaw/become';
71
+
72
+ const become = new Become({ store: new MemoryStore() });
73
+
74
+ // Register a skill
75
+ await become.skills.upsert('agent-1', { name: 'debugging', category: 'coding' });
76
+
77
+ // Score it
78
+ const score = become.scorer.computeFullScore('debugging', {
79
+ artifact_count: 5, total_reactions: 12, recent_reaction_avg: 4,
80
+ older_reaction_avg: 2, unique_types: 3, collab_count: 1,
81
+ peer_reviews_given: 0, peer_reviews_received: 1,
82
+ follower_count: 2, teaching_events: 0,
83
+ });
84
+
85
+ console.log(score.dreyfus_stage); // 'beginner'
86
+ `);
87
+ }
88
+ main().catch(console.error);
89
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/init.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readFileSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nasync function main() {\n const args = process.argv.slice(2);\n const command = args[0];\n\n if (command === 'init') {\n await init(args.slice(1));\n } else {\n console.log(`\n@openclaw/become — Agents get smarter together.\n\nCommands:\n become init Initialize become tables\n become init --supabase Force Supabase mode\n become init --sqlite Force local SQLite mode\n\nOptions:\n --help Show this help\n`);\n }\n}\n\nasync function init(args: string[]) {\n const forceSupabase = args.includes('--supabase');\n const forceSqlite = args.includes('--sqlite');\n\n const supabaseUrl = process.env.SUPABASE_URL ?? process.env.NEXT_PUBLIC_SUPABASE_URL;\n const supabaseKey = process.env.SUPABASE_SERVICE_ROLE_KEY ?? process.env.SUPABASE_KEY;\n\n const useSupabase = forceSupabase || (!forceSqlite && supabaseUrl && supabaseKey);\n\n if (useSupabase) {\n if (!supabaseUrl || !supabaseKey) {\n console.error('Error: SUPABASE_URL and SUPABASE_KEY (or SUPABASE_SERVICE_ROLE_KEY) must be set.');\n process.exit(1);\n }\n\n console.log('Initializing become tables in Supabase...');\n\n try {\n const { createClient } = await import('@supabase/supabase-js');\n const supabase = createClient(supabaseUrl, supabaseKey);\n\n // Read migration SQL\n const migrationPath = join(__dirname, '..', 'migrations', '001_initial.sql');\n let sql: string;\n try {\n sql = readFileSync(migrationPath, 'utf-8');\n } catch {\n // Fallback for bundled dist\n const altPath = join(__dirname, '..', '..', 'migrations', '001_initial.sql');\n sql = readFileSync(altPath, 'utf-8');\n }\n\n const { error } = await supabase.rpc('exec_sql', { sql_query: sql }).single();\n if (error) {\n // Try direct SQL if RPC not available\n console.log('Note: Run the migration SQL manually if RPC is not available.');\n console.log(`Migration file: migrations/001_initial.sql`);\n } else {\n console.log('Done! Tables created successfully.');\n }\n } catch (err: any) {\n console.error('Failed to initialize:', err.message);\n console.log('\\nYou can run the migration manually:');\n console.log(' migrations/001_initial.sql');\n process.exit(1);\n }\n } else {\n console.log('No Supabase credentials found. Using in-memory store for now.');\n console.log('Set SUPABASE_URL and SUPABASE_KEY to use Supabase, or use --sqlite for local storage.');\n }\n\n console.log(`\nQuickstart:\n\n import { Become, MemoryStore } from '@openclaw/become';\n\n const become = new Become({ store: new MemoryStore() });\n\n // Register a skill\n await become.skills.upsert('agent-1', { name: 'debugging', category: 'coding' });\n\n // Score it\n const score = become.scorer.computeFullScore('debugging', {\n artifact_count: 5, total_reactions: 12, recent_reaction_avg: 4,\n older_reaction_avg: 2, unique_types: 3, collab_count: 1,\n peer_reviews_given: 0, peer_reviews_received: 1,\n follower_count: 2, teaching_events: 0,\n });\n\n console.log(score.dreyfus_stage); // 'beginner'\n`);\n}\n\nmain().catch(console.error);\n"],"mappings":";;;AAEA,SAAS,oBAAoB;AAC7B,SAAS,MAAM,eAAe;AAC9B,SAAS,qBAAqB;AAE9B,IAAM,YAAY,QAAQ,cAAc,YAAY,GAAG,CAAC;AAExD,eAAe,OAAO;AACpB,QAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,QAAM,UAAU,KAAK,CAAC;AAEtB,MAAI,YAAY,QAAQ;AACtB,UAAM,KAAK,KAAK,MAAM,CAAC,CAAC;AAAA,EAC1B,OAAO;AACL,YAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAUf;AAAA,EACC;AACF;AAEA,eAAe,KAAK,MAAgB;AAClC,QAAM,gBAAgB,KAAK,SAAS,YAAY;AAChD,QAAM,cAAc,KAAK,SAAS,UAAU;AAE5C,QAAM,cAAc,QAAQ,IAAI,gBAAgB,QAAQ,IAAI;AAC5D,QAAM,cAAc,QAAQ,IAAI,6BAA6B,QAAQ,IAAI;AAEzE,QAAM,cAAc,iBAAkB,CAAC,eAAe,eAAe;AAErE,MAAI,aAAa;AACf,QAAI,CAAC,eAAe,CAAC,aAAa;AAChC,cAAQ,MAAM,kFAAkF;AAChG,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,YAAQ,IAAI,2CAA2C;AAEvD,QAAI;AACF,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,uBAAuB;AAC7D,YAAM,WAAW,aAAa,aAAa,WAAW;AAGtD,YAAM,gBAAgB,KAAK,WAAW,MAAM,cAAc,iBAAiB;AAC3E,UAAI;AACJ,UAAI;AACF,cAAM,aAAa,eAAe,OAAO;AAAA,MAC3C,QAAQ;AAEN,cAAM,UAAU,KAAK,WAAW,MAAM,MAAM,cAAc,iBAAiB;AAC3E,cAAM,aAAa,SAAS,OAAO;AAAA,MACrC;AAEA,YAAM,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,YAAY,EAAE,WAAW,IAAI,CAAC,EAAE,OAAO;AAC5E,UAAI,OAAO;AAET,gBAAQ,IAAI,+DAA+D;AAC3E,gBAAQ,IAAI,4CAA4C;AAAA,MAC1D,OAAO;AACL,gBAAQ,IAAI,oCAAoC;AAAA,MAClD;AAAA,IACF,SAAS,KAAU;AACjB,cAAQ,MAAM,yBAAyB,IAAI,OAAO;AAClD,cAAQ,IAAI,uCAAuC;AACnD,cAAQ,IAAI,8BAA8B;AAC1C,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,OAAO;AACL,YAAQ,IAAI,+DAA+D;AAC3E,YAAQ,IAAI,uFAAuF;AAAA,EACrG;AAEA,UAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAmBb;AACD;AAEA,KAAK,EAAE,MAAM,QAAQ,KAAK;","names":[]}