@myvillage/cli 1.3.0 → 1.5.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.
@@ -0,0 +1,165 @@
1
+ import { mkdirSync, writeFileSync } from 'fs';
2
+ import { join } from 'path';
3
+ import { stringify as stringifyYaml } from 'yaml';
4
+
5
+ // ── MCP Tool Catalog ────────────────────────────────────
6
+
7
+ const TOOL_CATALOG = {
8
+ myvillage: {
9
+ url: 'https://mcp.myvillageproject.ai',
10
+ description: 'MyVillageOS platform access (feed, posts, communities, wallet, knowledge)',
11
+ always_enabled: true,
12
+ },
13
+ filesystem: {
14
+ command: 'npx',
15
+ args: ['-y', '@modelcontextprotocol/server-filesystem', '~/projects'],
16
+ description: 'Read/write local project files',
17
+ },
18
+ gmail: {
19
+ command: 'npx',
20
+ args: ['-y', '@anthropic/mcp-gmail'],
21
+ description: 'Read and search Gmail',
22
+ },
23
+ calendar: {
24
+ command: 'npx',
25
+ args: ['-y', '@anthropic/mcp-google-calendar'],
26
+ description: 'Read events, check availability, create reminders',
27
+ },
28
+ github: {
29
+ command: 'npx',
30
+ args: ['-y', '@modelcontextprotocol/server-github'],
31
+ env: { GITHUB_TOKEN: '${GITHUB_TOKEN}' },
32
+ description: 'GitHub repository access',
33
+ },
34
+ browser: {
35
+ command: 'npx',
36
+ args: ['-y', '@anthropic/mcp-puppeteer'],
37
+ description: 'Navigate web pages, extract content',
38
+ },
39
+ };
40
+
41
+ export { TOOL_CATALOG };
42
+
43
+ // ── Check-in Interval Map ───────────────────────────────
44
+
45
+ const INTERVAL_MAP = {
46
+ '15min': 15,
47
+ '1hr': 60,
48
+ 'twice-daily': 720,
49
+ 'manual': 0,
50
+ };
51
+
52
+ // ── Scaffolding ─────────────────────────────────────────
53
+
54
+ export function scaffoldAgent(agentDir, options) {
55
+ const { name, displayName, description, tools, checkInInterval } = options;
56
+
57
+ // Create directories
58
+ mkdirSync(join(agentDir, 'routines'), { recursive: true });
59
+ mkdirSync(join(agentDir, 'logs'), { recursive: true });
60
+
61
+ // Write agent.config.yaml
62
+ writeFileSync(
63
+ join(agentDir, 'agent.config.yaml'),
64
+ generateAgentConfig({ name, displayName, description, checkInInterval })
65
+ );
66
+
67
+ // Write prompt.md
68
+ writeFileSync(
69
+ join(agentDir, 'prompt.md'),
70
+ generatePromptMd({ name, displayName, description })
71
+ );
72
+
73
+ // Write tools.yaml
74
+ writeFileSync(
75
+ join(agentDir, 'tools.yaml'),
76
+ generateToolsYaml(tools)
77
+ );
78
+
79
+ // Write logs/.gitkeep
80
+ writeFileSync(join(agentDir, 'logs', '.gitkeep'), '');
81
+ }
82
+
83
+ // ── Config Generation ───────────────────────────────────
84
+
85
+ function generateAgentConfig({ name, displayName, description, checkInInterval }) {
86
+ const intervalMin = INTERVAL_MAP[checkInInterval] || 60;
87
+
88
+ const config = {
89
+ name,
90
+ display_name: displayName,
91
+ description,
92
+
93
+ man: {
94
+ agent_id: null,
95
+ owner_id: null,
96
+ },
97
+
98
+ schedule: {
99
+ check_in_interval: intervalMin,
100
+ active_hours: {
101
+ start: '08:00',
102
+ end: '22:00',
103
+ },
104
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone || 'America/New_York',
105
+ },
106
+
107
+ brain: {
108
+ provider: 'anthropic',
109
+ model: 'claude-sonnet-4-5-20250929',
110
+ max_tokens_per_loop: 1000,
111
+ fallback_provider: null,
112
+ },
113
+
114
+ limits: {
115
+ max_posts_per_day: 10,
116
+ max_api_calls_per_hour: 20,
117
+ max_file_reads_per_loop: 50,
118
+ },
119
+ };
120
+
121
+ return stringifyYaml(config, { lineWidth: 0 });
122
+ }
123
+
124
+ // ── Prompt Generation ───────────────────────────────────
125
+
126
+ function generatePromptMd({ displayName, description }) {
127
+ return `# ${displayName}
128
+
129
+ ${description}
130
+
131
+ ## Behaviors
132
+ - Check the MAN feed for relevant posts and engage thoughtfully
133
+ - Keep your posts short, helpful, and on-topic
134
+ - Summarize interesting discussions you find
135
+
136
+ ## Personality
137
+ - Friendly and supportive
138
+ - Speaks casually but clearly
139
+ - Concise in responses
140
+
141
+ ## Boundaries
142
+ - Never share personal files or private data to the feed
143
+ - Ask before posting anything longer than 2 sentences
144
+ - Stay on topic and avoid spam
145
+ - Respect rate limits and community guidelines
146
+ `;
147
+ }
148
+
149
+ // ── Tools YAML Generation ───────────────────────────────
150
+
151
+ function generateToolsYaml(selectedTools) {
152
+ const servers = {};
153
+
154
+ // myvillage is always included
155
+ servers['myvillage'] = TOOL_CATALOG['myvillage'];
156
+
157
+ for (const toolId of selectedTools) {
158
+ if (toolId === 'myvillage') continue;
159
+ if (TOOL_CATALOG[toolId]) {
160
+ servers[toolId] = { ...TOOL_CATALOG[toolId] };
161
+ }
162
+ }
163
+
164
+ return stringifyYaml({ servers }, { lineWidth: 0 });
165
+ }
package/src/utils/api.js CHANGED
@@ -1,10 +1,13 @@
1
1
  import axios from 'axios';
2
+ import { createRequire } from 'module';
2
3
  import { getConfig } from './config.js';
3
4
  import { loadCredentials, saveCredentials, getAccessToken, isTokenExpired } from './auth.js';
4
5
 
5
- const USER_AGENT = 'MyVillageOS-CLI/1.0.0';
6
+ const require = createRequire(import.meta.url);
7
+ const { version } = require('../../package.json');
8
+ const USER_AGENT = `MyVillageOS-CLI/${version}`;
6
9
 
7
- function createClient(baseURL) {
10
+ export function createClient(baseURL) {
8
11
  const client = axios.create({
9
12
  baseURL,
10
13
  headers: {
@@ -106,9 +109,13 @@ export async function getUserInfo(accessToken) {
106
109
  return response.data;
107
110
  }
108
111
 
109
- export async function deployGame(gameData) {
112
+ export async function deployGame(gameIdOrNew, formData) {
110
113
  const client = getApiClient();
111
- const response = await client.post('/games/deploy', gameData);
114
+ const response = await client.post(`/games/${gameIdOrNew}/deploy`, formData, {
115
+ headers: { 'Content-Type': 'multipart/form-data' },
116
+ maxBodyLength: Infinity,
117
+ maxContentLength: Infinity,
118
+ });
112
119
  return response.data;
113
120
  }
114
121
 
@@ -118,9 +125,9 @@ export async function getMyGames() {
118
125
  return response.data;
119
126
  }
120
127
 
121
- export async function getGameStats(gameId) {
128
+ export async function getGameStatus(gameId) {
122
129
  const client = getApiClient();
123
- const response = await client.get(`/games/${gameId}/stats`);
130
+ const response = await client.get(`/games/${gameId}/status`);
124
131
  return response.data;
125
132
  }
126
133
 
@@ -201,12 +208,6 @@ export async function castVote(data) {
201
208
  return response.data;
202
209
  }
203
210
 
204
- export async function removeVote(id) {
205
- const client = getNetworkClient();
206
- const response = await client.delete(`/votes/${id}`);
207
- return response.data;
208
- }
209
-
210
211
  // Communities
211
212
  export async function listCommunities(params = {}) {
212
213
  const client = getNetworkClient();
@@ -271,9 +272,9 @@ export async function createAgent(data) {
271
272
  return response.data;
272
273
  }
273
274
 
274
- export async function listMyAgents() {
275
+ export async function listMyAgents(params = {}) {
275
276
  const client = getNetworkClient();
276
- const response = await client.get('/agents/my');
277
+ const response = await client.get('/agents/my', { params });
277
278
  return response.data;
278
279
  }
279
280
 
@@ -306,3 +307,123 @@ export async function agentLeaveCommunity(id, slug) {
306
307
  const response = await client.delete(`/agents/${id}/communities/${slug}/leave`);
307
308
  return response.data;
308
309
  }
310
+
311
+ export async function runAgent(id, input = null) {
312
+ const client = getNetworkClient();
313
+ const data = input ? { input } : {};
314
+ const response = await client.post(`/agents/${id}/run`, data);
315
+ return response.data;
316
+ }
317
+
318
+ // Agent Mentions
319
+ export async function getAgentMentions(id, params = {}) {
320
+ const client = getNetworkClient();
321
+ const response = await client.get(`/agents/${id}/mentions`, { params });
322
+ return response.data;
323
+ }
324
+
325
+ // Agent Activity
326
+ export async function getAgentActivity(id, params = {}) {
327
+ const client = getNetworkClient();
328
+ const response = await client.get(`/agents/${id}/activity`, { params });
329
+ return response.data;
330
+ }
331
+
332
+ // Agent Heartbeat
333
+ export async function postAgentHeartbeat(id, data) {
334
+ const client = getNetworkClient();
335
+ const response = await client.post(`/agents/${id}/heartbeat`, data);
336
+ return response.data;
337
+ }
338
+
339
+ export async function getAgentHeartbeats(id, params = {}) {
340
+ const client = getNetworkClient();
341
+ const response = await client.get(`/agents/${id}/heartbeat`, { params });
342
+ return response.data;
343
+ }
344
+
345
+ // Agent Memory
346
+ export async function upsertAgentMemory(id, data) {
347
+ const client = getNetworkClient();
348
+ const response = await client.post(`/agents/${id}/memory`, data);
349
+ return response.data;
350
+ }
351
+
352
+ export async function listAgentMemory(id, params = {}) {
353
+ const client = getNetworkClient();
354
+ const response = await client.get(`/agents/${id}/memory`, { params });
355
+ return response.data;
356
+ }
357
+
358
+ export async function getAgentMemoryEntry(id, key) {
359
+ const client = getNetworkClient();
360
+ const response = await client.get(`/agents/${id}/memory/${encodeURIComponent(key)}`);
361
+ return response.data;
362
+ }
363
+
364
+ export async function deleteAgentMemoryEntry(id, key) {
365
+ const client = getNetworkClient();
366
+ const response = await client.delete(`/agents/${id}/memory/${encodeURIComponent(key)}`);
367
+ return response.data;
368
+ }
369
+
370
+ // ── OAuth Client Registration ────────────────────────────
371
+
372
+ export async function registerOAuthClient(name, appType, redirectUris) {
373
+ const client = getNetworkClient();
374
+ const response = await client.post('/api/oauth/clients/register', {
375
+ name,
376
+ appType,
377
+ redirectUris,
378
+ });
379
+ return response.data;
380
+ }
381
+
382
+ // ── BizReqs API Client (/api/bizreqs) ───────────────────
383
+
384
+ export function getBizReqsClient() {
385
+ const config = getConfig();
386
+ return createClient(config.bizreqsBaseUrl);
387
+ }
388
+
389
+ export async function createBizReqsSubmission(data) {
390
+ const client = getBizReqsClient();
391
+ const response = await client.post('/', data);
392
+ return response.data;
393
+ }
394
+
395
+ export async function listBizReqsSubmissions(params = {}) {
396
+ const client = getBizReqsClient();
397
+ const response = await client.get('/', { params });
398
+ return response.data;
399
+ }
400
+
401
+ export async function getBizReqsSubmission(id) {
402
+ const client = getBizReqsClient();
403
+ const response = await client.get(`/${encodeURIComponent(id)}`);
404
+ return response.data;
405
+ }
406
+
407
+ export async function updateBizReqsSubmission(id, data) {
408
+ const client = getBizReqsClient();
409
+ const response = await client.patch(`/${encodeURIComponent(id)}`, data);
410
+ return response.data;
411
+ }
412
+
413
+ export async function getBizReqsStatus(id) {
414
+ const client = getBizReqsClient();
415
+ const response = await client.get(`/${encodeURIComponent(id)}/status`);
416
+ return response.data;
417
+ }
418
+
419
+ export async function saveBizReqsSpec(id, data) {
420
+ const client = getBizReqsClient();
421
+ const response = await client.post(`/${encodeURIComponent(id)}/spec`, data);
422
+ return response.data;
423
+ }
424
+
425
+ export async function getBizReqsSpec(id) {
426
+ const client = getBizReqsClient();
427
+ const response = await client.get(`/${encodeURIComponent(id)}/spec`);
428
+ return response.data;
429
+ }