@osmosis-ai/cli 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/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,223 @@
1
+ #!/usr/bin/env node
2
+ import { AtomStore, searchAtoms, getTopAtoms, seedAtoms } from '@osmosis-ai/core';
3
+ import { createSyncServer, syncWithMesh, contributeTo, learnFrom, startAutoSync, resolveSyncConfig } from '@osmosis-ai/sync';
4
+ import { homedir } from 'node:os';
5
+ import { join } from 'node:path';
6
+ import { mkdirSync } from 'node:fs';
7
+ const DEFAULT_DB_PATH = join(homedir(), '.osmosis', 'atoms.db');
8
+ const DEFAULT_PORT = 7432;
9
+ const DEFAULT_MESH_URL = 'https://mesh.osmosis.dev';
10
+ const args = process.argv.slice(2);
11
+ const command = args[0];
12
+ function getDbPath() {
13
+ const idx = args.indexOf('--db');
14
+ if (idx !== -1 && args[idx + 1])
15
+ return args[idx + 1];
16
+ return process.env.OSMOSIS_DB_PATH ?? DEFAULT_DB_PATH;
17
+ }
18
+ function getPort() {
19
+ const idx = args.indexOf('--port');
20
+ if (idx !== -1 && args[idx + 1])
21
+ return parseInt(args[idx + 1], 10);
22
+ return parseInt(process.env.OSMOSIS_PORT ?? String(DEFAULT_PORT), 10);
23
+ }
24
+ function getMeshUrl() {
25
+ const idx = args.indexOf('--mesh');
26
+ if (idx !== -1 && args[idx + 1])
27
+ return args[idx + 1];
28
+ return process.env.OSMOSIS_MESH_URL ?? DEFAULT_MESH_URL;
29
+ }
30
+ function ensureDir(dbPath) {
31
+ const dir = dbPath.substring(0, dbPath.lastIndexOf('/'));
32
+ if (dir)
33
+ mkdirSync(dir, { recursive: true });
34
+ }
35
+ function openStore() {
36
+ const dbPath = getDbPath();
37
+ ensureDir(dbPath);
38
+ return new AtomStore(dbPath);
39
+ }
40
+ async function main() {
41
+ switch (command) {
42
+ case 'serve': {
43
+ const store = openStore();
44
+ const port = getPort();
45
+ const meshUrl = getMeshUrl();
46
+ const syncConfig = resolveSyncConfig({
47
+ meshUrl,
48
+ autoSync: true,
49
+ });
50
+ const server = createSyncServer(store, port, syncConfig);
51
+ console.log(`🧠 Osmosis API server listening on http://localhost:${port}`);
52
+ console.log(` Database: ${getDbPath()}`);
53
+ console.log(` Mesh: ${meshUrl}`);
54
+ console.log(` Auto-sync: every ${syncConfig.syncIntervalMs / 1000}s`);
55
+ console.log(` Press Ctrl+C to stop`);
56
+ const autoSync = startAutoSync(store, syncConfig);
57
+ process.on('SIGINT', () => {
58
+ console.log('\nShutting down...');
59
+ autoSync.stop();
60
+ server.close();
61
+ store.close();
62
+ process.exit(0);
63
+ });
64
+ break;
65
+ }
66
+ case 'mesh-serve': {
67
+ // Dynamically import mesh-server to avoid hard dependency
68
+ const { startMeshServer } = await import('@osmosis-ai/mesh-server');
69
+ const port = getPort();
70
+ const dbPath = getDbPath();
71
+ const handle = startMeshServer({ port, dbPath });
72
+ console.log(`🌐 Osmosis Mesh Server listening on http://localhost:${port}`);
73
+ console.log(` Database: ${dbPath}`);
74
+ console.log(` Press Ctrl+C to stop`);
75
+ process.on('SIGINT', () => {
76
+ console.log('\nShutting down mesh server...');
77
+ handle.stop();
78
+ process.exit(0);
79
+ });
80
+ break;
81
+ }
82
+ case 'status': {
83
+ const store = openStore();
84
+ const all = store.getAll();
85
+ const top = getTopAtoms(store, undefined, 5);
86
+ console.log(`🧠 Osmosis Status`);
87
+ console.log(` Atoms: ${all.length}`);
88
+ console.log(` Database: ${getDbPath()}`);
89
+ if (all.length > 0) {
90
+ const dates = all.map(a => a.updated_at).sort();
91
+ console.log(` Last capture: ${dates[dates.length - 1]}`);
92
+ console.log(`\n Top atoms by fitness:`);
93
+ for (const a of top) {
94
+ const label = a.tool_name ? `[${a.tool_name}]` : `[${a.type}]`;
95
+ console.log(` ${a.fitness_score.toFixed(2)} ${label} ${a.observation.slice(0, 80)}`);
96
+ }
97
+ }
98
+ else {
99
+ console.log(` No atoms yet. Run 'osmosis seed' to add examples.`);
100
+ }
101
+ store.close();
102
+ break;
103
+ }
104
+ case 'search': {
105
+ const query = args.slice(1).join(' ');
106
+ if (!query) {
107
+ console.error('Usage: osmosis search <query>');
108
+ process.exit(1);
109
+ }
110
+ const store = openStore();
111
+ const results = searchAtoms(store, query, 10);
112
+ if (results.length === 0) {
113
+ console.log('No results found.');
114
+ }
115
+ else {
116
+ console.log(`Found ${results.length} atom(s):\n`);
117
+ for (const a of results) {
118
+ const label = a.tool_name ? `[${a.tool_name}]` : `[${a.type}]`;
119
+ console.log(` ${a.fitness_score.toFixed(2)} ${label} ${a.observation}`);
120
+ }
121
+ }
122
+ store.close();
123
+ break;
124
+ }
125
+ case 'seed': {
126
+ const store = openStore();
127
+ const before = store.getAll().length;
128
+ seedAtoms(store);
129
+ const after = store.getAll().length;
130
+ console.log(`🌱 Seeded ${after - before} atoms (total: ${after})`);
131
+ store.close();
132
+ break;
133
+ }
134
+ case 'sync': {
135
+ const store = openStore();
136
+ const meshUrl = getMeshUrl();
137
+ console.log(`🔄 Syncing with mesh at ${meshUrl}...`);
138
+ const result = await syncWithMesh(store, meshUrl);
139
+ console.log(` Pushed: ${result.pushed}`);
140
+ console.log(` Pulled: ${result.pulled}`);
141
+ console.log(` Deduped: ${result.deduped}`);
142
+ if (result.errors.length > 0) {
143
+ console.log(` Errors: ${result.errors.length}`);
144
+ for (const e of result.errors)
145
+ console.log(` - ${e}`);
146
+ }
147
+ store.close();
148
+ break;
149
+ }
150
+ case 'contribute': {
151
+ const store = openStore();
152
+ const meshUrl = getMeshUrl();
153
+ console.log(`📤 Contributing to mesh at ${meshUrl}...`);
154
+ const result = await contributeTo(store, meshUrl);
155
+ console.log(` Pushed: ${result.pushed}`);
156
+ console.log(` Deduped: ${result.deduped}`);
157
+ if (result.errors.length > 0) {
158
+ console.log(` Errors: ${result.errors.length}`);
159
+ for (const e of result.errors)
160
+ console.log(` - ${e}`);
161
+ }
162
+ store.close();
163
+ break;
164
+ }
165
+ case 'learn': {
166
+ const store = openStore();
167
+ const meshUrl = getMeshUrl();
168
+ console.log(`📥 Learning from mesh at ${meshUrl}...`);
169
+ const result = await learnFrom(store, meshUrl);
170
+ console.log(` Pulled: ${result.pulled}`);
171
+ console.log(` Deduped: ${result.deduped}`);
172
+ if (result.errors.length > 0) {
173
+ console.log(` Errors: ${result.errors.length}`);
174
+ for (const e of result.errors)
175
+ console.log(` - ${e}`);
176
+ }
177
+ store.close();
178
+ break;
179
+ }
180
+ case 'reset': {
181
+ const store = openStore();
182
+ const all = store.getAll();
183
+ let deleted = 0;
184
+ for (const a of all) {
185
+ if (store.deleteAtom(a.id))
186
+ deleted++;
187
+ }
188
+ console.log(`🗑️ Deleted ${deleted} atoms. Database is empty.`);
189
+ store.close();
190
+ break;
191
+ }
192
+ default:
193
+ console.log(`🧠 Osmosis CLI v0.1.0
194
+
195
+ Usage:
196
+ osmosis serve [--port N] [--db PATH] [--mesh URL] Start local API server
197
+ osmosis mesh-serve [--port N] [--db PATH] Start mesh server
198
+ osmosis sync [--mesh URL] [--db PATH] Sync with mesh (contribute + learn)
199
+ osmosis contribute [--mesh URL] [--db PATH] Push local atoms to mesh
200
+ osmosis learn [--mesh URL] [--db PATH] Pull atoms from mesh
201
+ osmosis status [--db PATH] Show atom count and top atoms
202
+ osmosis search <query> [--db PATH] Search atoms
203
+ osmosis seed [--db PATH] Seed with example atoms
204
+ osmosis reset [--db PATH] Wipe all atoms
205
+
206
+ Options:
207
+ --db PATH Database path (default: ~/.osmosis/atoms.db)
208
+ --port N API port (default: 7432)
209
+ --mesh URL Mesh server URL (default: https://mesh.osmosis.dev)
210
+
211
+ Environment:
212
+ OSMOSIS_DB_PATH Database path override
213
+ OSMOSIS_PORT API port override
214
+ OSMOSIS_MESH_URL Mesh server URL override`);
215
+ if (command)
216
+ process.exit(1);
217
+ }
218
+ }
219
+ main().catch(err => {
220
+ console.error(err);
221
+ process.exit(1);
222
+ });
223
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@osmosis-ai/cli",
3
+ "version": "0.1.0",
4
+ "description": "CLI runner for Osmosis knowledge store",
5
+ "type": "module",
6
+ "main": "dist/cli.js",
7
+ "types": "dist/cli.d.ts",
8
+ "bin": {
9
+ "osmosis": "./dist/cli.js"
10
+ },
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "test": "vitest run",
14
+ "test:watch": "vitest"
15
+ },
16
+ "dependencies": {
17
+ "@osmosis-ai/core": "*",
18
+ "@osmosis-ai/sync": "*",
19
+ "@osmosis-ai/mesh-server": "*"
20
+ },
21
+ "devDependencies": {
22
+ "better-sqlite3": "^11.7.0",
23
+ "@types/better-sqlite3": "^7.6.12",
24
+ "typescript": "^5.7.0",
25
+ "vitest": "^3.0.0"
26
+ },
27
+ "license": "MIT"
28
+ }
@@ -0,0 +1,55 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { execSync } from 'node:child_process';
3
+ import { join } from 'node:path';
4
+ import { mkdtempSync, rmSync } from 'node:fs';
5
+ import { tmpdir } from 'node:os';
6
+
7
+ const CLI = join(import.meta.dirname, '../../dist/cli.js');
8
+
9
+ function run(args: string, env: Record<string, string> = {}): string {
10
+ return execSync(`node ${CLI} ${args}`, {
11
+ encoding: 'utf-8',
12
+ env: { ...process.env, ...env },
13
+ timeout: 10000,
14
+ }).trim();
15
+ }
16
+
17
+ describe('CLI', () => {
18
+ it('shows help with no args', () => {
19
+ const out = run('');
20
+ expect(out).toContain('Osmosis CLI');
21
+ expect(out).toContain('osmosis serve');
22
+ });
23
+
24
+ it('seed + status + search + reset cycle', () => {
25
+ const tmpDir = mkdtempSync(join(tmpdir(), 'osmosis-test-'));
26
+ const dbPath = join(tmpDir, 'test.db');
27
+ const env = { OSMOSIS_DB_PATH: dbPath };
28
+
29
+ try {
30
+ // Seed
31
+ const seedOut = run('seed', env);
32
+ expect(seedOut).toContain('Seeded');
33
+ expect(seedOut).toMatch(/\d+ atoms/);
34
+
35
+ // Status
36
+ const statusOut = run('status', env);
37
+ expect(statusOut).toContain('Atoms:');
38
+ expect(statusOut).toContain('Top atoms');
39
+
40
+ // Search
41
+ const searchOut = run('search browser screenshot', env);
42
+ expect(searchOut).toContain('Found');
43
+
44
+ // Reset
45
+ const resetOut = run('reset', env);
46
+ expect(resetOut).toContain('Deleted');
47
+
48
+ // Status after reset
49
+ const emptyStatus = run('status', env);
50
+ expect(emptyStatus).toContain('Atoms: 0');
51
+ } finally {
52
+ rmSync(tmpDir, { recursive: true, force: true });
53
+ }
54
+ });
55
+ });
package/src/cli.ts ADDED
@@ -0,0 +1,235 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { AtomStore, createServer, searchAtoms, getTopAtoms, seedAtoms } from '@osmosis-ai/core';
4
+ import { createSyncServer, syncWithMesh, contributeTo, learnFrom, getAllPeers, startAutoSync, resolveSyncConfig } from '@osmosis-ai/sync';
5
+ import { homedir } from 'node:os';
6
+ import { join } from 'node:path';
7
+ import { mkdirSync } from 'node:fs';
8
+
9
+ const DEFAULT_DB_PATH = join(homedir(), '.osmosis', 'atoms.db');
10
+ const DEFAULT_PORT = 7432;
11
+ const DEFAULT_MESH_URL = 'https://mesh.osmosis.dev';
12
+
13
+ const args = process.argv.slice(2);
14
+ const command = args[0];
15
+
16
+ function getDbPath(): string {
17
+ const idx = args.indexOf('--db');
18
+ if (idx !== -1 && args[idx + 1]) return args[idx + 1]!;
19
+ return process.env.OSMOSIS_DB_PATH ?? DEFAULT_DB_PATH;
20
+ }
21
+
22
+ function getPort(): number {
23
+ const idx = args.indexOf('--port');
24
+ if (idx !== -1 && args[idx + 1]) return parseInt(args[idx + 1]!, 10);
25
+ return parseInt(process.env.OSMOSIS_PORT ?? String(DEFAULT_PORT), 10);
26
+ }
27
+
28
+ function getMeshUrl(): string {
29
+ const idx = args.indexOf('--mesh');
30
+ if (idx !== -1 && args[idx + 1]) return args[idx + 1]!;
31
+ return process.env.OSMOSIS_MESH_URL ?? DEFAULT_MESH_URL;
32
+ }
33
+
34
+ function ensureDir(dbPath: string): void {
35
+ const dir = dbPath.substring(0, dbPath.lastIndexOf('/'));
36
+ if (dir) mkdirSync(dir, { recursive: true });
37
+ }
38
+
39
+ function openStore(): AtomStore {
40
+ const dbPath = getDbPath();
41
+ ensureDir(dbPath);
42
+ return new AtomStore(dbPath);
43
+ }
44
+
45
+ async function main(): Promise<void> {
46
+ switch (command) {
47
+ case 'serve': {
48
+ const store = openStore();
49
+ const port = getPort();
50
+ const meshUrl = getMeshUrl();
51
+ const syncConfig = resolveSyncConfig({
52
+ meshUrl,
53
+ autoSync: true,
54
+ });
55
+ const server = createSyncServer(store, port, syncConfig);
56
+ console.log(`🧠 Osmosis API server listening on http://localhost:${port}`);
57
+ console.log(` Database: ${getDbPath()}`);
58
+ console.log(` Mesh: ${meshUrl}`);
59
+ console.log(` Auto-sync: every ${syncConfig.syncIntervalMs / 1000}s`);
60
+ console.log(` Press Ctrl+C to stop`);
61
+
62
+ const autoSync = startAutoSync(store, syncConfig);
63
+
64
+ process.on('SIGINT', () => {
65
+ console.log('\nShutting down...');
66
+ autoSync.stop();
67
+ server.close();
68
+ store.close();
69
+ process.exit(0);
70
+ });
71
+ break;
72
+ }
73
+
74
+ case 'mesh-serve': {
75
+ // Dynamically import mesh-server to avoid hard dependency
76
+ const { startMeshServer } = await import('@osmosis-ai/mesh-server');
77
+ const port = getPort();
78
+ const dbPath = getDbPath();
79
+ const handle = startMeshServer({ port, dbPath });
80
+ console.log(`🌐 Osmosis Mesh Server listening on http://localhost:${port}`);
81
+ console.log(` Database: ${dbPath}`);
82
+ console.log(` Press Ctrl+C to stop`);
83
+
84
+ process.on('SIGINT', () => {
85
+ console.log('\nShutting down mesh server...');
86
+ handle.stop();
87
+ process.exit(0);
88
+ });
89
+ break;
90
+ }
91
+
92
+ case 'status': {
93
+ const store = openStore();
94
+ const all = store.getAll();
95
+ const top = getTopAtoms(store, undefined, 5);
96
+
97
+ console.log(`🧠 Osmosis Status`);
98
+ console.log(` Atoms: ${all.length}`);
99
+ console.log(` Database: ${getDbPath()}`);
100
+
101
+ if (all.length > 0) {
102
+ const dates = all.map(a => a.updated_at).sort();
103
+ console.log(` Last capture: ${dates[dates.length - 1]}`);
104
+ console.log(`\n Top atoms by fitness:`);
105
+ for (const a of top) {
106
+ const label = (a as any).tool_name ? `[${(a as any).tool_name}]` : `[${a.type}]`;
107
+ console.log(` ${a.fitness_score.toFixed(2)} ${label} ${a.observation.slice(0, 80)}`);
108
+ }
109
+ } else {
110
+ console.log(` No atoms yet. Run 'osmosis seed' to add examples.`);
111
+ }
112
+ store.close();
113
+ break;
114
+ }
115
+
116
+ case 'search': {
117
+ const query = args.slice(1).join(' ');
118
+ if (!query) {
119
+ console.error('Usage: osmosis search <query>');
120
+ process.exit(1);
121
+ }
122
+ const store = openStore();
123
+ const results = searchAtoms(store, query, 10);
124
+ if (results.length === 0) {
125
+ console.log('No results found.');
126
+ } else {
127
+ console.log(`Found ${results.length} atom(s):\n`);
128
+ for (const a of results) {
129
+ const label = (a as any).tool_name ? `[${(a as any).tool_name}]` : `[${a.type}]`;
130
+ console.log(` ${a.fitness_score.toFixed(2)} ${label} ${a.observation}`);
131
+ }
132
+ }
133
+ store.close();
134
+ break;
135
+ }
136
+
137
+ case 'seed': {
138
+ const store = openStore();
139
+ const before = store.getAll().length;
140
+ seedAtoms(store);
141
+ const after = store.getAll().length;
142
+ console.log(`🌱 Seeded ${after - before} atoms (total: ${after})`);
143
+ store.close();
144
+ break;
145
+ }
146
+
147
+ case 'sync': {
148
+ const store = openStore();
149
+ const meshUrl = getMeshUrl();
150
+ console.log(`🔄 Syncing with mesh at ${meshUrl}...`);
151
+ const result = await syncWithMesh(store, meshUrl);
152
+ console.log(` Pushed: ${result.pushed}`);
153
+ console.log(` Pulled: ${result.pulled}`);
154
+ console.log(` Deduped: ${result.deduped}`);
155
+ if (result.errors.length > 0) {
156
+ console.log(` Errors: ${result.errors.length}`);
157
+ for (const e of result.errors) console.log(` - ${e}`);
158
+ }
159
+ store.close();
160
+ break;
161
+ }
162
+
163
+ case 'contribute': {
164
+ const store = openStore();
165
+ const meshUrl = getMeshUrl();
166
+ console.log(`📤 Contributing to mesh at ${meshUrl}...`);
167
+ const result = await contributeTo(store, meshUrl);
168
+ console.log(` Pushed: ${result.pushed}`);
169
+ console.log(` Deduped: ${result.deduped}`);
170
+ if (result.errors.length > 0) {
171
+ console.log(` Errors: ${result.errors.length}`);
172
+ for (const e of result.errors) console.log(` - ${e}`);
173
+ }
174
+ store.close();
175
+ break;
176
+ }
177
+
178
+ case 'learn': {
179
+ const store = openStore();
180
+ const meshUrl = getMeshUrl();
181
+ console.log(`📥 Learning from mesh at ${meshUrl}...`);
182
+ const result = await learnFrom(store, meshUrl);
183
+ console.log(` Pulled: ${result.pulled}`);
184
+ console.log(` Deduped: ${result.deduped}`);
185
+ if (result.errors.length > 0) {
186
+ console.log(` Errors: ${result.errors.length}`);
187
+ for (const e of result.errors) console.log(` - ${e}`);
188
+ }
189
+ store.close();
190
+ break;
191
+ }
192
+
193
+ case 'reset': {
194
+ const store = openStore();
195
+ const all = store.getAll();
196
+ let deleted = 0;
197
+ for (const a of all) {
198
+ if (store.deleteAtom(a.id)) deleted++;
199
+ }
200
+ console.log(`🗑️ Deleted ${deleted} atoms. Database is empty.`);
201
+ store.close();
202
+ break;
203
+ }
204
+
205
+ default:
206
+ console.log(`🧠 Osmosis CLI v0.1.0
207
+
208
+ Usage:
209
+ osmosis serve [--port N] [--db PATH] [--mesh URL] Start local API server
210
+ osmosis mesh-serve [--port N] [--db PATH] Start mesh server
211
+ osmosis sync [--mesh URL] [--db PATH] Sync with mesh (contribute + learn)
212
+ osmosis contribute [--mesh URL] [--db PATH] Push local atoms to mesh
213
+ osmosis learn [--mesh URL] [--db PATH] Pull atoms from mesh
214
+ osmosis status [--db PATH] Show atom count and top atoms
215
+ osmosis search <query> [--db PATH] Search atoms
216
+ osmosis seed [--db PATH] Seed with example atoms
217
+ osmosis reset [--db PATH] Wipe all atoms
218
+
219
+ Options:
220
+ --db PATH Database path (default: ~/.osmosis/atoms.db)
221
+ --port N API port (default: 7432)
222
+ --mesh URL Mesh server URL (default: https://mesh.osmosis.dev)
223
+
224
+ Environment:
225
+ OSMOSIS_DB_PATH Database path override
226
+ OSMOSIS_PORT API port override
227
+ OSMOSIS_MESH_URL Mesh server URL override`);
228
+ if (command) process.exit(1);
229
+ }
230
+ }
231
+
232
+ main().catch(err => {
233
+ console.error(err);
234
+ process.exit(1);
235
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ES2022",
5
+ "moduleResolution": "bundler",
6
+ "lib": ["ES2022"],
7
+ "outDir": "dist",
8
+ "rootDir": "src",
9
+ "declaration": true,
10
+ "strict": true,
11
+ "esModuleInterop": true,
12
+ "skipLibCheck": true,
13
+ "forceConsistentCasingInFileNames": true,
14
+ "resolveJsonModule": true,
15
+ "sourceMap": true,
16
+ "composite": true
17
+ },
18
+ "include": ["src"],
19
+ "exclude": ["node_modules", "dist", "**/*.test.ts"],
20
+ "references": [
21
+ { "path": "../core" },
22
+ { "path": "../mesh-server" },
23
+ { "path": "../sync" }
24
+ ]
25
+ }