@tuttiai/cli 0.2.0 → 0.4.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/index.js CHANGED
@@ -123,7 +123,14 @@ import { resolve } from "path";
123
123
  import { createInterface } from "readline/promises";
124
124
  import chalk2 from "chalk";
125
125
  import ora from "ora";
126
- import { TuttiRuntime, ScoreLoader } from "@tuttiai/core";
126
+ import {
127
+ TuttiRuntime,
128
+ ScoreLoader,
129
+ AnthropicProvider,
130
+ OpenAIProvider,
131
+ GeminiProvider,
132
+ SecretsManager
133
+ } from "@tuttiai/core";
127
134
  async function runCommand(scorePath) {
128
135
  const file = resolve(scorePath ?? "./tutti.score.ts");
129
136
  if (!existsSync2(file)) {
@@ -144,6 +151,25 @@ async function runCommand(scorePath) {
144
151
  );
145
152
  process.exit(1);
146
153
  }
154
+ const providerKeyMap = [
155
+ [AnthropicProvider, "ANTHROPIC_API_KEY"],
156
+ [OpenAIProvider, "OPENAI_API_KEY"],
157
+ [GeminiProvider, "GEMINI_API_KEY"]
158
+ ];
159
+ for (const [ProviderClass, envVar] of providerKeyMap) {
160
+ if (score.provider instanceof ProviderClass) {
161
+ const key = SecretsManager.optional(envVar);
162
+ if (!key) {
163
+ console.error(
164
+ chalk2.red(
165
+ `Missing API key: ${envVar}
166
+ Add it to your .env file: ${envVar}=your_value_here`
167
+ )
168
+ );
169
+ process.exit(1);
170
+ }
171
+ }
172
+ }
147
173
  const runtime = new TuttiRuntime(score);
148
174
  const spinner = ora({ color: "cyan" });
149
175
  runtime.events.on("agent:start", (e) => {
@@ -164,6 +190,19 @@ async function runCommand(scorePath) {
164
190
  runtime.events.on("tool:error", (e) => {
165
191
  console.log(chalk2.red(` Error in tool: ${e.tool_name}`));
166
192
  });
193
+ runtime.events.on("security:injection_detected", (e) => {
194
+ console.log(
195
+ chalk2.yellow(
196
+ ` [security] Potential prompt injection detected in: ${e.tool_name}`
197
+ )
198
+ );
199
+ });
200
+ runtime.events.on("budget:warning", () => {
201
+ console.log(chalk2.yellow(" Approaching token budget (80%)"));
202
+ });
203
+ runtime.events.on("budget:exceeded", () => {
204
+ console.log(chalk2.red(" Token budget exceeded. Stopping."));
205
+ });
167
206
  const rl = createInterface({
168
207
  input: process.stdin,
169
208
  output: process.stdout
@@ -191,7 +230,12 @@ ${result.output}
191
230
  spinner.stop();
192
231
  console.error(
193
232
  chalk2.red(
194
- `Error: ${err instanceof Error ? err.message : err}`
233
+ `[tutti] Something went wrong: ${err instanceof Error ? err.message : err}`
234
+ )
235
+ );
236
+ console.error(
237
+ chalk2.dim(
238
+ 'Run "tutti-ai check" to validate your score file.'
195
239
  )
196
240
  );
197
241
  }
@@ -203,15 +247,225 @@ ${result.output}
203
247
  process.exit(0);
204
248
  }
205
249
 
250
+ // src/commands/add.ts
251
+ import { existsSync as existsSync3, readFileSync } from "fs";
252
+ import { resolve as resolve2 } from "path";
253
+ import { execSync } from "child_process";
254
+ import chalk3 from "chalk";
255
+ import ora2 from "ora";
256
+ var OFFICIAL_VOICES = {
257
+ filesystem: {
258
+ package: "@tuttiai/filesystem",
259
+ setup: ` Add to your score:
260
+ ${chalk3.cyan('import { FilesystemVoice } from "@tuttiai/filesystem"')}
261
+ ${chalk3.cyan("voices: [new FilesystemVoice()]")}`
262
+ },
263
+ github: {
264
+ package: "@tuttiai/github",
265
+ setup: ` Add ${chalk3.bold("GITHUB_TOKEN")} to your .env file:
266
+ ${chalk3.cyan("GITHUB_TOKEN=ghp_your_token_here")}
267
+
268
+ Add to your score:
269
+ ${chalk3.cyan('import { GitHubVoice } from "@tuttiai/github"')}
270
+ ${chalk3.cyan("voices: [new GitHubVoice()]")}`
271
+ },
272
+ playwright: {
273
+ package: "@tuttiai/playwright",
274
+ setup: ` Install the browser:
275
+ ${chalk3.cyan("npx playwright install chromium")}
276
+
277
+ Add to your score:
278
+ ${chalk3.cyan('import { PlaywrightVoice } from "@tuttiai/playwright"')}
279
+ ${chalk3.cyan("voices: [new PlaywrightVoice()]")}`
280
+ }
281
+ };
282
+ function resolvePackageName(input) {
283
+ if (OFFICIAL_VOICES[input]) {
284
+ return OFFICIAL_VOICES[input].package;
285
+ }
286
+ if (input.startsWith("@")) {
287
+ return input;
288
+ }
289
+ return `@tuttiai/${input}`;
290
+ }
291
+ function isAlreadyInstalled(packageName) {
292
+ const pkgPath = resolve2(process.cwd(), "package.json");
293
+ if (!existsSync3(pkgPath)) return false;
294
+ try {
295
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
296
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
297
+ return packageName in deps;
298
+ } catch {
299
+ return false;
300
+ }
301
+ }
302
+ async function addCommand(voiceName) {
303
+ const packageName = resolvePackageName(voiceName);
304
+ const pkgPath = resolve2(process.cwd(), "package.json");
305
+ if (!existsSync3(pkgPath)) {
306
+ console.error(
307
+ chalk3.red("No package.json found in the current directory.")
308
+ );
309
+ console.error(
310
+ chalk3.dim('Run "tutti-ai init" to create a new project first.')
311
+ );
312
+ process.exit(1);
313
+ }
314
+ if (isAlreadyInstalled(packageName)) {
315
+ console.log(chalk3.green(` \u2714 ${packageName} is already installed`));
316
+ return;
317
+ }
318
+ const spinner = ora2(`Installing ${packageName}...`).start();
319
+ try {
320
+ execSync(`npm install ${packageName}`, {
321
+ cwd: process.cwd(),
322
+ stdio: "pipe"
323
+ });
324
+ spinner.succeed(`Installed ${packageName}`);
325
+ } catch (error) {
326
+ spinner.fail(`Failed to install ${packageName}`);
327
+ const message = error instanceof Error ? error.message : String(error);
328
+ console.error(chalk3.red(message));
329
+ process.exit(1);
330
+ }
331
+ const official = OFFICIAL_VOICES[voiceName];
332
+ if (official) {
333
+ console.log();
334
+ console.log(" Setup:");
335
+ console.log(official.setup);
336
+ console.log();
337
+ } else {
338
+ console.log();
339
+ console.log(
340
+ chalk3.dim(" Check the package README for setup instructions.")
341
+ );
342
+ console.log();
343
+ }
344
+ }
345
+
346
+ // src/commands/check.ts
347
+ import { existsSync as existsSync4 } from "fs";
348
+ import { resolve as resolve3 } from "path";
349
+ import chalk4 from "chalk";
350
+ import {
351
+ ScoreLoader as ScoreLoader2,
352
+ AnthropicProvider as AnthropicProvider2,
353
+ OpenAIProvider as OpenAIProvider2,
354
+ GeminiProvider as GeminiProvider2,
355
+ SecretsManager as SecretsManager2
356
+ } from "@tuttiai/core";
357
+ var ok = (msg) => console.log(chalk4.green(" \u2714 " + msg));
358
+ var fail = (msg) => console.log(chalk4.red(" \u2718 " + msg));
359
+ async function checkCommand(scorePath) {
360
+ const file = resolve3(scorePath ?? "./tutti.score.ts");
361
+ console.log(chalk4.cyan(`
362
+ Checking ${file}...
363
+ `));
364
+ if (!existsSync4(file)) {
365
+ fail("Score file not found: " + file);
366
+ process.exit(1);
367
+ }
368
+ let score;
369
+ try {
370
+ score = await ScoreLoader2.load(file);
371
+ ok("Score file is valid");
372
+ } catch (err) {
373
+ fail("Score validation failed");
374
+ console.error(
375
+ chalk4.red(
376
+ " " + (err instanceof Error ? err.message : String(err))
377
+ )
378
+ );
379
+ process.exit(1);
380
+ }
381
+ let hasErrors = false;
382
+ const providerChecks = [
383
+ [AnthropicProvider2, "AnthropicProvider", "ANTHROPIC_API_KEY"],
384
+ [OpenAIProvider2, "OpenAIProvider", "OPENAI_API_KEY"],
385
+ [GeminiProvider2, "GeminiProvider", "GEMINI_API_KEY"]
386
+ ];
387
+ let providerDetected = false;
388
+ for (const [ProviderClass, name, envVar] of providerChecks) {
389
+ if (score.provider instanceof ProviderClass) {
390
+ providerDetected = true;
391
+ const key = SecretsManager2.optional(envVar);
392
+ if (key) {
393
+ ok("Provider: " + name + " (" + envVar + " is set)");
394
+ } else {
395
+ fail("Provider: " + name + " (" + envVar + " is NOT set)");
396
+ hasErrors = true;
397
+ }
398
+ }
399
+ }
400
+ if (!providerDetected) {
401
+ ok("Provider: custom LLMProvider");
402
+ }
403
+ const agentKeys = Object.keys(score.agents);
404
+ ok(agentKeys.length + " agent" + (agentKeys.length === 1 ? "" : "s") + " configured");
405
+ for (const [agentKey, agent] of Object.entries(score.agents)) {
406
+ for (const voice of agent.voices) {
407
+ const voiceName = voice.name;
408
+ const voiceEnvMap = {
409
+ github: "GITHUB_TOKEN"
410
+ };
411
+ const envVar = voiceEnvMap[voiceName];
412
+ if (envVar) {
413
+ const key = SecretsManager2.optional(envVar);
414
+ if (key) {
415
+ ok(
416
+ "Voice: " + voiceName + " on " + agentKey + " (" + envVar + " is set)"
417
+ );
418
+ } else {
419
+ fail(
420
+ "Voice: " + voiceName + " on " + agentKey + " (" + envVar + " is NOT set)"
421
+ );
422
+ hasErrors = true;
423
+ }
424
+ } else {
425
+ ok("Voice: " + voiceName + " on " + agentKey + " (installed)");
426
+ }
427
+ }
428
+ }
429
+ console.log("");
430
+ if (hasErrors) {
431
+ console.log(
432
+ chalk4.yellow("Some checks failed. Fix the issues above and re-run.")
433
+ );
434
+ process.exit(1);
435
+ } else {
436
+ console.log(
437
+ chalk4.green("All checks passed.") + chalk4.dim(" Run tutti-ai run to start.")
438
+ );
439
+ }
440
+ }
441
+
206
442
  // src/index.ts
207
443
  config();
444
+ process.on("unhandledRejection", (reason) => {
445
+ console.error("[tutti] Unhandled error:", reason);
446
+ console.error("Report at github.com/tuttiai/tutti/issues");
447
+ process.exit(1);
448
+ });
449
+ process.on("uncaughtException", (err) => {
450
+ console.error("[tutti] Fatal error:", err.message);
451
+ process.exit(1);
452
+ });
208
453
  var program = new Command();
209
- program.name("tutti-ai").description("Tutti \u2014 multi-agent orchestration. All agents. All together.").version("0.2.0");
454
+ program.name("tutti-ai").description("Tutti \u2014 multi-agent orchestration. All agents. All together.").version("0.4.0");
210
455
  program.command("init [project-name]").description("Create a new Tutti project").action(async (projectName) => {
211
456
  await initCommand(projectName);
212
457
  });
213
458
  program.command("run [score]").description("Run a Tutti score interactively").action(async (score) => {
214
459
  await runCommand(score);
215
460
  });
461
+ program.command("add <voice>").description("Add a voice to your project").action(async (voice) => {
462
+ await addCommand(voice);
463
+ });
464
+ program.command("check [score]").description("Validate a score file without running it").action(async (score) => {
465
+ await checkCommand(score);
466
+ });
467
+ program.command("doctor [score]").description("Alias for check \u2014 validate a score file").action(async (score) => {
468
+ await checkCommand(score);
469
+ });
216
470
  program.parse();
217
471
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/commands/run.ts"],"sourcesContent":["import { config } from \"dotenv\";\nconfig();\n\nimport { Command } from \"commander\";\nimport { initCommand } from \"./commands/init.js\";\nimport { runCommand } from \"./commands/run.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"tutti-ai\")\n .description(\"Tutti — multi-agent orchestration. All agents. All together.\")\n .version(\"0.2.0\");\n\nprogram\n .command(\"init [project-name]\")\n .description(\"Create a new Tutti project\")\n .action(async (projectName?: string) => {\n await initCommand(projectName);\n });\n\nprogram\n .command(\"run [score]\")\n .description(\"Run a Tutti score interactively\")\n .action(async (score?: string) => {\n await runCommand(score);\n });\n\nprogram.parse();\n","import { mkdirSync, writeFileSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport chalk from \"chalk\";\nimport Enquirer from \"enquirer\";\n\nconst { prompt } = Enquirer;\n\nexport async function initCommand(projectName?: string): Promise<void> {\n if (!projectName) {\n const response = await prompt<{ projectName: string }>({\n type: \"input\",\n name: \"projectName\",\n message: \"Project name?\",\n });\n projectName = response.projectName;\n }\n\n if (!projectName) {\n console.error(chalk.red(\"Project name is required.\"));\n process.exit(1);\n }\n\n const dir = join(process.cwd(), projectName);\n\n if (existsSync(dir)) {\n console.error(chalk.red(`Directory already exists: ${projectName}/`));\n process.exit(1);\n }\n\n mkdirSync(dir, { recursive: true });\n\n const files: Record<string, string> = {\n \"package.json\": JSON.stringify(\n {\n name: projectName,\n version: \"0.0.1\",\n type: \"module\",\n scripts: {\n dev: \"tsx watch tutti.score.ts\",\n start: \"tsx tutti.score.ts\",\n },\n dependencies: {\n \"@tuttiai/core\": \"*\",\n \"@tuttiai/types\": \"*\",\n },\n devDependencies: {\n tsx: \"^4.0.0\",\n typescript: \"^5.7.0\",\n },\n },\n null,\n 2,\n ),\n\n \".env.example\": \"ANTHROPIC_API_KEY=your_key_here\\n\",\n\n \".gitignore\": \"node_modules\\ndist\\n.env\\n\",\n\n \"tsconfig.json\": JSON.stringify(\n {\n compilerOptions: {\n strict: true,\n target: \"ES2022\",\n module: \"ES2022\",\n moduleResolution: \"bundler\",\n esModuleInterop: true,\n skipLibCheck: true,\n outDir: \"dist\",\n rootDir: \".\",\n },\n include: [\".\"],\n },\n null,\n 2,\n ),\n\n \"tutti.score.ts\": `import { defineScore, AnthropicProvider } from \"@tuttiai/core\"\n\nexport default defineScore({\n provider: new AnthropicProvider(),\n default_model: \"claude-sonnet-4-20250514\",\n agents: {\n assistant: {\n name: \"Assistant\",\n system_prompt: \"You are a helpful assistant.\",\n voices: [],\n }\n }\n})\n`,\n\n \"README.md\": `# ${projectName}\n\nA Tutti agent project. All agents. All together.\n\n## Setup\n\n\\`\\`\\`bash\ncp .env.example .env\n# Add your ANTHROPIC_API_KEY to .env\nnpm install\n\\`\\`\\`\n\n## Run\n\n\\`\\`\\`bash\nnpm run dev\n\\`\\`\\`\n`,\n };\n\n for (const [filename, content] of Object.entries(files)) {\n writeFileSync(join(dir, filename), content);\n }\n\n console.log();\n console.log(chalk.green(` ✔ Created ${projectName}/`));\n console.log();\n console.log(\" Next steps:\");\n console.log(chalk.cyan(` cd ${projectName}`));\n console.log(chalk.cyan(\" cp .env.example .env\"));\n console.log(chalk.cyan(\" npm install\"));\n console.log(chalk.cyan(\" npm run dev\"));\n console.log();\n}\n","import { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { createInterface } from \"node:readline/promises\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { TuttiRuntime, ScoreLoader } from \"@tuttiai/core\";\n\nexport async function runCommand(scorePath?: string): Promise<void> {\n const file = resolve(scorePath ?? \"./tutti.score.ts\");\n\n if (!existsSync(file)) {\n console.error(chalk.red(`Score file not found: ${file}`));\n console.error(\n chalk.dim('Run \"tutti-ai init\" to create a new project.'),\n );\n process.exit(1);\n }\n\n let score;\n try {\n score = await ScoreLoader.load(file);\n } catch (err) {\n console.error(\n chalk.red(\n `Failed to load score: ${err instanceof Error ? err.message : err}`,\n ),\n );\n process.exit(1);\n }\n\n const runtime = new TuttiRuntime(score);\n const spinner = ora({ color: \"cyan\" });\n\n // Event-based execution trace\n runtime.events.on(\"agent:start\", (e) => {\n console.log(chalk.cyan(`Running agent: ${e.agent_name}`));\n });\n\n runtime.events.on(\"llm:request\", () => {\n spinner.start(\"Thinking...\");\n });\n\n runtime.events.on(\"llm:response\", () => {\n spinner.stop();\n });\n\n runtime.events.on(\"tool:start\", (e) => {\n console.log(chalk.dim(` Using tool: ${e.tool_name}`));\n });\n\n runtime.events.on(\"tool:end\", (e) => {\n console.log(chalk.dim(` Done: ${e.tool_name}`));\n });\n\n runtime.events.on(\"tool:error\", (e) => {\n console.log(chalk.red(` Error in tool: ${e.tool_name}`));\n });\n\n // REPL\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n console.log(chalk.dim('Tutti REPL — type \"exit\" to quit\\n'));\n\n let sessionId: string | undefined;\n\n // Handle Ctrl+C\n process.on(\"SIGINT\", () => {\n console.log(chalk.dim(\"\\nGoodbye!\"));\n rl.close();\n process.exit(0);\n });\n\n try {\n while (true) {\n const input = await rl.question(chalk.cyan(\"> \"));\n const trimmed = input.trim();\n\n if (!trimmed) continue;\n if (trimmed === \"exit\" || trimmed === \"quit\") break;\n\n try {\n const result = await runtime.run(\"assistant\", trimmed, sessionId);\n sessionId = result.session_id;\n console.log(`\\n${result.output}\\n`);\n } catch (err) {\n spinner.stop();\n console.error(\n chalk.red(\n `Error: ${err instanceof Error ? err.message : err}`,\n ),\n );\n }\n }\n } catch {\n // readline closed\n }\n\n console.log(chalk.dim(\"Goodbye!\"));\n rl.close();\n process.exit(0);\n}\n"],"mappings":"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","names":["existsSync","chalk"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/commands/run.ts","../src/commands/add.ts","../src/commands/check.ts"],"sourcesContent":["import { config } from \"dotenv\";\nconfig();\n\nprocess.on(\"unhandledRejection\", (reason) => {\n console.error(\"[tutti] Unhandled error:\", reason);\n console.error(\"Report at github.com/tuttiai/tutti/issues\");\n process.exit(1);\n});\n\nprocess.on(\"uncaughtException\", (err) => {\n console.error(\"[tutti] Fatal error:\", err.message);\n process.exit(1);\n});\n\nimport { Command } from \"commander\";\nimport { initCommand } from \"./commands/init.js\";\nimport { runCommand } from \"./commands/run.js\";\nimport { addCommand } from \"./commands/add.js\";\nimport { checkCommand } from \"./commands/check.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"tutti-ai\")\n .description(\"Tutti — multi-agent orchestration. All agents. All together.\")\n .version(\"0.4.0\");\n\nprogram\n .command(\"init [project-name]\")\n .description(\"Create a new Tutti project\")\n .action(async (projectName?: string) => {\n await initCommand(projectName);\n });\n\nprogram\n .command(\"run [score]\")\n .description(\"Run a Tutti score interactively\")\n .action(async (score?: string) => {\n await runCommand(score);\n });\n\nprogram\n .command(\"add <voice>\")\n .description(\"Add a voice to your project\")\n .action(async (voice: string) => {\n await addCommand(voice);\n });\n\nprogram\n .command(\"check [score]\")\n .description(\"Validate a score file without running it\")\n .action(async (score?: string) => {\n await checkCommand(score);\n });\n\nprogram\n .command(\"doctor [score]\")\n .description(\"Alias for check — validate a score file\")\n .action(async (score?: string) => {\n await checkCommand(score);\n });\n\nprogram.parse();\n","import { mkdirSync, writeFileSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport chalk from \"chalk\";\nimport Enquirer from \"enquirer\";\n\nconst { prompt } = Enquirer;\n\nexport async function initCommand(projectName?: string): Promise<void> {\n if (!projectName) {\n const response = await prompt<{ projectName: string }>({\n type: \"input\",\n name: \"projectName\",\n message: \"Project name?\",\n });\n projectName = response.projectName;\n }\n\n if (!projectName) {\n console.error(chalk.red(\"Project name is required.\"));\n process.exit(1);\n }\n\n const dir = join(process.cwd(), projectName);\n\n if (existsSync(dir)) {\n console.error(chalk.red(`Directory already exists: ${projectName}/`));\n process.exit(1);\n }\n\n mkdirSync(dir, { recursive: true });\n\n const files: Record<string, string> = {\n \"package.json\": JSON.stringify(\n {\n name: projectName,\n version: \"0.0.1\",\n type: \"module\",\n scripts: {\n dev: \"tsx watch tutti.score.ts\",\n start: \"tsx tutti.score.ts\",\n },\n dependencies: {\n \"@tuttiai/core\": \"*\",\n \"@tuttiai/types\": \"*\",\n },\n devDependencies: {\n tsx: \"^4.0.0\",\n typescript: \"^5.7.0\",\n },\n },\n null,\n 2,\n ),\n\n \".env.example\": \"ANTHROPIC_API_KEY=your_key_here\\n\",\n\n \".gitignore\": \"node_modules\\ndist\\n.env\\n\",\n\n \"tsconfig.json\": JSON.stringify(\n {\n compilerOptions: {\n strict: true,\n target: \"ES2022\",\n module: \"ES2022\",\n moduleResolution: \"bundler\",\n esModuleInterop: true,\n skipLibCheck: true,\n outDir: \"dist\",\n rootDir: \".\",\n },\n include: [\".\"],\n },\n null,\n 2,\n ),\n\n \"tutti.score.ts\": `import { defineScore, AnthropicProvider } from \"@tuttiai/core\"\n\nexport default defineScore({\n provider: new AnthropicProvider(),\n default_model: \"claude-sonnet-4-20250514\",\n agents: {\n assistant: {\n name: \"Assistant\",\n system_prompt: \"You are a helpful assistant.\",\n voices: [],\n }\n }\n})\n`,\n\n \"README.md\": `# ${projectName}\n\nA Tutti agent project. All agents. All together.\n\n## Setup\n\n\\`\\`\\`bash\ncp .env.example .env\n# Add your ANTHROPIC_API_KEY to .env\nnpm install\n\\`\\`\\`\n\n## Run\n\n\\`\\`\\`bash\nnpm run dev\n\\`\\`\\`\n`,\n };\n\n for (const [filename, content] of Object.entries(files)) {\n writeFileSync(join(dir, filename), content);\n }\n\n console.log();\n console.log(chalk.green(` ✔ Created ${projectName}/`));\n console.log();\n console.log(\" Next steps:\");\n console.log(chalk.cyan(` cd ${projectName}`));\n console.log(chalk.cyan(\" cp .env.example .env\"));\n console.log(chalk.cyan(\" npm install\"));\n console.log(chalk.cyan(\" npm run dev\"));\n console.log();\n}\n","import { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { createInterface } from \"node:readline/promises\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport {\n TuttiRuntime,\n ScoreLoader,\n AnthropicProvider,\n OpenAIProvider,\n GeminiProvider,\n SecretsManager,\n} from \"@tuttiai/core\";\n\nexport async function runCommand(scorePath?: string): Promise<void> {\n const file = resolve(scorePath ?? \"./tutti.score.ts\");\n\n if (!existsSync(file)) {\n console.error(chalk.red(`Score file not found: ${file}`));\n console.error(\n chalk.dim('Run \"tutti-ai init\" to create a new project.'),\n );\n process.exit(1);\n }\n\n let score;\n try {\n score = await ScoreLoader.load(file);\n } catch (err) {\n console.error(\n chalk.red(\n `Failed to load score: ${err instanceof Error ? err.message : err}`,\n ),\n );\n process.exit(1);\n }\n\n // Validate that the provider has a valid API key\n const providerKeyMap: [unknown, string][] = [\n [AnthropicProvider, \"ANTHROPIC_API_KEY\"],\n [OpenAIProvider, \"OPENAI_API_KEY\"],\n [GeminiProvider, \"GEMINI_API_KEY\"],\n ];\n\n for (const [ProviderClass, envVar] of providerKeyMap) {\n if (score.provider instanceof (ProviderClass as new (...args: unknown[]) => unknown)) {\n const key = SecretsManager.optional(envVar);\n if (!key) {\n console.error(\n chalk.red(\n `Missing API key: ${envVar}\\n` +\n `Add it to your .env file: ${envVar}=your_value_here`,\n ),\n );\n process.exit(1);\n }\n }\n }\n\n const runtime = new TuttiRuntime(score);\n const spinner = ora({ color: \"cyan\" });\n\n // Event-based execution trace\n runtime.events.on(\"agent:start\", (e) => {\n console.log(chalk.cyan(`Running agent: ${e.agent_name}`));\n });\n\n runtime.events.on(\"llm:request\", () => {\n spinner.start(\"Thinking...\");\n });\n\n runtime.events.on(\"llm:response\", () => {\n spinner.stop();\n });\n\n runtime.events.on(\"tool:start\", (e) => {\n console.log(chalk.dim(` Using tool: ${e.tool_name}`));\n });\n\n runtime.events.on(\"tool:end\", (e) => {\n console.log(chalk.dim(` Done: ${e.tool_name}`));\n });\n\n runtime.events.on(\"tool:error\", (e) => {\n console.log(chalk.red(` Error in tool: ${e.tool_name}`));\n });\n\n runtime.events.on(\"security:injection_detected\", (e) => {\n console.log(\n chalk.yellow(\n ` [security] Potential prompt injection detected in: ${e.tool_name}`,\n ),\n );\n });\n\n runtime.events.on(\"budget:warning\", () => {\n console.log(chalk.yellow(\" Approaching token budget (80%)\"));\n });\n\n runtime.events.on(\"budget:exceeded\", () => {\n console.log(chalk.red(\" Token budget exceeded. Stopping.\"));\n });\n\n // REPL\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n console.log(chalk.dim('Tutti REPL — type \"exit\" to quit\\n'));\n\n let sessionId: string | undefined;\n\n // Handle Ctrl+C\n process.on(\"SIGINT\", () => {\n console.log(chalk.dim(\"\\nGoodbye!\"));\n rl.close();\n process.exit(0);\n });\n\n try {\n while (true) {\n const input = await rl.question(chalk.cyan(\"> \"));\n const trimmed = input.trim();\n\n if (!trimmed) continue;\n if (trimmed === \"exit\" || trimmed === \"quit\") break;\n\n try {\n const result = await runtime.run(\"assistant\", trimmed, sessionId);\n sessionId = result.session_id;\n console.log(`\\n${result.output}\\n`);\n } catch (err) {\n spinner.stop();\n console.error(\n chalk.red(\n `[tutti] Something went wrong: ${err instanceof Error ? err.message : err}`,\n ),\n );\n console.error(\n chalk.dim(\n 'Run \"tutti-ai check\" to validate your score file.',\n ),\n );\n }\n }\n } catch {\n // readline closed\n }\n\n console.log(chalk.dim(\"Goodbye!\"));\n rl.close();\n process.exit(0);\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { execSync } from \"node:child_process\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\n\nconst OFFICIAL_VOICES: Record<string, { package: string; setup: string }> = {\n filesystem: {\n package: \"@tuttiai/filesystem\",\n setup: ` Add to your score:\n ${chalk.cyan('import { FilesystemVoice } from \"@tuttiai/filesystem\"')}\n ${chalk.cyan(\"voices: [new FilesystemVoice()]\")}`,\n },\n github: {\n package: \"@tuttiai/github\",\n setup: ` Add ${chalk.bold(\"GITHUB_TOKEN\")} to your .env file:\n ${chalk.cyan(\"GITHUB_TOKEN=ghp_your_token_here\")}\n\n Add to your score:\n ${chalk.cyan('import { GitHubVoice } from \"@tuttiai/github\"')}\n ${chalk.cyan(\"voices: [new GitHubVoice()]\")}`,\n },\n playwright: {\n package: \"@tuttiai/playwright\",\n setup: ` Install the browser:\n ${chalk.cyan(\"npx playwright install chromium\")}\n\n Add to your score:\n ${chalk.cyan('import { PlaywrightVoice } from \"@tuttiai/playwright\"')}\n ${chalk.cyan(\"voices: [new PlaywrightVoice()]\")}`,\n },\n};\n\nfunction resolvePackageName(input: string): string {\n // Known official voice\n if (OFFICIAL_VOICES[input]) {\n return OFFICIAL_VOICES[input].package;\n }\n // Already a scoped package\n if (input.startsWith(\"@\")) {\n return input;\n }\n // Try @tuttiai/<name> convention\n return `@tuttiai/${input}`;\n}\n\nfunction isAlreadyInstalled(packageName: string): boolean {\n const pkgPath = resolve(process.cwd(), \"package.json\");\n if (!existsSync(pkgPath)) return false;\n\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n return packageName in deps;\n } catch {\n return false;\n }\n}\n\nexport async function addCommand(voiceName: string): Promise<void> {\n const packageName = resolvePackageName(voiceName);\n\n // Check if package.json exists in cwd\n const pkgPath = resolve(process.cwd(), \"package.json\");\n if (!existsSync(pkgPath)) {\n console.error(\n chalk.red(\"No package.json found in the current directory.\"),\n );\n console.error(\n chalk.dim('Run \"tutti-ai init\" to create a new project first.'),\n );\n process.exit(1);\n }\n\n // Check if already installed\n if (isAlreadyInstalled(packageName)) {\n console.log(chalk.green(` ✔ ${packageName} is already installed`));\n return;\n }\n\n // Install\n const spinner = ora(`Installing ${packageName}...`).start();\n\n try {\n execSync(`npm install ${packageName}`, {\n cwd: process.cwd(),\n stdio: \"pipe\",\n });\n spinner.succeed(`Installed ${packageName}`);\n } catch (error) {\n spinner.fail(`Failed to install ${packageName}`);\n const message =\n error instanceof Error ? error.message : String(error);\n console.error(chalk.red(message));\n process.exit(1);\n }\n\n // Print setup instructions\n const official = OFFICIAL_VOICES[voiceName];\n if (official) {\n console.log();\n console.log(\" Setup:\");\n console.log(official.setup);\n console.log();\n } else {\n console.log();\n console.log(\n chalk.dim(\" Check the package README for setup instructions.\"),\n );\n console.log();\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport chalk from \"chalk\";\nimport {\n ScoreLoader,\n AnthropicProvider,\n OpenAIProvider,\n GeminiProvider,\n SecretsManager,\n} from \"@tuttiai/core\";\n\nconst ok = (msg: string) => console.log(chalk.green(\" \\u2714 \" + msg));\nconst fail = (msg: string) => console.log(chalk.red(\" \\u2718 \" + msg));\n\nexport async function checkCommand(scorePath?: string): Promise<void> {\n const file = resolve(scorePath ?? \"./tutti.score.ts\");\n\n console.log(chalk.cyan(`\\nChecking ${file}...\\n`));\n\n if (!existsSync(file)) {\n fail(\"Score file not found: \" + file);\n process.exit(1);\n }\n\n // 1. Load and validate\n let score;\n try {\n score = await ScoreLoader.load(file);\n ok(\"Score file is valid\");\n } catch (err) {\n fail(\"Score validation failed\");\n console.error(\n chalk.red(\n \" \" + (err instanceof Error ? err.message : String(err)),\n ),\n );\n process.exit(1);\n }\n\n let hasErrors = false;\n\n // 2. Check provider and API key\n const providerChecks: [unknown, string, string][] = [\n [AnthropicProvider, \"AnthropicProvider\", \"ANTHROPIC_API_KEY\"],\n [OpenAIProvider, \"OpenAIProvider\", \"OPENAI_API_KEY\"],\n [GeminiProvider, \"GeminiProvider\", \"GEMINI_API_KEY\"],\n ];\n\n let providerDetected = false;\n for (const [ProviderClass, name, envVar] of providerChecks) {\n if (\n score.provider instanceof\n (ProviderClass as new (...args: unknown[]) => unknown)\n ) {\n providerDetected = true;\n const key = SecretsManager.optional(envVar);\n if (key) {\n ok(\"Provider: \" + name + \" (\" + envVar + \" is set)\");\n } else {\n fail(\"Provider: \" + name + \" (\" + envVar + \" is NOT set)\");\n hasErrors = true;\n }\n }\n }\n\n if (!providerDetected) {\n ok(\"Provider: custom LLMProvider\");\n }\n\n // 3. Count agents\n const agentKeys = Object.keys(score.agents);\n ok(agentKeys.length + \" agent\" + (agentKeys.length === 1 ? \"\" : \"s\") + \" configured\");\n\n // 4. Check voices\n for (const [agentKey, agent] of Object.entries(score.agents)) {\n for (const voice of agent.voices) {\n const voiceName = voice.name;\n\n // Check for known voices and their env vars\n const voiceEnvMap: Record<string, string> = {\n github: \"GITHUB_TOKEN\",\n };\n\n const envVar = voiceEnvMap[voiceName];\n if (envVar) {\n const key = SecretsManager.optional(envVar);\n if (key) {\n ok(\n \"Voice: \" + voiceName + \" on \" + agentKey + \" (\" + envVar + \" is set)\",\n );\n } else {\n fail(\n \"Voice: \" + voiceName + \" on \" + agentKey + \" (\" + envVar + \" is NOT set)\",\n );\n hasErrors = true;\n }\n } else {\n ok(\"Voice: \" + voiceName + \" on \" + agentKey + \" (installed)\");\n }\n }\n }\n\n // Final summary\n console.log(\"\");\n if (hasErrors) {\n console.log(\n chalk.yellow(\"Some checks failed. Fix the issues above and re-run.\"),\n );\n process.exit(1);\n } else {\n console.log(\n chalk.green(\"All checks passed.\") +\n chalk.dim(\" Run tutti-ai run to start.\"),\n );\n }\n}\n"],"mappings":"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","names":["existsSync","chalk","existsSync","resolve","chalk","ora","existsSync","resolve","chalk","ScoreLoader","AnthropicProvider","OpenAIProvider","GeminiProvider","SecretsManager"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tuttiai/cli",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Tutti CLI — scaffold and run multi-agent projects",
5
5
  "type": "module",
6
6
  "bin": {
@@ -21,13 +21,13 @@
21
21
  "typecheck": "tsc --noEmit"
22
22
  },
23
23
  "dependencies": {
24
- "@tuttiai/core": "^0.1.0",
25
- "@tuttiai/types": "^0.1.0",
26
- "chalk": "^5.4.0",
27
- "commander": "^13.1.0",
28
- "dotenv": "^17.4.1",
29
- "enquirer": "^2.4.0",
30
- "ora": "^8.2.0"
24
+ "@tuttiai/core": "*",
25
+ "@tuttiai/types": "*",
26
+ "chalk": "5.6.2",
27
+ "commander": "4.1.1",
28
+ "dotenv": "17.4.1",
29
+ "enquirer": "2.4.1",
30
+ "ora": "8.2.0"
31
31
  },
32
32
  "keywords": ["tutti", "ai", "agents", "orchestration", "cli", "scaffold"],
33
33
  "license": "MIT",