@myvillage/cli 1.76.0 → 1.78.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myvillage/cli",
3
- "version": "1.76.0",
3
+ "version": "1.78.0",
4
4
  "description": "MyVillageOS CLI for community developers",
5
5
  "type": "module",
6
6
  "bin": {
@@ -72,7 +72,7 @@ export async function agentLoop(agentName, { signal }) {
72
72
  const anthropic = createAnthropic({ apiKey });
73
73
  model = anthropic(modelId);
74
74
  }
75
- const maxTokens = config.brain?.max_tokens_per_loop || 1000;
75
+ const maxTokens = config.brain?.max_tokens_per_loop || 8000;
76
76
 
77
77
  // Initialize MCP tools
78
78
  let tools;
@@ -292,7 +292,9 @@ Guidelines:
292
292
  const anthropicMeta = result.providerMetadata?.anthropic || {};
293
293
  logActivity(agentDir, {
294
294
  type: 'llm_response',
295
- text: (result.text || '').slice(0, 500),
295
+ // Keep the full response: at ~4 chars/token, 32k chars holds a maxed-out
296
+ // 8k-token reply, so the Logs panel no longer clips mid-sentence.
297
+ text: (result.text || '').slice(0, 32000),
296
298
  tokensUsed: {
297
299
  prompt: result.usage?.inputTokens || 0,
298
300
  completion: result.usage?.outputTokens || 0,
@@ -18,13 +18,14 @@ import {
18
18
  // The villager connects the provider once in MyVillage Studio or at
19
19
  // myvillageproject.ai. These commands only manage the per-agent consent.
20
20
 
21
- const VALID_PROVIDERS = ['google', 'microsoft', 'zoom'];
21
+ const VALID_PROVIDERS = ['google', 'microsoft', 'zoom', 'slack'];
22
22
 
23
23
  // Human-facing labels keyed by the lowercase slug the CLI accepts.
24
24
  const PROVIDER_LABELS = {
25
25
  google: 'Google (Gmail, Calendar, Drive)',
26
26
  microsoft: 'Microsoft 365 (Outlook mail, Calendar)',
27
27
  zoom: 'Zoom',
28
+ slack: 'Slack (channels, messages, search — acts as you)',
28
29
  };
29
30
 
30
31
  function fail(message) {
@@ -209,7 +209,8 @@ export async function agentCreateLocalCommand() {
209
209
 
210
210
  console.log(brand.green(` \u2713 Agent created at ~/.myvillage/agents/${answers.name}/\n`));
211
211
  console.log(brand.teal(' Next steps:'));
212
- console.log(` ${brand.gold(`myvillage agent add-mcp ${answers.name}`)} Add a tool (Gmail, Slack, your own MCP, etc.)`);
212
+ console.log(` ${brand.gold(`myvillage agent add-mcp ${answers.name}`)} Add a tool (GitHub, Twilio, your own MCP, etc.)`);
213
+ console.log(` ${brand.gold(`myvillage agent grant ${answers.name} <provider>`)} Authorize Google, Microsoft, or Slack`);
213
214
  console.log(` ${brand.gold(`myvillage agent start ${answers.name}`)} Launch the agent`);
214
215
  console.log(` ${brand.gold(`myvillage agent edit ${answers.name}`)} Customize the prompt`);
215
216
  console.log(` ${brand.gold(`myvillage agent logs ${answers.name}`)} View activity\n`);
@@ -737,7 +738,8 @@ export async function agentAddToolCommand(name, tool) {
737
738
  if (!validTools.includes(tool)) {
738
739
  console.log(chalk.red(` \u2717 Unknown built-in tool "${tool}".`));
739
740
  console.log(brand.teal(` Built-in tools: ${validTools.join(', ')}`));
740
- console.log(brand.teal(` For Gmail, Slack, Twilio, custom MCPs, etc. use: ${chalk.bold(`myvillage agent add-mcp ${name}`)}\n`));
741
+ console.log(brand.teal(` For GitHub, Twilio, custom MCPs, etc. use: ${chalk.bold(`myvillage agent add-mcp ${name}`)}`));
742
+ console.log(brand.teal(` For Google, Microsoft, or Slack use: ${chalk.bold(`myvillage agent grant ${name} <provider>`)}\n`));
741
743
  return;
742
744
  }
743
745
 
package/src/index.js CHANGED
@@ -536,7 +536,7 @@ export function run() {
536
536
 
537
537
  agentCmd
538
538
  .command('add-tool <name> <tool>')
539
- .description('Add a built-in tool (filesystem, browser) — for everything else (Gmail, GitHub, Slack, custom MCPs) use `add-mcp`')
539
+ .description('Add a built-in tool (filesystem, browser) — for custom MCPs use `add-mcp`, for Google/Microsoft/Slack use `grant`')
540
540
  .action(agentAddToolCommand);
541
541
 
542
542
  agentCmd
@@ -11,10 +11,11 @@ import { stringify as stringifyYaml } from 'yaml';
11
11
  // local-machine resources only; github uses an env var the developer sets
12
12
  // themselves).
13
13
  //
14
- // Everything else — Gmail, Slack, Twilio, custom remote MCPs, anything new
15
- // the community ships — lives as a "recipe" under src/recipes/ that the
16
- // developer installs via `myvillage agent add-mcp` after creation. See
17
- // src/utils/recipes.js.
14
+ // Everything else — Twilio, custom remote MCPs, anything new the community
15
+ // ships — lives as a "recipe" the developer installs via `myvillage agent
16
+ // add-mcp` after creation (see src/utils/recipes.js). OAuth providers (Google,
17
+ // Microsoft, Slack) instead connect once and are authorized per-agent with
18
+ // `myvillage agent grant`.
18
19
 
19
20
  const TOOL_CATALOG = {
20
21
 
@@ -100,8 +101,10 @@ export function scaffoldAgent(agentDir, options) {
100
101
  );
101
102
 
102
103
  // A starter .env file for the developer to populate. Tools/recipes that
103
- // need credentials (Gmail token, Slack bot token, Twilio SID/auth, custom
104
- // headers for remote MCPs) read env vars from this file at agent start.
104
+ // need credentials (Twilio SID/auth, custom headers for remote MCPs) read env
105
+ // vars from this file at agent start. OAuth providers (Google, Microsoft,
106
+ // Slack) are NOT env vars — they connect once and are authorized per-agent
107
+ // with `myvillage agent grant`.
105
108
  // Gitignore-able by convention — it's plaintext on the developer's machine
106
109
  // and isn't transmitted anywhere.
107
110
  writeFileSync(
@@ -122,13 +125,13 @@ function starterEnvFile() {
122
125
  '#',
123
126
  '# Examples (the curated recipes — install with `myvillage agent add-mcp`):',
124
127
  '# GITHUB_PERSONAL_ACCESS_TOKEN=ghp_xxxxxxxxxxxx',
125
- '# SLACK_BOT_TOKEN=xoxb-xxxxxxxxxxxx',
126
- '# SLACK_TEAM_ID=T01234567',
127
128
  '# TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxx',
128
129
  '# TWILIO_API_KEY=SKxxxxxxxxxxxx',
129
130
  '# TWILIO_API_SECRET=xxxxxxxxxxxx',
130
131
  '#',
131
- '# Gmail uses file-based auth (~/.gmail-mcp/credentials.json), no env var needed.',
132
+ '# Google, Microsoft, and Slack need NO env vars — connect them in MyVillage',
133
+ "# Studio (or at myvillageproject.ai), then authorize this agent with:",
134
+ '# myvillage agent grant <agent> google|microsoft|slack',
132
135
  '#',
133
136
  '# This file is plaintext — keep it out of version control.',
134
137
  '',
@@ -162,7 +165,7 @@ function generateAgentConfig({ name, displayName, description, checkInInterval,
162
165
  brain: {
163
166
  provider: provider || 'anthropic',
164
167
  model: model || (provider === 'openai' ? 'gpt-4o' : 'claude-sonnet-4-5-20250929'),
165
- max_tokens_per_loop: 1000,
168
+ max_tokens_per_loop: 8000,
166
169
  fallback_provider: null,
167
170
  },
168
171
 
@@ -45,6 +45,27 @@ import { parse as parseYaml } from 'yaml';
45
45
  import { getConfig } from './config.js';
46
46
  import { getAccessToken } from './auth.js';
47
47
 
48
+ // ── Deprecated registry recipes ─────────────────────────
49
+ //
50
+ // Curated recipes retired in favor of one-click OAuth provider connect
51
+ // (`myvillage agent grant <agent> <provider>`). We hide them from the registry
52
+ // listing and block a direct fetch so there's a single, obvious path — even if
53
+ // the backend registry still serves the old entry. Keyed by registry recipe
54
+ // name → the provider slug that replaces it. Only affects bare-name registry
55
+ // loads; a developer's own `--from ./slack.yaml` is untouched.
56
+ const DEPRECATED_REGISTRY_RECIPES = {
57
+ slack: 'slack', // bot-token Slack MCP → "Sign in with Slack" (acts as you)
58
+ };
59
+
60
+ function deprecationMessage(name, providerSlug) {
61
+ const label = name.charAt(0).toUpperCase() + name.slice(1);
62
+ return (
63
+ `The "${name}" bot-token tool has been replaced by one-click ${label} sign-in. ` +
64
+ `Connect ${label} in MyVillage Studio (or at myvillageproject.ai), then run ` +
65
+ `\`myvillage agent grant <agent> ${providerSlug}\` — no token to copy.`
66
+ );
67
+ }
68
+
48
69
  // ── Public API ──────────────────────────────────────────
49
70
 
50
71
  /**
@@ -81,12 +102,20 @@ export async function listRegistryRecipes() {
81
102
  throw await registryError(res, 'list recipes');
82
103
  }
83
104
  const body = await res.json();
84
- return body.recipes || [];
105
+ // Hide retired recipes (e.g. the bot-token Slack MCP) so they never show up
106
+ // as an option — the OAuth provider path supersedes them.
107
+ return (body.recipes || []).filter(
108
+ (r) => !Object.hasOwn(DEPRECATED_REGISTRY_RECIPES, String(r?.name || '').toLowerCase()),
109
+ );
85
110
  }
86
111
 
87
112
  // ── Loaders ─────────────────────────────────────────────
88
113
 
89
114
  async function loadRecipeFromRegistry(name) {
115
+ const slug = String(name || '').toLowerCase();
116
+ if (Object.hasOwn(DEPRECATED_REGISTRY_RECIPES, slug)) {
117
+ throw new Error(deprecationMessage(slug, DEPRECATED_REGISTRY_RECIPES[slug]));
118
+ }
90
119
  const url = `${getConfig().apiBaseUrl}/recipes/${encodeURIComponent(name)}`;
91
120
  const res = await authedFetch(url);
92
121
  if (!res.ok) {