@myvillage/cli 1.5.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.
- package/package.json +8 -7
- package/src/agent-runtime/loop.js +9 -9
- package/src/agent-runtime/mcp-client.js +31 -338
- package/src/commands/agent-local.js +24 -7
- package/src/commands/login.js +159 -72
- package/src/commands/logout.js +43 -6
- package/src/commands/soulprint.js +1379 -0
- package/src/index.js +113 -0
- package/src/utils/agent-scaffolder.js +6 -6
- package/src/utils/api.js +1 -1
- package/src/utils/config.js +1 -0
- package/src/utils/soulprint-api.js +136 -0
- package/src/utils/soulprint-workspace.js +158 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myvillage/cli",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "MyVillageOS CLI for community developers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -26,16 +26,17 @@
|
|
|
26
26
|
"author": "MyVillage Project",
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"
|
|
30
|
-
"
|
|
29
|
+
"@ai-sdk/anthropic": "^1.0.0",
|
|
30
|
+
"ai": "^4.0.0",
|
|
31
31
|
"axios": "^1.6.2",
|
|
32
32
|
"chalk": "^5.3.0",
|
|
33
|
-
"
|
|
34
|
-
"open": "^10.0.3",
|
|
33
|
+
"commander": "^11.1.0",
|
|
35
34
|
"conf": "^12.0.0",
|
|
35
|
+
"inquirer": "^9.2.12",
|
|
36
|
+
"open": "^10.0.3",
|
|
37
|
+
"ora": "^8.0.1",
|
|
38
|
+
"p-limit": "^5.0.0",
|
|
36
39
|
"update-notifier": "^7.0.0",
|
|
37
|
-
"ai": "^4.0.0",
|
|
38
|
-
"@ai-sdk/anthropic": "^1.0.0",
|
|
39
40
|
"yaml": "^2.3.0",
|
|
40
41
|
"zod": "^3.22.0"
|
|
41
42
|
}
|
|
@@ -131,9 +131,9 @@ export async function agentLoop(agentName, { signal }) {
|
|
|
131
131
|
if (step.toolCalls?.length) {
|
|
132
132
|
for (const tc of step.toolCalls) {
|
|
133
133
|
activity.toolCalls++;
|
|
134
|
-
if (tc.toolName === '
|
|
135
|
-
if (tc.toolName === '
|
|
136
|
-
if (tc.toolName === '
|
|
134
|
+
if (tc.toolName === 'post_create') activity.postsCreated++;
|
|
135
|
+
if (tc.toolName === 'comment_create') activity.commentsCreated++;
|
|
136
|
+
if (tc.toolName === 'vote_cast') activity.votesGiven++;
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
if (step.toolCalls?.length && step.toolResults?.length) {
|
|
@@ -160,9 +160,9 @@ export async function agentLoop(agentName, { signal }) {
|
|
|
160
160
|
} else if (result.toolCalls?.length) {
|
|
161
161
|
for (const tc of result.toolCalls) {
|
|
162
162
|
activity.toolCalls++;
|
|
163
|
-
if (tc.toolName === '
|
|
164
|
-
if (tc.toolName === '
|
|
165
|
-
if (tc.toolName === '
|
|
163
|
+
if (tc.toolName === 'post_create') activity.postsCreated++;
|
|
164
|
+
if (tc.toolName === 'comment_create') activity.commentsCreated++;
|
|
165
|
+
if (tc.toolName === 'vote_cast') activity.votesGiven++;
|
|
166
166
|
logActivity(agentDir, {
|
|
167
167
|
type: 'tool_call',
|
|
168
168
|
tool: tc.toolName,
|
|
@@ -174,11 +174,11 @@ export async function agentLoop(agentName, { signal }) {
|
|
|
174
174
|
|
|
175
175
|
// Record actions for dedup in future iterations
|
|
176
176
|
const collectActions = (toolName, args) => {
|
|
177
|
-
if (toolName === '
|
|
177
|
+
if (toolName === 'comment_create' && args?.postId) {
|
|
178
178
|
recentActions.push({ type: 'comment', postId: args.postId, ts: new Date().toISOString() });
|
|
179
|
-
} else if (toolName === '
|
|
179
|
+
} else if (toolName === 'post_create' && args?.communitySlug) {
|
|
180
180
|
recentActions.push({ type: 'post', community: args.communitySlug, ts: new Date().toISOString() });
|
|
181
|
-
} else if (toolName === '
|
|
181
|
+
} else if (toolName === 'vote_cast' && args?.targetId) {
|
|
182
182
|
recentActions.push({ type: 'vote', targetId: args.targetId, targetType: args.targetType, ts: new Date().toISOString() });
|
|
183
183
|
}
|
|
184
184
|
};
|
|
@@ -5,20 +5,6 @@
|
|
|
5
5
|
import { readFileSync } from 'fs';
|
|
6
6
|
import { join } from 'path';
|
|
7
7
|
import { parse as parseYaml } from 'yaml';
|
|
8
|
-
import { tool } from 'ai';
|
|
9
|
-
import { z } from 'zod';
|
|
10
|
-
import {
|
|
11
|
-
getLatestFeed,
|
|
12
|
-
createPost,
|
|
13
|
-
createComment,
|
|
14
|
-
castVote,
|
|
15
|
-
searchNetwork,
|
|
16
|
-
getAgentMentions,
|
|
17
|
-
upsertAgentMemory,
|
|
18
|
-
listAgentMemory,
|
|
19
|
-
getAgentMemoryEntry,
|
|
20
|
-
deleteAgentMemoryEntry,
|
|
21
|
-
} from '../utils/api.js';
|
|
22
8
|
|
|
23
9
|
const activeClients = [];
|
|
24
10
|
|
|
@@ -37,21 +23,42 @@ export async function getMCPTools(agentDir, agentConfig) {
|
|
|
37
23
|
|
|
38
24
|
for (const [name, server] of Object.entries(toolsConfig.servers || {})) {
|
|
39
25
|
if (server.command === 'internal') {
|
|
40
|
-
|
|
26
|
+
// Legacy internal tools — skip (replaced by MCP server)
|
|
41
27
|
continue;
|
|
42
28
|
}
|
|
43
29
|
|
|
44
|
-
// External MCP servers via stdio transport
|
|
45
30
|
try {
|
|
46
31
|
const { experimental_createMCPClient: createMCPClient } = await import('ai');
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
32
|
+
let client;
|
|
33
|
+
|
|
34
|
+
if (server.url) {
|
|
35
|
+
// Remote MCP server via Streamable HTTP transport
|
|
36
|
+
const headers = {};
|
|
37
|
+
if (process.env.MYVILLAGE_ACCESS_TOKEN) {
|
|
38
|
+
headers['Authorization'] = `Bearer ${process.env.MYVILLAGE_ACCESS_TOKEN}`;
|
|
39
|
+
}
|
|
40
|
+
if (process.env.MYVILLAGE_AGENT_ID) {
|
|
41
|
+
headers['X-Agent-Id'] = process.env.MYVILLAGE_AGENT_ID;
|
|
42
|
+
}
|
|
43
|
+
client = await createMCPClient({
|
|
44
|
+
transport: {
|
|
45
|
+
type: 'sse',
|
|
46
|
+
url: server.url,
|
|
47
|
+
headers,
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
} else {
|
|
51
|
+
// Local MCP servers via stdio transport
|
|
52
|
+
client = await createMCPClient({
|
|
53
|
+
transport: {
|
|
54
|
+
type: 'stdio',
|
|
55
|
+
command: server.command,
|
|
56
|
+
args: server.args || [],
|
|
57
|
+
env: { ...process.env, ...resolveEnvVars(server.env || {}) },
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
55
62
|
activeClients.push(client);
|
|
56
63
|
const tools = await client.tools();
|
|
57
64
|
Object.assign(allTools, tools);
|
|
@@ -71,320 +78,6 @@ export async function cleanupMCPClients() {
|
|
|
71
78
|
activeClients.length = 0;
|
|
72
79
|
}
|
|
73
80
|
|
|
74
|
-
// ── Internal Tools (MAN Feed) ───────────────────────────
|
|
75
|
-
|
|
76
|
-
function getInternalTools(name, agentConfig) {
|
|
77
|
-
if (name !== 'man-feed') return {};
|
|
78
|
-
|
|
79
|
-
const agentProfileId = agentConfig?.man?.agent_id || null;
|
|
80
|
-
|
|
81
|
-
// Rate limit tracking (in-memory, resets on daemon restart)
|
|
82
|
-
const counters = {
|
|
83
|
-
postsToday: 0,
|
|
84
|
-
apiCallsThisHour: 0,
|
|
85
|
-
lastHourReset: Date.now(),
|
|
86
|
-
lastDayReset: new Date().toDateString(),
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
function checkRateLimits(type) {
|
|
90
|
-
const limits = agentConfig?.limits || {};
|
|
91
|
-
const now = new Date();
|
|
92
|
-
|
|
93
|
-
// Reset daily counter
|
|
94
|
-
if (now.toDateString() !== counters.lastDayReset) {
|
|
95
|
-
counters.postsToday = 0;
|
|
96
|
-
counters.lastDayReset = now.toDateString();
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Reset hourly counter
|
|
100
|
-
if (Date.now() - counters.lastHourReset > 3600000) {
|
|
101
|
-
counters.apiCallsThisHour = 0;
|
|
102
|
-
counters.lastHourReset = Date.now();
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (type === 'post' && counters.postsToday >= (limits.max_posts_per_day || 10)) {
|
|
106
|
-
return 'Rate limit: max posts per day reached';
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
if (counters.apiCallsThisHour >= (limits.max_api_calls_per_hour || 20)) {
|
|
110
|
-
return 'Rate limit: max API calls per hour reached';
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return null;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return {
|
|
117
|
-
man_read_feed: tool({
|
|
118
|
-
description: 'Read recent posts from the MAN feed. Returns the latest posts from communities.',
|
|
119
|
-
parameters: z.object({
|
|
120
|
-
limit: z.number().optional().describe('Number of posts to fetch (default 20)'),
|
|
121
|
-
community: z.string().optional().describe('Filter by community slug'),
|
|
122
|
-
}),
|
|
123
|
-
execute: async ({ limit, community }) => {
|
|
124
|
-
const rateErr = checkRateLimits('read');
|
|
125
|
-
if (rateErr) return { error: rateErr };
|
|
126
|
-
counters.apiCallsThisHour++;
|
|
127
|
-
|
|
128
|
-
try {
|
|
129
|
-
const params = { pageSize: limit || 20 };
|
|
130
|
-
if (community) params.communitySlug = community;
|
|
131
|
-
const result = await getLatestFeed(params);
|
|
132
|
-
const items = result.data || result;
|
|
133
|
-
if (!Array.isArray(items)) return { posts: [] };
|
|
134
|
-
return {
|
|
135
|
-
posts: items.map(p => ({
|
|
136
|
-
id: p.id,
|
|
137
|
-
title: p.title,
|
|
138
|
-
body: (p.body || '').slice(0, 200),
|
|
139
|
-
author: p.agentProfile?.handle || p.villager?.firstName || 'unknown',
|
|
140
|
-
community: p.community?.slug,
|
|
141
|
-
upvotes: p.upvoteCount || 0,
|
|
142
|
-
comments: p.commentCount || 0,
|
|
143
|
-
createdAt: p.createdAt,
|
|
144
|
-
})),
|
|
145
|
-
};
|
|
146
|
-
} catch (err) {
|
|
147
|
-
return { error: err.message };
|
|
148
|
-
}
|
|
149
|
-
},
|
|
150
|
-
}),
|
|
151
|
-
|
|
152
|
-
man_create_post: tool({
|
|
153
|
-
description: 'Create a new post on the MAN feed as this agent.',
|
|
154
|
-
parameters: z.object({
|
|
155
|
-
communitySlug: z.string().describe('Community slug to post in'),
|
|
156
|
-
body: z.string().describe('Post content'),
|
|
157
|
-
title: z.string().optional().describe('Post title'),
|
|
158
|
-
postType: z.enum(['DISCUSSION', 'QUESTION', 'PROJECT_SHOWCASE', 'TUTORIAL']).optional().describe('Post type (default DISCUSSION)'),
|
|
159
|
-
}),
|
|
160
|
-
execute: async ({ communitySlug, body, title, postType }) => {
|
|
161
|
-
if (!agentProfileId) return { error: 'Agent not registered on MAN' };
|
|
162
|
-
const rateErr = checkRateLimits('post');
|
|
163
|
-
if (rateErr) return { error: rateErr };
|
|
164
|
-
counters.apiCallsThisHour++;
|
|
165
|
-
counters.postsToday++;
|
|
166
|
-
|
|
167
|
-
try {
|
|
168
|
-
const data = {
|
|
169
|
-
communitySlug,
|
|
170
|
-
body,
|
|
171
|
-
postType: postType || 'DISCUSSION',
|
|
172
|
-
agentProfileId,
|
|
173
|
-
};
|
|
174
|
-
if (title) data.title = title;
|
|
175
|
-
const result = await createPost(data);
|
|
176
|
-
const post = result.data || result;
|
|
177
|
-
return { success: true, postId: post.id };
|
|
178
|
-
} catch (err) {
|
|
179
|
-
counters.postsToday--; // undo on failure
|
|
180
|
-
return { error: err.response?.data?.message || err.message };
|
|
181
|
-
}
|
|
182
|
-
},
|
|
183
|
-
}),
|
|
184
|
-
|
|
185
|
-
man_create_comment: tool({
|
|
186
|
-
description: 'Reply to a post on the MAN feed as this agent.',
|
|
187
|
-
parameters: z.object({
|
|
188
|
-
postId: z.string().describe('ID of the post to comment on'),
|
|
189
|
-
body: z.string().describe('Comment content'),
|
|
190
|
-
}),
|
|
191
|
-
execute: async ({ postId, body }) => {
|
|
192
|
-
if (!agentProfileId) return { error: 'Agent not registered on MAN' };
|
|
193
|
-
const rateErr = checkRateLimits('comment');
|
|
194
|
-
if (rateErr) return { error: rateErr };
|
|
195
|
-
counters.apiCallsThisHour++;
|
|
196
|
-
|
|
197
|
-
try {
|
|
198
|
-
const result = await createComment(postId, { body, agentProfileId });
|
|
199
|
-
const comment = result.data || result;
|
|
200
|
-
return { success: true, commentId: comment.id };
|
|
201
|
-
} catch (err) {
|
|
202
|
-
return { error: err.response?.data?.message || err.message };
|
|
203
|
-
}
|
|
204
|
-
},
|
|
205
|
-
}),
|
|
206
|
-
|
|
207
|
-
man_vote: tool({
|
|
208
|
-
description: 'Upvote a post or comment on the MAN feed.',
|
|
209
|
-
parameters: z.object({
|
|
210
|
-
targetType: z.enum(['POST', 'COMMENT']).describe('What to vote on'),
|
|
211
|
-
targetId: z.string().describe('ID of the post or comment'),
|
|
212
|
-
}),
|
|
213
|
-
execute: async ({ targetType, targetId }) => {
|
|
214
|
-
if (!agentProfileId) return { error: 'Agent not registered on MAN' };
|
|
215
|
-
const rateErr = checkRateLimits('vote');
|
|
216
|
-
if (rateErr) return { error: rateErr };
|
|
217
|
-
counters.apiCallsThisHour++;
|
|
218
|
-
|
|
219
|
-
try {
|
|
220
|
-
await castVote({
|
|
221
|
-
targetType,
|
|
222
|
-
targetId,
|
|
223
|
-
value: 'UP',
|
|
224
|
-
agentProfileId,
|
|
225
|
-
});
|
|
226
|
-
return { success: true };
|
|
227
|
-
} catch (err) {
|
|
228
|
-
return { error: err.response?.data?.message || err.message };
|
|
229
|
-
}
|
|
230
|
-
},
|
|
231
|
-
}),
|
|
232
|
-
|
|
233
|
-
man_search: tool({
|
|
234
|
-
description: 'Search the MAN feed for posts, communities, or users.',
|
|
235
|
-
parameters: z.object({
|
|
236
|
-
query: z.string().describe('Search query'),
|
|
237
|
-
type: z.enum(['posts', 'communities', 'users']).optional().describe('Filter search by type'),
|
|
238
|
-
}),
|
|
239
|
-
execute: async ({ query, type }) => {
|
|
240
|
-
const rateErr = checkRateLimits('search');
|
|
241
|
-
if (rateErr) return { error: rateErr };
|
|
242
|
-
counters.apiCallsThisHour++;
|
|
243
|
-
|
|
244
|
-
try {
|
|
245
|
-
const params = { q: query };
|
|
246
|
-
if (type) params.type = type;
|
|
247
|
-
const result = await searchNetwork(params);
|
|
248
|
-
return result.data || result;
|
|
249
|
-
} catch (err) {
|
|
250
|
-
return { error: err.message };
|
|
251
|
-
}
|
|
252
|
-
},
|
|
253
|
-
}),
|
|
254
|
-
|
|
255
|
-
man_get_mentions: tool({
|
|
256
|
-
description: 'Get posts and comments that mention this agent. Use to find conversations directed at you.',
|
|
257
|
-
parameters: z.object({
|
|
258
|
-
since: z.string().optional().describe('ISO 8601 timestamp to fetch mentions after'),
|
|
259
|
-
limit: z.number().optional().describe('Number of mentions to fetch (default 20)'),
|
|
260
|
-
}),
|
|
261
|
-
execute: async ({ since, limit }) => {
|
|
262
|
-
if (!agentProfileId) return { error: 'Agent not registered on MAN' };
|
|
263
|
-
const rateErr = checkRateLimits('read');
|
|
264
|
-
if (rateErr) return { error: rateErr };
|
|
265
|
-
counters.apiCallsThisHour++;
|
|
266
|
-
|
|
267
|
-
try {
|
|
268
|
-
const params = { pageSize: limit || 20 };
|
|
269
|
-
if (since) params.since = since;
|
|
270
|
-
const result = await getAgentMentions(agentProfileId, params);
|
|
271
|
-
const items = result.data || result;
|
|
272
|
-
if (!Array.isArray(items)) return { mentions: [] };
|
|
273
|
-
return {
|
|
274
|
-
mentions: items.map(m => ({
|
|
275
|
-
id: m.id,
|
|
276
|
-
type: m.postId ? 'comment' : 'post',
|
|
277
|
-
body: (m.body || '').slice(0, 200),
|
|
278
|
-
author: m.agentProfile?.handle || m.villager?.firstName || 'unknown',
|
|
279
|
-
postId: m.postId || m.id,
|
|
280
|
-
createdAt: m.createdAt,
|
|
281
|
-
})),
|
|
282
|
-
};
|
|
283
|
-
} catch (err) {
|
|
284
|
-
return { error: err.message };
|
|
285
|
-
}
|
|
286
|
-
},
|
|
287
|
-
}),
|
|
288
|
-
|
|
289
|
-
man_memory_set: tool({
|
|
290
|
-
description: 'Store a key-value pair in persistent memory. Use to remember things across sessions.',
|
|
291
|
-
parameters: z.object({
|
|
292
|
-
key: z.string().describe('Memory key (e.g., "preferred_communities", "strategy_notes")'),
|
|
293
|
-
value: z.string().describe('Value to store (string or JSON-stringified object)'),
|
|
294
|
-
category: z.string().optional().describe('Category for grouping (e.g., "preferences", "observations")'),
|
|
295
|
-
}),
|
|
296
|
-
execute: async ({ key, value, category }) => {
|
|
297
|
-
if (!agentProfileId) return { error: 'Agent not registered on MAN' };
|
|
298
|
-
const rateErr = checkRateLimits('memory');
|
|
299
|
-
if (rateErr) return { error: rateErr };
|
|
300
|
-
counters.apiCallsThisHour++;
|
|
301
|
-
|
|
302
|
-
try {
|
|
303
|
-
const data = { key, value };
|
|
304
|
-
if (category) data.category = category;
|
|
305
|
-
await upsertAgentMemory(agentProfileId, data);
|
|
306
|
-
return { success: true, key };
|
|
307
|
-
} catch (err) {
|
|
308
|
-
return { error: err.response?.data?.message || err.message };
|
|
309
|
-
}
|
|
310
|
-
},
|
|
311
|
-
}),
|
|
312
|
-
|
|
313
|
-
man_memory_get: tool({
|
|
314
|
-
description: 'Retrieve a specific memory entry by key.',
|
|
315
|
-
parameters: z.object({
|
|
316
|
-
key: z.string().describe('Memory key to retrieve'),
|
|
317
|
-
}),
|
|
318
|
-
execute: async ({ key }) => {
|
|
319
|
-
if (!agentProfileId) return { error: 'Agent not registered on MAN' };
|
|
320
|
-
const rateErr = checkRateLimits('read');
|
|
321
|
-
if (rateErr) return { error: rateErr };
|
|
322
|
-
counters.apiCallsThisHour++;
|
|
323
|
-
|
|
324
|
-
try {
|
|
325
|
-
const result = await getAgentMemoryEntry(agentProfileId, key);
|
|
326
|
-
const entry = result.data || result;
|
|
327
|
-
return { key: entry.key, value: entry.value, category: entry.category };
|
|
328
|
-
} catch (err) {
|
|
329
|
-
if (err.response?.status === 404) return { key, value: null, found: false };
|
|
330
|
-
return { error: err.message };
|
|
331
|
-
}
|
|
332
|
-
},
|
|
333
|
-
}),
|
|
334
|
-
|
|
335
|
-
man_memory_list: tool({
|
|
336
|
-
description: 'List all memory entries, optionally filtered by category.',
|
|
337
|
-
parameters: z.object({
|
|
338
|
-
category: z.string().optional().describe('Filter by category'),
|
|
339
|
-
}),
|
|
340
|
-
execute: async ({ category }) => {
|
|
341
|
-
if (!agentProfileId) return { error: 'Agent not registered on MAN' };
|
|
342
|
-
const rateErr = checkRateLimits('read');
|
|
343
|
-
if (rateErr) return { error: rateErr };
|
|
344
|
-
counters.apiCallsThisHour++;
|
|
345
|
-
|
|
346
|
-
try {
|
|
347
|
-
const params = {};
|
|
348
|
-
if (category) params.category = category;
|
|
349
|
-
const result = await listAgentMemory(agentProfileId, params);
|
|
350
|
-
const entries = result.data || result;
|
|
351
|
-
if (!Array.isArray(entries)) return { entries: [] };
|
|
352
|
-
return {
|
|
353
|
-
entries: entries.map(e => ({
|
|
354
|
-
key: e.key,
|
|
355
|
-
value: e.value,
|
|
356
|
-
category: e.category,
|
|
357
|
-
updatedAt: e.updatedAt,
|
|
358
|
-
})),
|
|
359
|
-
};
|
|
360
|
-
} catch (err) {
|
|
361
|
-
return { error: err.message };
|
|
362
|
-
}
|
|
363
|
-
},
|
|
364
|
-
}),
|
|
365
|
-
|
|
366
|
-
man_memory_delete: tool({
|
|
367
|
-
description: 'Delete a memory entry by key.',
|
|
368
|
-
parameters: z.object({
|
|
369
|
-
key: z.string().describe('Memory key to delete'),
|
|
370
|
-
}),
|
|
371
|
-
execute: async ({ key }) => {
|
|
372
|
-
if (!agentProfileId) return { error: 'Agent not registered on MAN' };
|
|
373
|
-
const rateErr = checkRateLimits('memory');
|
|
374
|
-
if (rateErr) return { error: rateErr };
|
|
375
|
-
counters.apiCallsThisHour++;
|
|
376
|
-
|
|
377
|
-
try {
|
|
378
|
-
await deleteAgentMemoryEntry(agentProfileId, key);
|
|
379
|
-
return { success: true, key };
|
|
380
|
-
} catch (err) {
|
|
381
|
-
return { error: err.response?.data?.message || err.message };
|
|
382
|
-
}
|
|
383
|
-
},
|
|
384
|
-
}),
|
|
385
|
-
};
|
|
386
|
-
}
|
|
387
|
-
|
|
388
81
|
// ── Helpers ─────────────────────────────────────────────
|
|
389
82
|
|
|
390
83
|
function resolveEnvVars(envMap) {
|
|
@@ -5,7 +5,7 @@ import inquirer from 'inquirer';
|
|
|
5
5
|
import { existsSync, readFileSync } from 'fs';
|
|
6
6
|
import { join } from 'path';
|
|
7
7
|
import { execSync } from 'child_process';
|
|
8
|
-
import { isAuthenticated } from '../utils/auth.js';
|
|
8
|
+
import { isAuthenticated, getAccessToken } from '../utils/auth.js';
|
|
9
9
|
import { getConfig, setConfig } from '../utils/config.js';
|
|
10
10
|
import {
|
|
11
11
|
createAgent as apiCreateAgent,
|
|
@@ -72,7 +72,7 @@ export async function agentCreateLocalCommand() {
|
|
|
72
72
|
name: 'tools',
|
|
73
73
|
message: 'Which tools should your agent have?',
|
|
74
74
|
choices: [
|
|
75
|
-
{ name: '
|
|
75
|
+
{ name: 'MyVillageOS MCP (feed, posts, communities, wallet)', value: 'myvillage', checked: true, disabled: 'always enabled' },
|
|
76
76
|
{ name: 'Local Files (read/write project files)', value: 'filesystem', checked: true },
|
|
77
77
|
{ name: 'Gmail', value: 'gmail' },
|
|
78
78
|
{ name: 'Calendar', value: 'calendar' },
|
|
@@ -109,8 +109,8 @@ export async function agentCreateLocalCommand() {
|
|
|
109
109
|
|
|
110
110
|
const agentDir = getAgentDir(answers.name);
|
|
111
111
|
|
|
112
|
-
//
|
|
113
|
-
const tools = ['
|
|
112
|
+
// myvillage is always included even though disabled in checkbox
|
|
113
|
+
const tools = ['myvillage', ...answers.tools.filter(t => t !== 'myvillage')];
|
|
114
114
|
|
|
115
115
|
scaffoldAgent(agentDir, {
|
|
116
116
|
name: answers.name,
|
|
@@ -236,6 +236,23 @@ export async function agentStartCommand(name) {
|
|
|
236
236
|
}
|
|
237
237
|
}
|
|
238
238
|
|
|
239
|
+
// Migrate tools.yaml: replace man-feed with myvillage MCP server
|
|
240
|
+
const toolsConfig = readToolsYaml(name);
|
|
241
|
+
if (toolsConfig.servers?.['man-feed'] && !toolsConfig.servers?.['myvillage']) {
|
|
242
|
+
delete toolsConfig.servers['man-feed'];
|
|
243
|
+
toolsConfig.servers = { myvillage: TOOL_CATALOG['myvillage'], ...toolsConfig.servers };
|
|
244
|
+
writeToolsYaml(name, toolsConfig);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Pass MyVillage credentials to daemon for MCP server
|
|
248
|
+
const accessToken = getAccessToken();
|
|
249
|
+
if (accessToken) {
|
|
250
|
+
process.env.MYVILLAGE_ACCESS_TOKEN = accessToken;
|
|
251
|
+
}
|
|
252
|
+
if (agentConfig.man?.agent_id) {
|
|
253
|
+
process.env.MYVILLAGE_AGENT_ID = agentConfig.man.agent_id;
|
|
254
|
+
}
|
|
255
|
+
|
|
239
256
|
// Fork the daemon process
|
|
240
257
|
const spinner = villageSpinner(`Starting agent "${name}"...`).start();
|
|
241
258
|
|
|
@@ -492,7 +509,7 @@ export async function agentAddToolCommand(name, tool) {
|
|
|
492
509
|
return;
|
|
493
510
|
}
|
|
494
511
|
|
|
495
|
-
const validTools = Object.keys(TOOL_CATALOG).filter(t => t !== '
|
|
512
|
+
const validTools = Object.keys(TOOL_CATALOG).filter(t => t !== 'myvillage');
|
|
496
513
|
if (!validTools.includes(tool)) {
|
|
497
514
|
console.log(chalk.red(` \u2717 Unknown tool "${tool}".`));
|
|
498
515
|
console.log(brand.teal(` Available tools: ${validTools.join(', ')}\n`));
|
|
@@ -530,8 +547,8 @@ export async function agentRemoveToolCommand(name, tool) {
|
|
|
530
547
|
return;
|
|
531
548
|
}
|
|
532
549
|
|
|
533
|
-
if (tool === '
|
|
534
|
-
console.log(chalk.red(' \u2717 Cannot remove
|
|
550
|
+
if (tool === 'myvillage') {
|
|
551
|
+
console.log(chalk.red(' \u2717 Cannot remove myvillage — it is always enabled.\n'));
|
|
535
552
|
return;
|
|
536
553
|
}
|
|
537
554
|
|