@tuttiai/cli 0.11.1 → 0.12.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/README.md CHANGED
@@ -231,6 +231,96 @@ Resume from turn 2? (y/n) y
231
231
  Final turn: 3
232
232
  ```
233
233
 
234
+ ### `tutti-ai schedule [score]`
235
+
236
+ Start the scheduler daemon — reads a score file, registers all agents
237
+ that have a `schedule` config, and runs on their configured triggers
238
+ (cron, interval, or one-shot datetime) until the process is killed.
239
+
240
+ ```bash
241
+ tutti-ai schedule # defaults to ./tutti.score.ts
242
+ tutti-ai schedule ./custom-score.ts # specify a score file
243
+ ```
244
+
245
+ Score file example:
246
+
247
+ ```ts
248
+ const score = defineScore({
249
+ provider: new AnthropicProvider(),
250
+ agents: {
251
+ reporter: {
252
+ name: "Reporter",
253
+ system_prompt: "Generate a daily status report.",
254
+ voices: [],
255
+ schedule: {
256
+ cron: "0 9 * * *", // 9 AM daily
257
+ input: "Generate the daily status report",
258
+ max_runs: 30, // auto-disable after 30 runs
259
+ },
260
+ },
261
+ },
262
+ });
263
+ ```
264
+
265
+ Environment:
266
+
267
+ | Variable | Required | Description |
268
+ |---|---|---|
269
+ | `TUTTI_PG_URL` | Recommended | PostgreSQL URL for durable schedule persistence. Falls back to in-memory (lost on restart). |
270
+
271
+ The daemon logs `schedule:triggered`, `schedule:completed`, and
272
+ `schedule:error` events to stdout with timestamps.
273
+
274
+ ### `tutti-ai schedules list`
275
+
276
+ Show all registered schedules:
277
+
278
+ ```bash
279
+ tutti-ai schedules list
280
+ ```
281
+
282
+ Output:
283
+
284
+ ```
285
+ ID AGENT TRIGGER ENABLED RUNS CREATED
286
+ ──────────────────────────────────────────────────────────────────────────────────────
287
+ nightly-report reporter cron: 0 9 * * * yes 12 2026-04-14
288
+ health-check monitor every 30m yes 48/100 2026-04-14
289
+ ```
290
+
291
+ ### `tutti-ai schedules enable <id>`
292
+
293
+ Re-enable a disabled schedule:
294
+
295
+ ```bash
296
+ tutti-ai schedules enable nightly-report
297
+ ```
298
+
299
+ ### `tutti-ai schedules disable <id>`
300
+
301
+ Disable a schedule without deleting it:
302
+
303
+ ```bash
304
+ tutti-ai schedules disable nightly-report
305
+ ```
306
+
307
+ ### `tutti-ai schedules trigger <id>`
308
+
309
+ Manually trigger a scheduled run immediately (useful for testing):
310
+
311
+ ```bash
312
+ tutti-ai schedules trigger nightly-report
313
+ tutti-ai schedules trigger nightly-report --score ./custom-score.ts
314
+ ```
315
+
316
+ ### `tutti-ai schedules runs <id>`
317
+
318
+ Show run history for a schedule (last 20 runs):
319
+
320
+ ```bash
321
+ tutti-ai schedules runs nightly-report
322
+ ```
323
+
234
324
  ## Links
235
325
 
236
326
  - [Tutti](https://tutti-ai.com)
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { config } from "dotenv";
5
- import { createLogger as createLogger11 } from "@tuttiai/core";
5
+ import { createLogger as createLogger13 } from "@tuttiai/core";
6
6
  import { Command } from "commander";
7
7
 
8
8
  // src/commands/init.ts
@@ -1865,19 +1865,287 @@ function printBanner(port, host, agentName, score, file, watch) {
1865
1865
  console.log();
1866
1866
  }
1867
1867
 
1868
+ // src/commands/schedule.ts
1869
+ import { existsSync as existsSync11 } from "fs";
1870
+ import { resolve as resolve11 } from "path";
1871
+ import chalk11 from "chalk";
1872
+ import {
1873
+ ScoreLoader as ScoreLoader7,
1874
+ SchedulerEngine,
1875
+ PostgresScheduleStore,
1876
+ MemoryScheduleStore,
1877
+ AgentRunner,
1878
+ EventBus,
1879
+ InMemorySessionStore as InMemorySessionStore3,
1880
+ SecretsManager as SecretsManager6,
1881
+ createLogger as createLogger11
1882
+ } from "@tuttiai/core";
1883
+ var logger11 = createLogger11("tutti-cli");
1884
+ function resolveStore() {
1885
+ const pgUrl = SecretsManager6.optional("TUTTI_PG_URL");
1886
+ if (pgUrl) {
1887
+ return new PostgresScheduleStore({ connection_string: pgUrl });
1888
+ }
1889
+ logger11.warn("TUTTI_PG_URL not set \u2014 using in-memory store (not durable across restarts)");
1890
+ return new MemoryScheduleStore();
1891
+ }
1892
+ async function scheduleCommand(scorePath) {
1893
+ const file = resolve11(scorePath ?? "./tutti.score.ts");
1894
+ if (!existsSync11(file)) {
1895
+ console.error(chalk11.red("Score file not found: " + file));
1896
+ console.error(chalk11.dim('Run "tutti-ai init" to create a new project.'));
1897
+ process.exit(1);
1898
+ }
1899
+ const score = await ScoreLoader7.load(file);
1900
+ const events = new EventBus();
1901
+ const sessions = new InMemorySessionStore3();
1902
+ const runner = new AgentRunner(
1903
+ score.provider,
1904
+ events,
1905
+ sessions
1906
+ );
1907
+ const store = resolveStore();
1908
+ const engine = new SchedulerEngine(store, runner, events);
1909
+ let registered = 0;
1910
+ for (const [agentId, agent] of Object.entries(score.agents)) {
1911
+ if (!agent.schedule) continue;
1912
+ const resolvedAgent = agent.model ? agent : { ...agent, model: score.default_model ?? "claude-sonnet-4-20250514" };
1913
+ await engine.schedule(agentId, resolvedAgent, agent.schedule);
1914
+ registered++;
1915
+ }
1916
+ if (registered === 0) {
1917
+ console.log(chalk11.yellow("No agents have a schedule config. Nothing to run."));
1918
+ console.log(chalk11.dim("Add schedule: { cron: '...', input: '...' } to an agent in your score."));
1919
+ process.exit(0);
1920
+ }
1921
+ events.onAny((e) => {
1922
+ if (e.type === "schedule:triggered") {
1923
+ const ev = e;
1924
+ console.log(
1925
+ chalk11.dim((/* @__PURE__ */ new Date()).toISOString()) + " " + chalk11.cyan("triggered") + " " + chalk11.bold(ev.schedule_id) + " \u2192 " + ev.agent_name
1926
+ );
1927
+ }
1928
+ if (e.type === "schedule:completed") {
1929
+ const ev = e;
1930
+ console.log(
1931
+ chalk11.dim((/* @__PURE__ */ new Date()).toISOString()) + " " + chalk11.green("completed") + " " + chalk11.bold(ev.schedule_id) + " " + chalk11.dim("(" + ev.duration_ms + "ms)")
1932
+ );
1933
+ }
1934
+ if (e.type === "schedule:error") {
1935
+ const ev = e;
1936
+ console.log(
1937
+ chalk11.dim((/* @__PURE__ */ new Date()).toISOString()) + " " + chalk11.red("error") + " " + chalk11.bold(ev.schedule_id) + " \u2014 " + ev.error.message
1938
+ );
1939
+ }
1940
+ });
1941
+ engine.start();
1942
+ console.log("");
1943
+ console.log(chalk11.cyan.bold(" Tutti Scheduler"));
1944
+ console.log(chalk11.dim(" Score: " + (score.name ?? file)));
1945
+ console.log(chalk11.dim(" Schedules: " + registered));
1946
+ console.log(chalk11.dim(" Store: " + (SecretsManager6.optional("TUTTI_PG_URL") ? "postgres" : "memory")));
1947
+ console.log("");
1948
+ console.log(chalk11.dim(" Press Ctrl+C to stop."));
1949
+ console.log("");
1950
+ const shutdown = () => {
1951
+ console.log(chalk11.dim("\n Shutting down scheduler..."));
1952
+ engine.stop();
1953
+ if ("close" in store && typeof store.close === "function") {
1954
+ void store.close();
1955
+ }
1956
+ process.exit(0);
1957
+ };
1958
+ process.on("SIGINT", shutdown);
1959
+ process.on("SIGTERM", shutdown);
1960
+ await new Promise(() => void 0);
1961
+ }
1962
+
1963
+ // src/commands/schedules.ts
1964
+ import { existsSync as existsSync12 } from "fs";
1965
+ import { resolve as resolve12 } from "path";
1966
+ import chalk12 from "chalk";
1967
+ import {
1968
+ ScoreLoader as ScoreLoader8,
1969
+ SchedulerEngine as SchedulerEngine2,
1970
+ PostgresScheduleStore as PostgresScheduleStore2,
1971
+ MemoryScheduleStore as MemoryScheduleStore2,
1972
+ AgentRunner as AgentRunner2,
1973
+ EventBus as EventBus2,
1974
+ InMemorySessionStore as InMemorySessionStore4,
1975
+ SecretsManager as SecretsManager7,
1976
+ createLogger as createLogger12
1977
+ } from "@tuttiai/core";
1978
+ var logger12 = createLogger12("tutti-cli");
1979
+ function resolveStore2() {
1980
+ const pgUrl = SecretsManager7.optional("TUTTI_PG_URL");
1981
+ if (pgUrl) {
1982
+ return new PostgresScheduleStore2({ connection_string: pgUrl });
1983
+ }
1984
+ logger12.warn("TUTTI_PG_URL not set \u2014 using in-memory store (schedules are ephemeral)");
1985
+ return new MemoryScheduleStore2();
1986
+ }
1987
+ async function closeStore(store) {
1988
+ if ("close" in store && typeof store.close === "function") {
1989
+ await store.close();
1990
+ }
1991
+ }
1992
+ function formatTrigger(r) {
1993
+ if (r.config.cron) return "cron: " + r.config.cron;
1994
+ if (r.config.every) return "every " + r.config.every;
1995
+ if (r.config.at) return "at " + r.config.at;
1996
+ return "?";
1997
+ }
1998
+ function pad(s, len) {
1999
+ return s.length >= len ? s : s + " ".repeat(len - s.length);
2000
+ }
2001
+ async function schedulesListCommand() {
2002
+ const store = resolveStore2();
2003
+ try {
2004
+ const records = await store.list();
2005
+ if (records.length === 0) {
2006
+ console.log(chalk12.dim("No schedules found."));
2007
+ console.log(chalk12.dim('Run "tutti-ai schedule" to start the scheduler daemon.'));
2008
+ return;
2009
+ }
2010
+ console.log("");
2011
+ console.log(
2012
+ chalk12.dim(
2013
+ " " + pad("ID", 20) + pad("AGENT", 16) + pad("TRIGGER", 22) + pad("ENABLED", 10) + pad("RUNS", 8) + "CREATED"
2014
+ )
2015
+ );
2016
+ console.log(chalk12.dim(" " + "\u2500".repeat(90)));
2017
+ for (const r of records) {
2018
+ const enabled = r.enabled ? chalk12.green("yes") : chalk12.red("no") + " ";
2019
+ const maxLabel = r.config.max_runs ? r.run_count + "/" + r.config.max_runs : String(r.run_count);
2020
+ console.log(
2021
+ " " + chalk12.bold(pad(r.id, 20)) + pad(r.agent_id, 16) + pad(formatTrigger(r), 22) + pad(enabled, 10) + pad(maxLabel, 8) + chalk12.dim(r.created_at.toISOString().slice(0, 10))
2022
+ );
2023
+ }
2024
+ console.log("");
2025
+ } finally {
2026
+ await closeStore(store);
2027
+ }
2028
+ }
2029
+ async function schedulesEnableCommand(id) {
2030
+ const store = resolveStore2();
2031
+ try {
2032
+ const record = await store.get(id);
2033
+ if (!record) {
2034
+ console.error(chalk12.red('Schedule "' + id + '" not found.'));
2035
+ process.exit(1);
2036
+ }
2037
+ await store.setEnabled(id, true);
2038
+ console.log(chalk12.green('Schedule "' + id + '" enabled.'));
2039
+ } finally {
2040
+ await closeStore(store);
2041
+ }
2042
+ }
2043
+ async function schedulesDisableCommand(id) {
2044
+ const store = resolveStore2();
2045
+ try {
2046
+ const record = await store.get(id);
2047
+ if (!record) {
2048
+ console.error(chalk12.red('Schedule "' + id + '" not found.'));
2049
+ process.exit(1);
2050
+ }
2051
+ await store.setEnabled(id, false);
2052
+ console.log(chalk12.yellow('Schedule "' + id + '" disabled.'));
2053
+ } finally {
2054
+ await closeStore(store);
2055
+ }
2056
+ }
2057
+ async function schedulesTriggerCommand(id, scorePath) {
2058
+ const file = resolve12(scorePath ?? "./tutti.score.ts");
2059
+ if (!existsSync12(file)) {
2060
+ console.error(chalk12.red("Score file not found: " + file));
2061
+ process.exit(1);
2062
+ }
2063
+ const score = await ScoreLoader8.load(file);
2064
+ const events = new EventBus2();
2065
+ const sessions = new InMemorySessionStore4();
2066
+ const runner = new AgentRunner2(score.provider, events, sessions);
2067
+ const store = resolveStore2();
2068
+ try {
2069
+ const record = await store.get(id);
2070
+ if (!record) {
2071
+ console.error(chalk12.red('Schedule "' + id + '" not found.'));
2072
+ process.exit(1);
2073
+ }
2074
+ const agent = score.agents[record.agent_id];
2075
+ if (!agent) {
2076
+ console.error(chalk12.red('Agent "' + record.agent_id + '" not found in score.'));
2077
+ process.exit(1);
2078
+ }
2079
+ const resolvedAgent = agent.model ? agent : { ...agent, model: score.default_model ?? "claude-sonnet-4-20250514" };
2080
+ const engine = new SchedulerEngine2(store, runner, events);
2081
+ await engine.schedule(id, resolvedAgent, record.config);
2082
+ engine.start();
2083
+ console.log(chalk12.cyan('Triggering "' + id + '" (' + record.agent_id + ")..."));
2084
+ const run2 = await engine.trigger(id);
2085
+ engine.stop();
2086
+ if (run2.error) {
2087
+ console.log(chalk12.red(" Error: " + run2.error));
2088
+ process.exit(1);
2089
+ }
2090
+ const duration = run2.completed_at && run2.triggered_at ? run2.completed_at.getTime() - run2.triggered_at.getTime() : 0;
2091
+ console.log(chalk12.green(" Completed in " + duration + "ms"));
2092
+ if (run2.result) {
2093
+ const preview = run2.result.length > 200 ? run2.result.slice(0, 200) + "..." : run2.result;
2094
+ console.log(chalk12.dim(" Output: " + preview));
2095
+ }
2096
+ } finally {
2097
+ await closeStore(store);
2098
+ }
2099
+ }
2100
+ async function schedulesRunsCommand(id) {
2101
+ const store = resolveStore2();
2102
+ try {
2103
+ const record = await store.get(id);
2104
+ if (!record) {
2105
+ console.error(chalk12.red('Schedule "' + id + '" not found.'));
2106
+ process.exit(1);
2107
+ }
2108
+ if ("getRuns" in store && typeof store.getRuns === "function") {
2109
+ const runs = store.getRuns(id);
2110
+ if (runs.length === 0) {
2111
+ console.log(chalk12.dim("No runs recorded for this schedule."));
2112
+ return;
2113
+ }
2114
+ const recent = runs.slice(-20);
2115
+ console.log("");
2116
+ console.log(chalk12.dim(" Showing last " + recent.length + " of " + runs.length + " runs:"));
2117
+ console.log("");
2118
+ for (const run2 of recent) {
2119
+ const duration = run2.completed_at && run2.triggered_at ? run2.completed_at.getTime() - run2.triggered_at.getTime() + "ms" : "?";
2120
+ const status = run2.error ? chalk12.red("error") : chalk12.green("ok");
2121
+ const preview = run2.error ? run2.error.slice(0, 80) : (run2.result ?? "").slice(0, 80);
2122
+ console.log(
2123
+ " " + chalk12.dim(run2.triggered_at.toISOString()) + " " + status + " " + chalk12.dim(duration) + " " + preview
2124
+ );
2125
+ }
2126
+ console.log("");
2127
+ } else {
2128
+ console.log(chalk12.dim('Schedule "' + id + '" has completed ' + record.run_count + " runs."));
2129
+ console.log(chalk12.dim("Full run history requires the MemoryScheduleStore or a future tutti_schedule_runs table."));
2130
+ }
2131
+ } finally {
2132
+ await closeStore(store);
2133
+ }
2134
+ }
2135
+
1868
2136
  // src/index.ts
1869
2137
  config();
1870
- var logger11 = createLogger11("tutti-cli");
2138
+ var logger13 = createLogger13("tutti-cli");
1871
2139
  process.on("unhandledRejection", (reason) => {
1872
- logger11.error({ error: reason instanceof Error ? reason.message : String(reason) }, "Unhandled rejection");
2140
+ logger13.error({ error: reason instanceof Error ? reason.message : String(reason) }, "Unhandled rejection");
1873
2141
  process.exit(1);
1874
2142
  });
1875
2143
  process.on("uncaughtException", (err) => {
1876
- logger11.error({ error: err.message }, "Fatal error");
2144
+ logger13.error({ error: err.message }, "Fatal error");
1877
2145
  process.exit(1);
1878
2146
  });
1879
2147
  var program = new Command();
1880
- program.name("tutti-ai").description("Tutti \u2014 multi-agent orchestration. All agents. All together.").version("0.11.1");
2148
+ program.name("tutti-ai").description("Tutti \u2014 multi-agent orchestration. All agents. All together.").version("0.12.0");
1881
2149
  program.command("init [project-name]").description("Create a new Tutti project").option("-t, --template <id>", "Project template to use").action(async (projectName, opts) => {
1882
2150
  await initCommand(projectName, opts.template);
1883
2151
  });
@@ -1933,5 +2201,24 @@ program.command("publish").description("Publish the current voice to npm and the
1933
2201
  program.command("eval <suite-file>").description("Run an evaluation suite against a score").option("--ci", "Exit with code 1 if any case fails").option("-s, --score <path>", "Path to score file (default: ./tutti.score.ts)").action(async (suitePath, opts) => {
1934
2202
  await evalCommand(suitePath, opts);
1935
2203
  });
2204
+ program.command("schedule [score]").description("Start the scheduler daemon \u2014 runs agents on their configured schedules").action(async (score) => {
2205
+ await scheduleCommand(score);
2206
+ });
2207
+ var schedulesCmd = program.command("schedules").description("Manage scheduled agents");
2208
+ schedulesCmd.command("list").description("Show all registered schedules").action(async () => {
2209
+ await schedulesListCommand();
2210
+ });
2211
+ schedulesCmd.command("enable <id>").description("Enable a disabled schedule").action(async (id) => {
2212
+ await schedulesEnableCommand(id);
2213
+ });
2214
+ schedulesCmd.command("disable <id>").description("Disable a schedule without deleting it").action(async (id) => {
2215
+ await schedulesDisableCommand(id);
2216
+ });
2217
+ schedulesCmd.command("trigger <id>").description("Manually trigger a scheduled run immediately").option("-s, --score <path>", "Path to score file (default: ./tutti.score.ts)").action(async (id, opts) => {
2218
+ await schedulesTriggerCommand(id, opts.score);
2219
+ });
2220
+ schedulesCmd.command("runs <id>").description("Show run history for a schedule (last 20 runs)").action(async (id) => {
2221
+ await schedulesRunsCommand(id);
2222
+ });
1936
2223
  program.parse();
1937
2224
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/templates/index.ts","../src/commands/run.ts","../src/watch/score-watcher.ts","../src/commands/resume.ts","../src/commands/add.ts","../src/commands/check.ts","../src/commands/studio.ts","../src/commands/search.ts","../src/commands/publish.ts","../src/commands/eval.ts","../src/commands/serve.ts"],"sourcesContent":["import { config } from \"dotenv\";\nconfig();\n\nimport { createLogger } from \"@tuttiai/core\";\nconst logger = createLogger(\"tutti-cli\");\n\nprocess.on(\"unhandledRejection\", (reason) => {\n logger.error({ error: reason instanceof Error ? reason.message : String(reason) }, \"Unhandled rejection\");\n process.exit(1);\n});\n\nprocess.on(\"uncaughtException\", (err) => {\n logger.error({ error: err.message }, \"Fatal error\");\n process.exit(1);\n});\n\nimport { Command } from \"commander\";\nimport { initCommand, templatesCommand } from \"./commands/init.js\";\nimport { runCommand } from \"./commands/run.js\";\nimport { resumeCommand, type ResumeOptions } from \"./commands/resume.js\";\nimport { addCommand } from \"./commands/add.js\";\nimport { checkCommand } from \"./commands/check.js\";\nimport { studioCommand } from \"./commands/studio.js\";\nimport { searchCommand, voicesCommand } from \"./commands/search.js\";\nimport { publishCommand } from \"./commands/publish.js\";\nimport { evalCommand } from \"./commands/eval.js\";\nimport { serveCommand, type ServeOptions } from \"./commands/serve.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.11.1\");\n\nprogram\n .command(\"init [project-name]\")\n .description(\"Create a new Tutti project\")\n .option(\"-t, --template <id>\", \"Project template to use\")\n .action(async (projectName: string | undefined, opts: { template?: string }) => {\n await initCommand(projectName, opts.template);\n });\n\nprogram\n .command(\"templates\")\n .description(\"List all available project templates\")\n .action(() => {\n templatesCommand();\n });\n\nprogram\n .command(\"run [score]\")\n .description(\"Run a Tutti score interactively\")\n .option(\"-w, --watch\", \"Reload the score on file changes\")\n .action(async (score: string | undefined, opts: { watch?: boolean }) => {\n await runCommand(score, { watch: opts.watch });\n });\n\nprogram\n .command(\"serve [score]\")\n .description(\"Start the Tutti HTTP server\")\n .option(\"-p, --port <number>\", \"Port to listen on (default: 3847)\")\n .option(\"-H, --host <address>\", \"Host to bind to (default: 0.0.0.0)\")\n .option(\"-k, --api-key <key>\", \"API key for bearer auth (or set TUTTI_API_KEY)\")\n .option(\"-a, --agent <name>\", \"Agent to expose (default: score entry or first agent)\")\n .option(\"-w, --watch\", \"Reload the score on file changes\")\n .action(async (score: string | undefined, opts: ServeOptions) => {\n await serveCommand(score, opts);\n });\n\nprogram\n .command(\"resume <session-id>\")\n .description(\"Resume a crashed or interrupted run from its last checkpoint\")\n .option(\n \"--store <backend>\",\n \"Durable store the checkpoint was written to (redis | postgres)\",\n \"redis\",\n )\n .option(\"-s, --score <path>\", \"Path to score file (default: ./tutti.score.ts)\")\n .option(\"-a, --agent <name>\", \"Agent key to resume (default: score.entry or the first agent)\")\n .option(\"-y, --yes\", \"Skip the confirmation prompt\")\n .action(\n async (\n sessionId: string,\n opts: { store?: string; score?: string; agent?: string; yes?: boolean },\n ) => {\n if (opts.store !== \"redis\" && opts.store !== \"postgres\") {\n console.error(\"--store must be 'redis' or 'postgres'\");\n process.exit(1);\n }\n const resolved: ResumeOptions = {\n store: opts.store,\n ...(opts.score !== undefined ? { score: opts.score } : {}),\n ...(opts.agent !== undefined ? { agent: opts.agent } : {}),\n ...(opts.yes !== undefined ? { yes: opts.yes } : {}),\n };\n await resumeCommand(sessionId, resolved);\n },\n );\n\nprogram\n .command(\"add <voice>\")\n .description(\"Add a voice to your project\")\n .action((voice: string) => {\n 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\n .command(\"studio [score]\")\n .description(\"Launch Tutti Studio — local web UI for inspecting agent runs\")\n .action(async (score?: string) => {\n await studioCommand(score);\n });\n\nprogram\n .command(\"search <query>\")\n .description(\"Search the voice registry for voices matching a query\")\n .action(async (query: string) => {\n await searchCommand(query);\n });\n\nprogram\n .command(\"voices\")\n .description(\"List all available official voices and install status\")\n .action(async () => {\n await voicesCommand();\n });\n\nprogram\n .command(\"publish\")\n .description(\"Publish the current voice to npm and the voice registry\")\n .option(\"--dry-run\", \"Run all checks without publishing\")\n .action(async (opts: { dryRun?: boolean }) => {\n await publishCommand(opts);\n });\n\nprogram\n .command(\"eval <suite-file>\")\n .description(\"Run an evaluation suite against a score\")\n .option(\"--ci\", \"Exit with code 1 if any case fails\")\n .option(\"-s, --score <path>\", \"Path to score file (default: ./tutti.score.ts)\")\n .action(async (suitePath: string, opts: { ci?: boolean; score?: string }) => {\n await evalCommand(suitePath, opts);\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\";\nimport { createLogger } from \"@tuttiai/core\";\nimport { TEMPLATES, getTemplate } from \"../templates/index.js\";\nimport type { Template } from \"../templates/index.js\";\n\nconst logger = createLogger(\"tutti-cli\");\n\nconst { prompt } = Enquirer;\n\nexport async function initCommand(projectName?: string, templateId?: 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 logger.error(\"Project name is required\");\n process.exit(1);\n }\n\n const dir = join(process.cwd(), projectName);\n\n if (existsSync(dir)) {\n logger.error({ dir: `${projectName}/` }, \"Directory already exists\");\n process.exit(1);\n }\n\n // Resolve template\n let template: Template | undefined;\n if (templateId) {\n template = getTemplate(templateId);\n if (!template) {\n logger.error({ template: templateId }, \"Unknown template\");\n console.error(chalk.dim(\" Available: \" + TEMPLATES.map((t) => t.id).join(\", \")));\n process.exit(1);\n }\n } else {\n // Interactive picker\n const response = await prompt<{ templateId: string }>({\n type: \"select\",\n name: \"templateId\",\n message: \"Which template?\",\n choices: TEMPLATES.map((t) => ({\n name: t.id,\n message: t.name + chalk.dim(\" — \" + t.description),\n })),\n });\n template = getTemplate(response.templateId);\n if (!template) template = TEMPLATES[0];\n }\n\n mkdirSync(dir, { recursive: true });\n\n const deps: Record<string, string> = {\n \"@tuttiai/core\": \"*\",\n \"@tuttiai/types\": \"*\",\n ...template.deps,\n };\n\n const envLines = [\n \"ANTHROPIC_API_KEY=your_key_here\",\n ...template.envVars,\n \"\",\n \"# Log level: debug | info | warn | error (default: info)\",\n \"TUTTI_LOG_LEVEL=info\",\n \"\",\n \"# OpenTelemetry (optional)\",\n \"# OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318\",\n \"# OTEL_SERVICE_NAME=tutti\",\n ];\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: deps,\n devDependencies: {\n tsx: \"^4.0.0\",\n typescript: \"^5.7.0\",\n },\n },\n null,\n 2,\n ),\n\n \".env.example\": envLines.join(\"\\n\") + \"\\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\": template.score,\n\n \"README.md\": `# ${projectName}\n\nA Tutti agent project. All agents. All together.\n\n**Template:** ${template.name} — ${template.description}\n\n## Setup\n\n\\`\\`\\`bash\ncp .env.example .env\n# Add your API keys 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}/`) + chalk.dim(` (${template.name})`));\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\nexport function templatesCommand(): void {\n console.log();\n console.log(chalk.bold(\" Available Templates\"));\n console.log();\n for (const t of TEMPLATES) {\n console.log(\" \" + chalk.cyan(t.id.padEnd(18)) + t.description);\n }\n console.log();\n console.log(chalk.dim(\" Use: tutti-ai init my-project --template \" + TEMPLATES[0].id));\n console.log();\n}\n","export interface Template {\n id: string;\n name: string;\n description: string;\n deps: Record<string, string>;\n envVars: string[];\n score: string;\n}\n\nconst minimal: Template = {\n id: \"minimal\",\n name: \"Minimal\",\n description: \"One agent, no voices — the simplest starting point\",\n deps: {},\n envVars: [],\n score: `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\nconst codingAgent: Template = {\n id: \"coding-agent\",\n name: \"Coding Agent\",\n description: \"TypeScript developer with filesystem + GitHub access\",\n deps: { \"@tuttiai/filesystem\": \"*\", \"@tuttiai/github\": \"*\" },\n envVars: [\"GITHUB_TOKEN=ghp_your_token_here\"],\n score: `import { defineScore, AnthropicProvider } from \"@tuttiai/core\"\nimport { FilesystemVoice } from \"@tuttiai/filesystem\"\nimport { GitHubVoice } from \"@tuttiai/github\"\n\nexport default defineScore({\n provider: new AnthropicProvider(),\n default_model: \"claude-sonnet-4-20250514\",\n agents: {\n coder: {\n name: \"Coder\",\n system_prompt:\n \"You are an expert TypeScript developer. \" +\n \"You read and write code using the filesystem voice, \" +\n \"and manage issues and PRs via the GitHub voice. \" +\n \"Write clean, tested, well-documented code.\",\n voices: [new FilesystemVoice(), new GitHubVoice()],\n permissions: [\"filesystem\", \"network\"],\n streaming: true,\n }\n }\n})\n`,\n};\n\nconst researchAgent: Template = {\n id: \"research-agent\",\n name: \"Research Agent\",\n description: \"Researcher that saves structured notes to files\",\n deps: { \"@tuttiai/filesystem\": \"*\" },\n envVars: [],\n score: `import { defineScore, AnthropicProvider } from \"@tuttiai/core\"\nimport { FilesystemVoice } from \"@tuttiai/filesystem\"\n\nexport default defineScore({\n provider: new AnthropicProvider(),\n default_model: \"claude-sonnet-4-20250514\",\n agents: {\n researcher: {\n name: \"Researcher\",\n system_prompt:\n \"You are an expert researcher. \" +\n \"Analyze topics thoroughly, cite sources, and save \" +\n \"structured notes as markdown files using the filesystem voice. \" +\n \"Organize findings with clear headings and bullet points.\",\n voices: [new FilesystemVoice()],\n permissions: [\"filesystem\"],\n streaming: true,\n }\n }\n})\n`,\n};\n\nconst qaPipeline: Template = {\n id: \"qa-pipeline\",\n name: \"QA Pipeline\",\n description: \"Orchestrator + QA specialist with browser testing and HITL\",\n deps: { \"@tuttiai/playwright\": \"*\" },\n envVars: [],\n score: `import { defineScore, AnthropicProvider } from \"@tuttiai/core\"\nimport { PlaywrightVoice } from \"@tuttiai/playwright\"\n\nexport default defineScore({\n provider: new AnthropicProvider(),\n default_model: \"claude-sonnet-4-20250514\",\n entry: \"orchestrator\",\n agents: {\n orchestrator: {\n name: \"QA Lead\",\n system_prompt:\n \"You are a QA lead. Triage incoming bugs by delegating \" +\n \"browser testing to the QA specialist. Use human-in-the-loop \" +\n \"to ask for approval before marking bugs as verified.\",\n voices: [],\n role: \"orchestrator\",\n delegates: [\"qa\"],\n allow_human_input: true,\n streaming: true,\n },\n qa: {\n name: \"QA Specialist\",\n system_prompt:\n \"You are a QA engineer. Navigate to URLs, check elements, \" +\n \"take screenshots, and verify bug reports using the browser.\",\n voices: [new PlaywrightVoice()],\n permissions: [\"network\", \"browser\"],\n role: \"specialist\",\n budget: { max_cost_usd: 0.50, warn_at_percent: 80 },\n streaming: true,\n }\n }\n})\n`,\n};\n\nconst devTeam: Template = {\n id: \"dev-team\",\n name: \"Dev Team\",\n description: \"Full team: orchestrator + coder + PM + QA with all voices\",\n deps: {\n \"@tuttiai/filesystem\": \"*\",\n \"@tuttiai/github\": \"*\",\n \"@tuttiai/playwright\": \"*\",\n },\n envVars: [\"GITHUB_TOKEN=ghp_your_token_here\"],\n score: `import { defineScore, AnthropicProvider, createLoggingHook, createBlocklistHook, createLogger } from \"@tuttiai/core\"\nimport { FilesystemVoice } from \"@tuttiai/filesystem\"\nimport { GitHubVoice } from \"@tuttiai/github\"\nimport { PlaywrightVoice } from \"@tuttiai/playwright\"\n\nconst logger = createLogger(\"dev-team\")\n\nexport default defineScore({\n provider: new AnthropicProvider(),\n default_model: \"claude-sonnet-4-20250514\",\n entry: \"orchestrator\",\n hooks: {\n ...createLoggingHook(logger),\n ...createBlocklistHook([\"delete_file\"]),\n },\n agents: {\n orchestrator: {\n name: \"Tech Lead\",\n system_prompt:\n \"You are the tech lead. Break tasks into subtasks and delegate: \" +\n \"code tasks to Coder, documentation to PM, testing to QA. \" +\n \"Review outputs before presenting to the user.\",\n voices: [],\n role: \"orchestrator\",\n delegates: [\"coder\", \"pm\", \"qa\"],\n allow_human_input: true,\n streaming: true,\n },\n coder: {\n name: \"Coder\",\n system_prompt:\n \"You are a senior TypeScript developer. Write clean, tested code. \" +\n \"Use the filesystem voice to read/write files and GitHub to manage PRs.\",\n voices: [new FilesystemVoice(), new GitHubVoice()],\n permissions: [\"filesystem\", \"network\"],\n role: \"specialist\",\n streaming: true,\n },\n pm: {\n name: \"PM\",\n system_prompt:\n \"You are a product manager. Write specs, update documentation, \" +\n \"and create GitHub issues for tracking. Focus on clarity and completeness.\",\n voices: [new FilesystemVoice(), new GitHubVoice()],\n permissions: [\"filesystem\", \"network\"],\n role: \"specialist\",\n streaming: true,\n },\n qa: {\n name: \"QA\",\n system_prompt:\n \"You are a QA engineer. Test features in the browser, verify bugs, \" +\n \"and write test reports. Screenshot evidence for every finding.\",\n voices: [new PlaywrightVoice()],\n permissions: [\"network\", \"browser\"],\n role: \"specialist\",\n budget: { max_cost_usd: 1.00 },\n streaming: true,\n }\n }\n})\n`,\n};\n\nexport const TEMPLATES: Template[] = [minimal, codingAgent, researchAgent, qaPipeline, devTeam];\n\nexport function getTemplate(id: string): Template | undefined {\n return TEMPLATES.find((t) => t.id === id);\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 InMemorySessionStore,\n createLogger,\n} from \"@tuttiai/core\";\nimport type { ScoreConfig, SessionStore } from \"@tuttiai/types\";\nimport { ReactiveScore } from \"../watch/score-watcher.js\";\n\nconst logger = createLogger(\"tutti-cli\");\n\nexport interface RunOptions {\n /** Reload the score on file changes. */\n watch?: boolean;\n}\n\nexport async function runCommand(\n scorePath?: string,\n options: RunOptions = {},\n): Promise<void> {\n const file = resolve(scorePath ?? \"./tutti.score.ts\");\n\n if (!existsSync(file)) {\n logger.error({ file }, \"Score file not found\");\n console.error(chalk.dim('Run \"tutti-ai init\" to create a new project.'));\n process.exit(1);\n }\n\n let score;\n try {\n score = await ScoreLoader.load(file);\n } catch (err) {\n logger.error(\n { error: err instanceof Error ? err.message : String(err) },\n \"Failed to load score\",\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 logger.error({ envVar }, \"Missing API key\");\n process.exit(1);\n }\n }\n }\n\n // Enable streaming on every agent in the score. Factored out so we can\n // reapply it after a hot-reload in watch mode.\n const applyRunDefaults = (cfg: ScoreConfig): void => {\n for (const agent of Object.values(cfg.agents)) {\n agent.streaming = true;\n }\n };\n applyRunDefaults(score);\n\n // Build a single session store up front in watch mode so the\n // conversation history survives runtime swaps. Non-watch runs can let\n // TuttiRuntime provision its own store from score.memory as usual.\n const sharedSessions: SessionStore | undefined = options.watch\n ? new InMemorySessionStore()\n : undefined;\n\n const spinner = ora({ color: \"cyan\" });\n\n // REPL-level state. `streaming` resets per turn; `runtime` may be\n // swapped by the hot-reload path below.\n let streaming = false;\n let runtime = buildRuntime(score, sharedSessions);\n\n attachListeners(runtime);\n\n // REPL readline — created early so the HITL handler below can use it.\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n // Wire per-runtime listeners. Separated from the REPL so a hot-reload\n // can swap the runtime and re-wire without touching the outer loop.\n function attachListeners(r: TuttiRuntime): void {\n r.events.on(\"agent:start\", (e) => {\n logger.info({ agent: e.agent_name }, \"Running agent\");\n });\n\n r.events.on(\"llm:request\", () => {\n spinner.start(\"Thinking...\");\n });\n\n r.events.on(\"token:stream\", (e) => {\n if (!streaming) {\n spinner.stop();\n streaming = true;\n }\n process.stdout.write(e.text);\n });\n\n r.events.on(\"llm:response\", () => {\n if (streaming) {\n process.stdout.write(\"\\n\");\n } else {\n spinner.stop();\n }\n });\n\n r.events.on(\"tool:start\", (e) => {\n if (streaming) {\n process.stdout.write(chalk.dim(\"\\n [using: \" + e.tool_name + \"]\"));\n } else {\n spinner.stop();\n console.log(chalk.dim(\" [using: \" + e.tool_name + \"]\"));\n }\n });\n\n r.events.on(\"tool:end\", (e) => {\n if (streaming) {\n process.stdout.write(chalk.dim(\" [done: \" + e.tool_name + \"]\\n\"));\n }\n });\n\n r.events.on(\"tool:error\", (e) => {\n spinner.stop();\n logger.error({ tool: e.tool_name }, \"Tool error\");\n });\n\n r.events.on(\"security:injection_detected\", (e) => {\n logger.warn({ tool: e.tool_name }, \"Potential prompt injection detected\");\n });\n\n r.events.on(\"budget:warning\", () => {\n logger.warn(\"Approaching token budget (80%)\");\n });\n\n r.events.on(\"budget:exceeded\", () => {\n logger.error(\"Token budget exceeded — stopping\");\n });\n\n r.events.on(\"hitl:requested\", (e) => {\n spinner.stop();\n if (streaming) {\n process.stdout.write(\"\\n\");\n streaming = false;\n }\n console.log();\n console.log(\n chalk.yellow(\n \" \" + chalk.bold(\"[Agent needs input]\") + \" \" + e.question,\n ),\n );\n if (e.options) {\n e.options.forEach((opt, i) => {\n console.log(chalk.yellow(\" \" + (i + 1) + \". \" + opt));\n });\n }\n void rl.question(chalk.yellow(\" > \")).then((answer) => {\n runtime.answer(e.session_id, answer.trim());\n });\n });\n }\n\n // --- Watch mode wiring ---------------------------------------------------\n // Scope: set up a ReactiveScore that reloads the score file on change\n // and surfaces status to the REPL. The REPL checks `pendingReload`\n // between turns (so we never interrupt a mid-turn call) and swaps\n // `runtime` when appropriate.\n let reactive: ReactiveScore | undefined;\n if (options.watch) {\n reactive = new ReactiveScore(score, file);\n reactive.on(\"file-change\", () => {\n console.log(chalk.cyan(\"\\n[tutti] Score changed, reloading...\"));\n });\n reactive.on(\"reloaded\", () => {\n // Defer the actual swap to the next turn boundary — the REPL loop\n // checks `pendingReload` before each iteration. Applying mid-turn\n // would either interrupt a tool call or strand events listeners\n // pointing at the old runtime instance.\n console.log(chalk.green(\"[tutti] Score reloaded. Changes applied.\"));\n });\n reactive.on(\"reload-failed\", (err) => {\n logger.error(\n { error: err instanceof Error ? err.message : String(err) },\n \"[tutti] Reload failed — using previous config\",\n );\n });\n }\n\n // REPL\n console.log(chalk.dim('Tutti REPL — type \"exit\" to quit\\n'));\n if (options.watch) {\n console.log(chalk.dim(\"Watching \" + file + \" for changes…\\n\"));\n }\n\n let sessionId: string | undefined;\n\n // Handle Ctrl+C cleanly\n process.on(\"SIGINT\", () => {\n if (streaming) process.stdout.write(\"\\n\");\n spinner.stop();\n console.log(chalk.dim(\"Goodbye!\"));\n rl.close();\n if (reactive) void reactive.close();\n process.exit(0);\n });\n\n try {\n while (true) {\n // Apply any pending hot-reload before we start the next turn. This\n // is the \"don't interrupt mid-tool-call\" guarantee — we only swap\n // at a REPL-loop boundary, after the previous `run()` resolved.\n if (reactive?.pendingReload) {\n const nextScore = reactive.current;\n applyRunDefaults(nextScore);\n runtime = buildRuntime(nextScore, sharedSessions);\n attachListeners(runtime);\n reactive.consumePendingReload();\n }\n\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 // Reset streaming state for this run\n streaming = false;\n\n try {\n const result = await runtime.run(\"assistant\", trimmed, sessionId);\n sessionId = result.session_id;\n\n if (!streaming) {\n console.log(\"\\n\" + result.output + \"\\n\");\n } else {\n console.log();\n }\n } catch (err) {\n if (streaming) process.stdout.write(\"\\n\");\n spinner.stop();\n logger.error(\n { error: err instanceof Error ? err.message : String(err) },\n \"Something went wrong\",\n );\n }\n }\n } catch {\n // readline closed\n }\n\n console.log(chalk.dim(\"Goodbye!\"));\n rl.close();\n if (reactive) await reactive.close();\n process.exit(0);\n}\n\nfunction buildRuntime(\n score: ScoreConfig,\n sessionStore: SessionStore | undefined,\n): TuttiRuntime {\n return new TuttiRuntime(\n score,\n sessionStore ? { sessionStore } : {},\n );\n}\n","import { dirname, resolve } from \"node:path\";\nimport { EventEmitter } from \"node:events\";\nimport chokidar, { type FSWatcher } from \"chokidar\";\nimport type { ScoreConfig } from \"@tuttiai/types\";\nimport { validateScore } from \"@tuttiai/core\";\n\n/** How long to wait after the last change event before reloading. */\nconst DEFAULT_DEBOUNCE_MS = 200;\n\n/** Default ignore-patterns for the directory-tree watch. */\nconst DEFAULT_IGNORED = [\n /(^|[/\\\\])\\../, // dotfiles (.git, .env, etc.)\n /node_modules/,\n /[/\\\\]dist[/\\\\]/,\n /[/\\\\]coverage[/\\\\]/,\n];\n\n/**\n * Load a score module with ESM cache-busting. Node's ESM cache is per-URL\n * and cannot be invalidated, so we append a unique query parameter on\n * each reload to force a fresh module instance. The old instance stays in\n * memory — acceptable leak for a development-only watch loop.\n */\nasync function defaultLoadScore(path: string): Promise<ScoreConfig> {\n const absolute = resolve(path);\n // Node's ESM cache is per-URL and can't be invalidated — append a\n // unique query parameter so each reload gets a fresh module instance.\n // The previous instance stays in memory (small leak, acceptable for a\n // development-only watch loop).\n const { pathToFileURL } = await import(\"node:url\");\n const url = pathToFileURL(absolute).href + \"?t=\" + Date.now().toString(36);\n const mod = (await import(url)) as { default?: ScoreConfig };\n if (!mod.default) {\n throw new Error(\n \"Score file has no default export: \" + path +\n \" — your score must export `defineScore({ ... })` as its default.\",\n );\n }\n // Validate the freshly-loaded score. `ScoreLoader.load` would have run\n // the same validator but on a stale cache entry, so we inline it.\n validateScore(mod.default);\n return mod.default;\n}\n\nexport interface ReactiveScoreEvents {\n /** Emitted immediately when a watched file changes (before debounce settles). */\n \"file-change\": (changedPath: string) => void;\n /** Emitted when a reload attempt starts (after debounce). */\n reloading: () => void;\n /** Emitted when a reload succeeds — `current` now returns the new score. */\n reloaded: (score: ScoreConfig) => void;\n /**\n * Emitted when a reload fails. The previous `current` score is kept so\n * the REPL can continue with the last-known-good config.\n */\n \"reload-failed\": (error: Error) => void;\n}\n\nexport interface ReactiveScoreOptions {\n /**\n * Additional paths or glob patterns to watch beyond the score file and\n * its parent directory. Useful when voices live elsewhere.\n */\n extraPaths?: string[];\n /** Debounce window in ms. Default 200. */\n debounceMs?: number;\n /**\n * Override the score loader. Primarily a test seam — production code\n * uses the default cache-busting ESM importer.\n */\n load?: (path: string) => Promise<ScoreConfig>;\n}\n\n/**\n * A {@link ScoreConfig} that refreshes itself when the underlying file\n * (or any file in its directory) changes on disk.\n *\n * Consumers read `reactive.current` before each turn and get the most\n * recent successfully-loaded score. On a reload failure (syntax error in\n * the score file, schema validation, etc.), `current` keeps returning the\n * previous value — callers can listen for `reload-failed` to surface the\n * error in their UI.\n */\nexport class ReactiveScore extends EventEmitter {\n private _current: ScoreConfig;\n private readonly scorePath: string;\n private readonly load: (path: string) => Promise<ScoreConfig>;\n private readonly debounceMs: number;\n private readonly watcher: FSWatcher;\n private debounceTimer: ReturnType<typeof setTimeout> | undefined;\n private closed = false;\n private _pendingReload = false;\n\n constructor(\n initialScore: ScoreConfig,\n scorePath: string,\n options: ReactiveScoreOptions = {},\n ) {\n super();\n this._current = initialScore;\n this.scorePath = resolve(scorePath);\n this.load = options.load ?? defaultLoadScore;\n this.debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;\n\n // Watch the score file, its parent directory tree, and any extras.\n // Directory-tree watching catches voice files and local utility\n // modules without needing a proper import-graph resolver; the\n // trade-off is that unrelated files in the tree also trigger reloads.\n const watchTargets = [\n this.scorePath,\n dirname(this.scorePath),\n ...(options.extraPaths ?? []),\n ];\n this.watcher = chokidar.watch(watchTargets, {\n ignored: DEFAULT_IGNORED,\n ignoreInitial: true,\n // awaitWriteFinish: guard against partial writes from editors that\n // save atomically via rename/move.\n awaitWriteFinish: {\n stabilityThreshold: 50,\n pollInterval: 20,\n },\n });\n\n this.watcher.on(\"change\", (path) => this.handleChange(path));\n this.watcher.on(\"add\", (path) => this.handleChange(path));\n }\n\n /** The most recent successfully-loaded score. Never stale. */\n get current(): ScoreConfig {\n return this._current;\n }\n\n /**\n * True when a file change has been observed and a reload is pending\n * (or just completed and not yet consumed). Readers call\n * {@link consumePendingReload} to clear the flag when they've taken\n * action on the new config.\n */\n get pendingReload(): boolean {\n return this._pendingReload;\n }\n\n consumePendingReload(): void {\n this._pendingReload = false;\n }\n\n /** Release the underlying filesystem watchers. */\n async close(): Promise<void> {\n this.closed = true;\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n await this.watcher.close();\n }\n\n /**\n * Force an immediate reload without waiting for a filesystem event.\n * Exposed for tests and for the `reload` REPL command.\n */\n async reloadNow(): Promise<void> {\n if (this.closed) return;\n this.emit(\"reloading\");\n try {\n const next = await this.load(this.scorePath);\n this._current = next;\n this._pendingReload = true;\n this.emit(\"reloaded\", next);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n this.emit(\"reload-failed\", error);\n }\n }\n\n private handleChange(path: string): void {\n if (this.closed) return;\n this.emit(\"file-change\", path);\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n this.debounceTimer = setTimeout(() => {\n void this.reloadNow();\n }, this.debounceMs);\n }\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 AnthropicProvider,\n GeminiProvider,\n OpenAIProvider,\n ScoreLoader,\n SecretsManager,\n TuttiRuntime,\n createCheckpointStore,\n createLogger,\n type Checkpoint,\n type ChatMessage,\n} from \"@tuttiai/core\";\nconst logger = createLogger(\"tutti-cli\");\n\nexport interface ResumeOptions {\n /** Which durable store the checkpoint was written to. */\n store: \"redis\" | \"postgres\";\n /** Path to the score file (defaults to ./tutti.score.ts). */\n score?: string;\n /** Agent key to resume; defaults to the score's entry agent. */\n agent?: string;\n /** Skip the confirmation prompt — for scripted use. */\n yes?: boolean;\n}\n\nexport async function resumeCommand(\n sessionId: string,\n opts: ResumeOptions,\n): Promise<void> {\n // --- Score loading (same flow as `run`) -------------------------------\n const scoreFile = resolve(opts.score ?? \"./tutti.score.ts\");\n if (!existsSync(scoreFile)) {\n logger.error({ file: scoreFile }, \"Score file not found\");\n console.error(chalk.dim('Run \"tutti-ai init\" to create a new project.'));\n process.exit(1);\n }\n\n let score;\n try {\n score = await ScoreLoader.load(scoreFile);\n } catch (err) {\n logger.error(\n { error: err instanceof Error ? err.message : String(err) },\n \"Failed to load score\",\n );\n process.exit(1);\n }\n\n // --- Provider API-key check (same shortlist as `run`) -----------------\n const providerKeyMap: [unknown, string][] = [\n [AnthropicProvider, \"ANTHROPIC_API_KEY\"],\n [OpenAIProvider, \"OPENAI_API_KEY\"],\n [GeminiProvider, \"GEMINI_API_KEY\"],\n ];\n for (const [ProviderClass, envVar] of providerKeyMap) {\n if (\n score.provider instanceof\n (ProviderClass as new (...args: unknown[]) => unknown)\n ) {\n if (!SecretsManager.optional(envVar)) {\n logger.error({ envVar }, \"Missing API key\");\n process.exit(1);\n }\n }\n }\n\n // --- Resolve the target agent -----------------------------------------\n const agentName = resolveAgentName(score, opts.agent);\n const agent = score.agents[agentName];\n if (!agent) {\n logger.error(\n { agent: agentName, available: Object.keys(score.agents) },\n \"Agent not found in score\",\n );\n process.exit(1);\n }\n if (!agent.durable) {\n console.error(\n chalk.yellow(\n \"Agent '\" +\n agentName +\n \"' does not have `durable: true` set — resume has nothing to restore.\",\n ),\n );\n console.error(\n chalk.dim(\n \"Enable durable checkpointing on the agent before the run that created this session.\",\n ),\n );\n process.exit(1);\n }\n\n // --- Load the checkpoint ----------------------------------------------\n const spinner = ora({ color: \"cyan\" }).start(\"Loading checkpoint...\");\n let checkpointStore;\n let checkpoint: Checkpoint | null;\n try {\n checkpointStore = createCheckpointStore({ store: opts.store });\n checkpoint = await checkpointStore.loadLatest(sessionId);\n } catch (err) {\n spinner.fail(\"Failed to load checkpoint\");\n logger.error(\n { error: err instanceof Error ? err.message : String(err), store: opts.store },\n \"Checkpoint store error\",\n );\n process.exit(1);\n }\n spinner.stop();\n\n if (!checkpoint) {\n console.error(\n chalk.red(\"No checkpoint found for session \" + sessionId + \".\"),\n );\n console.error(\n chalk.dim(\n \"Verify TUTTI_\" +\n (opts.store === \"redis\" ? \"REDIS\" : \"PG\") +\n \"_URL points to the same \" +\n opts.store +\n \" the original run used.\",\n ),\n );\n process.exit(1);\n }\n\n // --- Render the summary -----------------------------------------------\n printSummary(checkpoint);\n\n // --- Confirm (unless --yes) -------------------------------------------\n if (!opts.yes && !(await confirmResume(checkpoint.turn))) {\n console.log(chalk.dim(\"Cancelled.\"));\n process.exit(0);\n }\n\n // --- Build the runtime and hand off to AgentRunner --------------------\n const runtime = new TuttiRuntime(score, { checkpointStore });\n\n // Seed the session store with a synthetic Session so the runner's\n // `sessions.get(id)` lookup succeeds. The agent loop immediately\n // overwrites `messages` from the checkpoint — the seeded messages\n // array only exists so the initial get() call doesn't miss.\n const sessions = runtime.sessions;\n if (\"save\" in sessions && typeof sessions.save === \"function\") {\n (sessions.save as (s: { id: string; agent_name: string; messages: ChatMessage[]; created_at: Date; updated_at: Date }) => void)({\n id: sessionId,\n agent_name: agentName,\n messages: [...checkpoint.messages],\n created_at: checkpoint.saved_at,\n updated_at: new Date(),\n });\n } else {\n console.error(\n chalk.red(\n \"Session store does not support resume seeding. Use the default InMemorySessionStore or PostgresSessionStore.\",\n ),\n );\n process.exit(1);\n }\n\n wireProgress(runtime);\n\n try {\n // Input is ignored when the runner sees a mid-cycle checkpoint, but\n // we still need a non-empty value to satisfy the method signature.\n const result = await runtime.run(agentName, \"[resume]\", sessionId);\n console.log();\n console.log(chalk.green(\"✓ Resumed run complete.\"));\n console.log(chalk.dim(\" Final turn: \" + result.turns));\n console.log(chalk.dim(\" Session ID: \" + result.session_id));\n console.log(\n chalk.dim(\n \" Token usage: \" +\n result.usage.input_tokens +\n \" in / \" +\n result.usage.output_tokens +\n \" out\",\n ),\n );\n console.log();\n console.log(result.output);\n } catch (err) {\n logger.error(\n { error: err instanceof Error ? err.message : String(err) },\n \"Resume failed\",\n );\n process.exit(1);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction resolveAgentName(\n score: { entry?: string | { agents: string[] }; agents: Record<string, unknown> },\n override?: string,\n): string {\n if (override) return override;\n if (typeof score.entry === \"string\") return score.entry;\n const first = Object.keys(score.agents)[0];\n if (!first) {\n console.error(chalk.red(\"Score has no agents defined.\"));\n process.exit(1);\n }\n return first;\n}\n\nfunction printSummary(checkpoint: Checkpoint): void {\n console.log();\n console.log(chalk.cyan.bold(\"Checkpoint summary\"));\n console.log(\n chalk.dim(\" Session ID: \") + checkpoint.session_id,\n );\n console.log(\n chalk.dim(\" Last turn: \") + String(checkpoint.turn),\n );\n console.log(\n chalk.dim(\" Saved at: \") +\n checkpoint.saved_at.toISOString(),\n );\n console.log(\n chalk.dim(\" Messages: \") +\n String(checkpoint.messages.length) +\n \" total\",\n );\n console.log();\n console.log(chalk.cyan(\"First messages\"));\n const preview = checkpoint.messages.slice(0, 3);\n for (const msg of preview) {\n const text = excerpt(messageToText(msg), 200);\n console.log(chalk.dim(\" [\" + msg.role + \"] \") + text);\n }\n if (checkpoint.messages.length > preview.length) {\n console.log(\n chalk.dim(\n \" … \" +\n String(checkpoint.messages.length - preview.length) +\n \" more\",\n ),\n );\n }\n console.log();\n}\n\nfunction messageToText(msg: ChatMessage): string {\n if (typeof msg.content === \"string\") return msg.content;\n const parts: string[] = [];\n for (const block of msg.content) {\n if (block.type === \"text\") {\n parts.push(block.text);\n } else if (block.type === \"tool_use\") {\n parts.push(\"[tool_use \" + block.name + \"]\");\n } else if (block.type === \"tool_result\") {\n parts.push(\"[tool_result \" + excerpt(block.content, 80) + \"]\");\n }\n }\n return parts.join(\" \");\n}\n\nfunction excerpt(text: string, max: number): string {\n const oneLine = text.replace(/\\s+/g, \" \").trim();\n return oneLine.length > max ? oneLine.slice(0, max - 1) + \"…\" : oneLine;\n}\n\nasync function confirmResume(turn: number): Promise<boolean> {\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n try {\n const answer = (\n await rl.question(\n chalk.cyan(\"Resume from turn \" + turn + \"? \") + chalk.dim(\"(y/n) \"),\n )\n )\n .trim()\n .toLowerCase();\n return answer === \"y\" || answer === \"yes\";\n } finally {\n rl.close();\n }\n}\n\nfunction wireProgress(runtime: TuttiRuntime): void {\n const spinner = ora({ color: \"cyan\" });\n let streaming = false;\n\n runtime.events.on(\"checkpoint:restored\", (e) => {\n console.log(\n chalk.dim(\"↻ Restored from turn \" + e.turn) +\n chalk.dim(\" (session \" + e.session_id.slice(0, 8) + \"…)\"),\n );\n });\n runtime.events.on(\"checkpoint:saved\", (e) => {\n console.log(chalk.dim(\"· Checkpoint saved at turn \" + e.turn));\n });\n runtime.events.on(\"llm:request\", () => {\n spinner.start(\"Thinking...\");\n });\n runtime.events.on(\"token:stream\", (e) => {\n if (!streaming) {\n spinner.stop();\n streaming = true;\n }\n process.stdout.write(e.text);\n });\n runtime.events.on(\"llm:response\", () => {\n if (streaming) {\n process.stdout.write(\"\\n\");\n } else {\n spinner.stop();\n }\n });\n runtime.events.on(\"tool:start\", (e) => {\n if (streaming) {\n process.stdout.write(chalk.dim(\"\\n [using: \" + e.tool_name + \"]\"));\n } else {\n spinner.stop();\n console.log(chalk.dim(\" [using: \" + e.tool_name + \"]\"));\n }\n });\n runtime.events.on(\"tool:end\", (e) => {\n if (streaming) {\n process.stdout.write(chalk.dim(\" [done: \" + e.tool_name + \"]\\n\"));\n }\n });\n runtime.events.on(\"tool:error\", (e) => {\n spinner.stop();\n logger.error({ tool: e.tool_name }, \"Tool error\");\n });\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\";\nimport { createLogger } from \"@tuttiai/core\";\n\nconst logger = createLogger(\"tutti-cli\");\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 postgres: {\n package: \"pg\",\n setup: ` Add ${chalk.bold(\"DATABASE_URL\")} to your .env file:\n ${chalk.cyan(\"DATABASE_URL=postgres://user:pass@localhost:5432/tutti\")}\n\n Add to your score:\n ${chalk.cyan(\"memory: { provider: 'postgres' }\")}\n\n Or with an explicit URL:\n ${chalk.cyan(\"memory: { provider: 'postgres', url: process.env.DATABASE_URL }\")}\n\n Use the async factory for initialization:\n ${chalk.cyan(\"const tutti = await TuttiRuntime.create(score)\")}`,\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\")) as { dependencies?: Record<string, string>; devDependencies?: Record<string, string> };\n const deps: Record<string, string> = { ...pkg.dependencies, ...pkg.devDependencies };\n return packageName in deps;\n } catch {\n return false;\n }\n}\n\nexport function addCommand(voiceName: string): 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 logger.error(\"No package.json found in the current directory\");\n console.error(chalk.dim('Run \"tutti-ai init\" to create a new project first.'));\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 = error instanceof Error ? error.message : String(error);\n logger.error({ error: message, package: packageName }, \"Installation failed\");\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 createLogger,\n} from \"@tuttiai/core\";\n\nconst logger = createLogger(\"tutti-cli\");\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 logger.error(\n { error: err instanceof Error ? err.message : String(err) },\n \"Score validation failed\",\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","import { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { execFile } from \"node:child_process\";\nimport express from \"express\";\nimport chalk from \"chalk\";\nimport {\n TuttiRuntime,\n ScoreLoader,\n createLogger,\n} from \"@tuttiai/core\";\nimport type { Response as ExpressResponse } from \"express\";\n\nconst logger = createLogger(\"tutti-studio\");\nconst envPort = Number.parseInt(process.env.PORT ?? \"\", 10);\nconst PORT = Number.isInteger(envPort) && envPort > 0 && envPort <= 65535 ? envPort : 4747;\n\nfunction safeStringify(obj: unknown): string {\n return JSON.stringify(obj, (_key, value: unknown) => {\n if (value instanceof Error) return { message: value.message, name: value.name };\n if (typeof value === \"function\") return undefined;\n return value;\n });\n}\n\nfunction openBrowser(url: string): void {\n if (process.platform === \"win32\") {\n execFile(\"cmd.exe\", [\"/c\", \"start\", \"\", url]);\n return;\n }\n const cmd = process.platform === \"darwin\" ? \"open\" : \"xdg-open\";\n execFile(cmd, [url]);\n}\n\nexport async function studioCommand(scorePath?: string): Promise<void> {\n const file = resolve(scorePath ?? \"./tutti.score.ts\");\n\n if (!existsSync(file)) {\n logger.error({ file }, \"Score file not found\");\n console.error(chalk.dim('Run \"tutti-ai init\" to create a new project.'));\n process.exit(1);\n }\n\n let score;\n try {\n score = await ScoreLoader.load(file);\n } catch (err) {\n logger.error({ error: err instanceof Error ? err.message : String(err) }, \"Failed to load score\");\n process.exit(1);\n }\n\n const runtime = new TuttiRuntime(score);\n\n // Track sessions via events\n const sessionRegistry = new Map<string, { agent_name: string; created_at: Date }>();\n runtime.events.on(\"agent:start\", (e) => {\n if (!sessionRegistry.has(e.session_id)) {\n sessionRegistry.set(e.session_id, { agent_name: e.agent_name, created_at: new Date() });\n }\n });\n\n // SSE clients\n const sseClients = new Set<ExpressResponse>();\n runtime.events.onAny((event) => {\n const data = safeStringify(event);\n for (const client of sseClients) {\n client.write(\"event: tutti\\ndata: \" + data + \"\\n\\n\");\n }\n });\n\n // Express\n const app = express();\n app.use(express.json());\n\n // SSE endpoint\n app.get(\"/events\", (_req, res) => {\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n });\n res.write(\":\\n\\n\");\n sseClients.add(res);\n _req.on(\"close\", () => sseClients.delete(res));\n });\n\n // REST API\n app.get(\"/api/score\", (_req, res) => {\n const agents = Object.fromEntries(\n Object.entries(runtime.score.agents).map(([id, agent]) => [\n id,\n {\n name: agent.name,\n description: agent.description,\n model: agent.model,\n role: agent.role,\n delegates: agent.delegates,\n voice_count: agent.voices.length,\n voices: agent.voices.map((v) => v.name),\n },\n ]),\n );\n res.json({\n name: runtime.score.name,\n description: runtime.score.description,\n default_model: runtime.score.default_model,\n entry: runtime.score.entry,\n agents,\n });\n });\n\n app.get(\"/api/sessions\", (_req, res) => {\n const sessions = Array.from(sessionRegistry.entries()).map(([id, meta]) => {\n const session = runtime.getSession(id);\n return {\n id,\n agent_name: meta.agent_name,\n message_count: session?.messages.length ?? 0,\n created_at: meta.created_at,\n };\n });\n res.json(sessions.reverse());\n });\n\n app.get(\"/api/sessions/:id\", (req, res) => {\n const session = runtime.getSession(req.params.id);\n if (!session) {\n res.status(404).json({ error: \"Session not found\" });\n return;\n }\n res.json(session);\n });\n\n app.post(\"/api/run\", async (req, res) => {\n const body: unknown = req.body;\n if (typeof body !== \"object\" || body === null) {\n res.status(400).json({ error: \"Invalid request body\" });\n return;\n }\n const agent = (body as Record<string, unknown>).agent;\n const input = (body as Record<string, unknown>).input;\n const session_id = (body as Record<string, unknown>).session_id;\n if (typeof agent !== \"string\" || agent.trim().length === 0) {\n res.status(400).json({ error: \"agent must be a non-empty string\" });\n return;\n }\n if (typeof input !== \"string\" || input.trim().length === 0) {\n res.status(400).json({ error: \"input must be a non-empty string\" });\n return;\n }\n if (session_id !== undefined && (typeof session_id !== \"string\" || session_id.trim().length === 0)) {\n res.status(400).json({ error: \"session_id must be a non-empty string when provided\" });\n return;\n }\n try {\n const result = await runtime.run(agent, input, session_id);\n res.json(result);\n } catch (err) {\n res.status(500).json({ error: err instanceof Error ? err.message : String(err) });\n }\n });\n\n // Serve UI\n app.get(\"/\", (_req, res) => {\n res.type(\"html\").send(getStudioHtml());\n });\n\n app.listen(PORT, () => {\n const url = \"http://localhost:\" + PORT;\n console.log();\n console.log(chalk.bold(\" Tutti Studio\"));\n console.log(chalk.dim(\" \" + url));\n console.log();\n console.log(chalk.dim(\" Score: \") + (runtime.score.name ?? file));\n console.log(chalk.dim(\" Agents: \") + Object.keys(runtime.score.agents).join(\", \"));\n console.log();\n openBrowser(url);\n });\n\n process.on(\"SIGINT\", () => {\n console.log(chalk.dim(\"\\nShutting down Tutti Studio...\"));\n process.exit(0);\n });\n}\n\n// ---------------------------------------------------------------------------\n// Inline HTML UI\n// ---------------------------------------------------------------------------\n\nfunction getStudioHtml(): string {\n return '<!DOCTYPE html>\\\n<html lang=\"en\">\\\n<head>\\\n<meta charset=\"utf-8\">\\\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\\\n<title>Tutti Studio</title>\\\n<style>\\\n*{margin:0;padding:0;box-sizing:border-box}\\\n:root{\\\n--bg:#0a0a0f;--panel:#12121a;--card:#1a1a26;--input:#0f0f17;\\\n--border:#2a2a3a;--text:#e2e8f0;--muted:#64748b;\\\n--purple:#8b5cf6;--teal:#14b8a6;--blue:#3b82f6;--green:#10b981;\\\n--red:#ef4444;--orange:#f97316;--amber:#f59e0b;--indigo:#6366f1;\\\n}\\\nhtml,body{height:100%;font-family:system-ui,-apple-system,sans-serif;background:var(--bg);color:var(--text);font-size:13px}\\\n#app{display:flex;flex-direction:column;height:100vh}\\\n\\\nheader{display:flex;align-items:center;justify-content:space-between;padding:10px 20px;border-bottom:1px solid var(--border);background:var(--panel)}\\\nheader .logo{font-weight:700;font-size:15px;letter-spacing:.5px}\\\nheader .logo span{color:var(--purple)}\\\nheader .meta{color:var(--muted);font-size:12px}\\\nheader .status{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--muted)}\\\nheader .dot{width:7px;height:7px;border-radius:50%;background:var(--green)}\\\nheader .dot.off{background:var(--red)}\\\n\\\nmain{display:grid;grid-template-columns:260px 1fr 280px;flex:1;overflow:hidden;border-bottom:1px solid var(--border)}\\\n\\\n.panel{display:flex;flex-direction:column;border-right:1px solid var(--border);overflow:hidden}\\\n.panel:last-child{border-right:none}\\\n.panel-title{padding:10px 14px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.8px;color:var(--muted);border-bottom:1px solid var(--border);background:var(--panel);flex-shrink:0}\\\n.panel-body{flex:1;overflow-y:auto;padding:10px}\\\n.panel-body::-webkit-scrollbar{width:5px}\\\n.panel-body::-webkit-scrollbar-track{background:transparent}\\\n.panel-body::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}\\\n\\\n#graph-panel .panel-body{padding:0;display:flex;align-items:center;justify-content:center}\\\n#graph-panel svg text{font-family:system-ui,-apple-system,sans-serif}\\\n\\\n#events-panel{display:flex;flex-direction:column}\\\n#event-stream{flex:1;overflow-y:auto;padding:10px}\\\n#event-stream::-webkit-scrollbar{width:5px}\\\n#event-stream::-webkit-scrollbar-track{background:transparent}\\\n#event-stream::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}\\\n\\\n.ev{padding:7px 10px;margin-bottom:6px;border-radius:6px;background:var(--card);border-left:3px solid var(--muted);font-size:12px;line-height:1.5}\\\n.ev .ev-head{display:flex;justify-content:space-between;align-items:center}\\\n.ev .ev-type{font-weight:600;font-family:\"SF Mono\",Menlo,monospace;font-size:11px}\\\n.ev .ev-time{color:var(--muted);font-size:10px;font-family:\"SF Mono\",Menlo,monospace}\\\n.ev .ev-detail{color:var(--muted);margin-top:3px;font-size:11px;word-break:break-all}\\\n.ev.agent{border-left-color:var(--purple)}.ev.agent .ev-type{color:var(--purple)}\\\n.ev.turn{border-left-color:var(--blue)}.ev.turn .ev-type{color:var(--blue)}\\\n.ev.llm{border-left-color:var(--green)}.ev.llm .ev-type{color:var(--green)}\\\n.ev.tool{border-left-color:var(--teal)}.ev.tool .ev-type{color:var(--teal)}\\\n.ev.tool-error{border-left-color:var(--red)}.ev.tool-error .ev-type{color:var(--red)}\\\n.ev.security{border-left-color:var(--orange)}.ev.security .ev-type{color:var(--orange)}\\\n.ev.budget-warn{border-left-color:var(--amber)}.ev.budget-warn .ev-type{color:var(--amber)}\\\n.ev.budget-exceed{border-left-color:var(--red)}.ev.budget-exceed .ev-type{color:var(--red)}\\\n.ev.delegate{border-left-color:var(--indigo)}.ev.delegate .ev-type{color:var(--indigo)}\\\n\\\n#input-bar{display:flex;gap:8px;padding:10px 12px;border-top:1px solid var(--border);background:var(--panel);flex-shrink:0}\\\n#agent-select{background:var(--input);color:var(--text);border:1px solid var(--border);border-radius:6px;padding:6px 10px;font-size:12px;outline:none;cursor:pointer;min-width:110px}\\\n#user-input{flex:1;background:var(--input);color:var(--text);border:1px solid var(--border);border-radius:6px;padding:6px 12px;font-size:13px;outline:none}\\\n#user-input:focus{border-color:var(--purple)}\\\n#send-btn{background:var(--purple);color:#fff;border:none;border-radius:6px;padding:6px 16px;font-size:12px;font-weight:600;cursor:pointer;white-space:nowrap}\\\n#send-btn:hover{opacity:.9}\\\n#send-btn:disabled{opacity:.4;cursor:default}\\\n\\\n.session-item{padding:8px 10px;margin-bottom:4px;border-radius:6px;background:var(--card);cursor:pointer;transition:background .15s}\\\n.session-item:hover{background:#22223a}\\\n.session-item.active{background:#22223a;border:1px solid var(--purple)}\\\n.session-id{font-family:\"SF Mono\",Menlo,monospace;font-size:11px;color:var(--purple)}\\\n.session-meta{font-size:11px;color:var(--muted);margin-top:2px}\\\n\\\n#session-detail{margin-top:10px;border-top:1px solid var(--border);padding-top:10px}\\\n.msg{padding:6px 8px;margin-bottom:4px;border-radius:5px;font-size:12px;line-height:1.5;word-break:break-word}\\\n.msg.user{background:#1c1c3a;border-left:2px solid var(--blue)}\\\n.msg.assistant{background:#1a2a1a;border-left:2px solid var(--green)}\\\n.msg .msg-role{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;margin-bottom:2px}\\\n.msg.user .msg-role{color:var(--blue)}\\\n.msg.assistant .msg-role{color:var(--green)}\\\n\\\nfooter{display:flex;align-items:center;gap:32px;padding:8px 20px;background:var(--panel);font-size:12px}\\\n.token-item{display:flex;align-items:center;gap:6px}\\\n.token-label{color:var(--muted)}\\\n.token-val{font-family:\"SF Mono\",Menlo,monospace;font-weight:600}\\\n.token-val.input{color:var(--blue)}\\\n.token-val.output{color:var(--green)}\\\n.token-val.cost{color:var(--amber)}\\\n\\\n.empty{color:var(--muted);text-align:center;padding:30px 10px;font-size:12px}\\\n</style>\\\n</head>\\\n<body>\\\n<div id=\"app\">\\\n\\\n<header>\\\n <div class=\"logo\"><span>&#9835;</span> Tutti Studio</div>\\\n <div class=\"meta\" id=\"score-name\"></div>\\\n <div class=\"status\"><div class=\"dot\" id=\"sse-dot\"></div><span id=\"sse-label\">connecting</span></div>\\\n</header>\\\n\\\n<main>\\\n <div class=\"panel\" id=\"graph-panel\">\\\n <div class=\"panel-title\">Agent Graph</div>\\\n <div class=\"panel-body\" id=\"graph-body\"></div>\\\n </div>\\\n\\\n <div class=\"panel\" id=\"events-panel\">\\\n <div class=\"panel-title\">Live Event Stream</div>\\\n <div id=\"event-stream\"><div class=\"empty\">Waiting for events&hellip;<br>Send a message below to start an agent run.</div></div>\\\n <div id=\"input-bar\">\\\n <select id=\"agent-select\"></select>\\\n <input id=\"user-input\" placeholder=\"Type a message&hellip;\" autocomplete=\"off\">\\\n <button id=\"send-btn\">Send</button>\\\n </div>\\\n </div>\\\n\\\n <div class=\"panel\" id=\"sessions-panel\">\\\n <div class=\"panel-title\">Sessions</div>\\\n <div class=\"panel-body\" id=\"sessions-body\"><div class=\"empty\">No sessions yet</div></div>\\\n </div>\\\n</main>\\\n\\\n<footer>\\\n <div class=\"token-item\"><span class=\"token-label\">&#x2193; Input</span><span class=\"token-val input\" id=\"tok-in\">0</span></div>\\\n <div class=\"token-item\"><span class=\"token-label\">&#x2191; Output</span><span class=\"token-val output\" id=\"tok-out\">0</span></div>\\\n <div class=\"token-item\"><span class=\"token-label\">$ Est. cost</span><span class=\"token-val cost\" id=\"tok-cost\">0.0000</span></div>\\\n</footer>\\\n\\\n</div>\\\n\\\n<script>\\\n(function(){\\\n\\\nvar tokIn=0,tokOut=0;\\\nvar sessionMap={};\\\nvar activeSession=null;\\\n\\\n/* ---- helpers ---- */\\\nfunction esc(s){var d=document.createElement(\"div\");d.textContent=s;return d.innerHTML}\\\nfunction fmt(n){return n.toLocaleString()}\\\nfunction timeStr(){var d=new Date();return (\"0\"+d.getHours()).slice(-2)+\":\"+(\"0\"+d.getMinutes()).slice(-2)+\":\"+(\"0\"+d.getSeconds()).slice(-2)}\\\nfunction truncId(id){return id.slice(0,8)}\\\n\\\n/* ---- score + graph ---- */\\\nfunction loadScore(){\\\n fetch(\"/api/score\").then(function(r){return r.json()}).then(function(s){\\\n document.getElementById(\"score-name\").textContent=s.name||\"tutti.score.ts\";\\\n var sel=document.getElementById(\"agent-select\");\\\n sel.innerHTML=\"\";\\\n Object.keys(s.agents).forEach(function(id){\\\n var o=document.createElement(\"option\");o.value=id;o.textContent=s.agents[id].name;sel.appendChild(o);\\\n });\\\n renderGraph(s);\\\n });\\\n}\\\n\\\nfunction renderGraph(score){\\\n var body=document.getElementById(\"graph-body\");\\\n var W=260,ids=Object.keys(score.agents),N=ids.length;\\\n if(N===0){body.innerHTML=\"<div class=\\\\\"empty\\\\\">No agents</div>\";return}\\\n var hasDelegate=false;\\\n ids.forEach(function(id){if(score.agents[id].delegates&&score.agents[id].delegates.length)hasDelegate=true});\\\n var nodeR=26,padY=90,padTop=50;\\\n var leftIds=[],rightIds=[];\\\n if(hasDelegate){\\\n ids.forEach(function(id){var a=score.agents[id];if(a.delegates&&a.delegates.length)leftIds.push(id);else rightIds.push(id)});\\\n }else{leftIds=ids}\\\n var cols=hasDelegate?2:1;\\\n var cx1=cols===1?W/2:72,cx2=W-72;\\\n var H=Math.max(leftIds.length,rightIds.length)*padY+padTop*2;\\\n if(H<200)H=200;\\\n var pos={};\\\n var svg=\\'<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"\\'+W+\\'\" height=\"\\'+H+\\'\" viewBox=\"0 0 \\'+W+\" \"+H+\\'\">\\';\\\n svg+=\\'<defs><marker id=\"ah\" viewBox=\"0 0 10 10\" refX=\"10\" refY=\"5\" markerWidth=\"5\" markerHeight=\"5\" orient=\"auto\"><path d=\"M0 0L10 5L0 10z\" fill=\"#64748b\"/></marker></defs>\\';\\\n function drawNode(id,cx,cy){\\\n var a=score.agents[id];\\\n var col=a.role===\"orchestrator\"?\"#8b5cf6\":\"#14b8a6\";\\\n pos[id]={x:cx,y:cy};\\\n svg+=\\'<circle cx=\"\\'+cx+\\'\" cy=\"\\'+cy+\\'\" r=\"\\'+nodeR+\\'\" fill=\"\\'+col+\\'\" fill-opacity=\"0.15\" stroke=\"\\'+col+\\'\" stroke-width=\"2\"/>\\';\\\n svg+=\\'<text x=\"\\'+cx+\\'\" y=\"\\'+(cy+4)+\\'\" text-anchor=\"middle\" fill=\"#e2e8f0\" font-size=\"10\" font-weight=\"600\">\\'+esc(a.name)+\\'</text>\\';\\\n var model=a.model||score.default_model||\"\";\\\n if(model){var sh=model.replace(/-\\\\d{8}$/,\"\");if(sh.length>18)sh=sh.slice(0,18)+\"\\\\u2026\";svg+=\\'<text x=\"\\'+cx+\\'\" y=\"\\'+(cy+nodeR+14)+\\'\" text-anchor=\"middle\" fill=\"#64748b\" font-size=\"9\">\\'+esc(sh)+\\'</text>\\'}\\\n svg+=\\'<text x=\"\\'+cx+\\'\" y=\"\\'+(cy+nodeR+26)+\\'\" text-anchor=\"middle\" fill=\"#64748b\" font-size=\"9\">\\'+a.voice_count+\" voice\"+(a.voice_count!==1?\"s\":\"\")+\\'</text>\\';\\\n }\\\n leftIds.forEach(function(id,i){drawNode(id,cx1,padTop+i*padY)});\\\n rightIds.forEach(function(id,i){drawNode(id,cx2,padTop+i*padY)});\\\n ids.forEach(function(id){\\\n var a=score.agents[id];\\\n if(a.delegates)a.delegates.forEach(function(did){\\\n if(pos[id]&&pos[did]){\\\n var x1=pos[id].x+nodeR,y1=pos[id].y,x2=pos[did].x-nodeR,y2=pos[did].y;\\\n var mx=(x1+x2)/2;\\\n svg+=\\'<path d=\"M\\'+x1+\" \"+y1+\" C\"+mx+\" \"+y1+\" \"+mx+\" \"+y2+\" \"+x2+\" \"+y2+\\'\" fill=\"none\" stroke=\"#64748b\" stroke-width=\"1.5\" stroke-dasharray=\"4 3\" marker-end=\"url(#ah)\"/>\\';\\\n }\\\n });\\\n });\\\n svg+=\"</svg>\";\\\n body.innerHTML=svg;\\\n}\\\n\\\n/* ---- SSE ---- */\\\nfunction connectSSE(){\\\n var es=new EventSource(\"/events\");\\\n es.addEventListener(\"tutti\",function(e){\\\n var ev=JSON.parse(e.data);\\\n addEvent(ev);\\\n if(ev.type===\"llm:response\"&&ev.response&&ev.response.usage){\\\n tokIn+=ev.response.usage.input_tokens||0;\\\n tokOut+=ev.response.usage.output_tokens||0;\\\n document.getElementById(\"tok-in\").textContent=fmt(tokIn);\\\n document.getElementById(\"tok-out\").textContent=fmt(tokOut);\\\n document.getElementById(\"tok-cost\").textContent=estimateCost(tokIn,tokOut);\\\n }\\\n if(ev.type===\"agent:start\"||ev.type===\"agent:end\")refreshSessions();\\\n });\\\n es.onopen=function(){document.getElementById(\"sse-dot\").className=\"dot\";document.getElementById(\"sse-label\").textContent=\"connected\"};\\\n es.onerror=function(){document.getElementById(\"sse-dot\").className=\"dot off\";document.getElementById(\"sse-label\").textContent=\"disconnected\"};\\\n}\\\n\\\n/* Pricing: USD per 1M tokens (Sonnet-class default) */\\\nvar INPUT_PRICE_PER_MILLION=3;\\\nvar OUTPUT_PRICE_PER_MILLION=15;\\\nfunction estimateCost(inp,out){\\\n var c=(inp/1e6)*INPUT_PRICE_PER_MILLION+(out/1e6)*OUTPUT_PRICE_PER_MILLION;\\\n return c.toFixed(4);\\\n}\\\n\\\nfunction evClass(t){\\\n if(t.indexOf(\"agent\")===0)return \"agent\";\\\n if(t.indexOf(\"turn\")===0)return \"turn\";\\\n if(t===\"llm:request\"||t===\"llm:response\")return \"llm\";\\\n if(t===\"tool:error\")return \"tool-error\";\\\n if(t.indexOf(\"tool\")===0)return \"tool\";\\\n if(t.indexOf(\"security\")===0)return \"security\";\\\n if(t===\"budget:warning\")return \"budget-warn\";\\\n if(t===\"budget:exceeded\")return \"budget-exceed\";\\\n if(t.indexOf(\"delegate\")===0)return \"delegate\";\\\n return \"\";\\\n}\\\n\\\nfunction evDetail(ev){\\\n var parts=[];\\\n if(ev.agent_name)parts.push(\"agent: \"+ev.agent_name);\\\n if(ev.session_id)parts.push(\"session: \"+truncId(ev.session_id));\\\n if(ev.turn!==undefined)parts.push(\"turn: \"+ev.turn);\\\n if(ev.tool_name)parts.push(\"tool: \"+ev.tool_name);\\\n if(ev.from)parts.push(\"from: \"+ev.from);\\\n if(ev.to)parts.push(\"to: \"+ev.to);\\\n if(ev.tokens!==undefined)parts.push(\"tokens: \"+fmt(ev.tokens));\\\n if(ev.cost_usd!==undefined)parts.push(\"cost: $\"+ev.cost_usd.toFixed(4));\\\n if(ev.response&&ev.response.usage)parts.push(\"tokens: \"+fmt(ev.response.usage.input_tokens)+\" in / \"+fmt(ev.response.usage.output_tokens)+\" out\");\\\n if(ev.error){var em=typeof ev.error===\"object\"?ev.error.message||\"\":ev.error;if(em)parts.push(\"error: \"+em)}\\\n if(ev.patterns)parts.push(\"patterns: \"+ev.patterns.join(\", \"));\\\n return parts.join(\" &middot; \");\\\n}\\\n\\\nvar firstEvent=true;\\\nfunction addEvent(ev){\\\n var stream=document.getElementById(\"event-stream\");\\\n if(firstEvent){stream.innerHTML=\"\";firstEvent=false}\\\n var div=document.createElement(\"div\");\\\n div.className=\"ev \"+evClass(ev.type);\\\n div.innerHTML=\\'<div class=\"ev-head\"><span class=\"ev-type\">\\'+esc(ev.type)+\\'</span><span class=\"ev-time\">\\'+timeStr()+\\'</span></div>\\';\\\n var det=evDetail(ev);\\\n if(det)div.innerHTML+=\\'<div class=\"ev-detail\">\\'+det+\"</div>\";\\\n stream.appendChild(div);\\\n stream.scrollTop=stream.scrollHeight;\\\n}\\\n\\\n/* ---- sessions ---- */\\\nfunction refreshSessions(){\\\n fetch(\"/api/sessions\").then(function(r){return r.json()}).then(function(list){\\\n var body=document.getElementById(\"sessions-body\");\\\n if(!list.length){body.innerHTML=\\'<div class=\"empty\">No sessions yet</div>\\';return}\\\n var html=\"\";\\\n list.forEach(function(s){\\\n var cls=\"session-item\"+(activeSession===s.id?\" active\":\"\");\\\n html+=\\'<div class=\"\\'+cls+\\'\" data-id=\"\\'+s.id+\\'\">\\';\\\n html+=\\'<div class=\"session-id\">\\'+truncId(s.id)+\"</div>\";\\\n html+=\\'<div class=\"session-meta\">\\'+esc(s.agent_name)+\" &middot; \"+s.message_count+\" msgs</div>\";\\\n html+=\"</div>\";\\\n });\\\n if(activeSession)html+=\\'<div id=\"session-detail\"></div>\\';\\\n body.innerHTML=html;\\\n body.querySelectorAll(\".session-item\").forEach(function(el){\\\n el.addEventListener(\"click\",function(){selectSession(el.getAttribute(\"data-id\"))});\\\n });\\\n if(activeSession)loadSessionDetail(activeSession);\\\n });\\\n}\\\n\\\nfunction selectSession(id){\\\n activeSession=activeSession===id?null:id;\\\n refreshSessions();\\\n}\\\n\\\nfunction loadSessionDetail(id){\\\n var det=document.getElementById(\"session-detail\");\\\n if(!det)return;\\\n fetch(\"/api/sessions/\"+id).then(function(r){return r.json()}).then(function(session){\\\n if(!session||session.error){det.innerHTML=\\'<div class=\"empty\">Session not found</div>\\';return}\\\n var html=\"\";\\\n (session.messages||[]).forEach(function(m){\\\n var role=m.role;\\\n var text=\"\";\\\n if(typeof m.content===\"string\")text=m.content;\\\n else if(Array.isArray(m.content)){\\\n m.content.forEach(function(b){\\\n if(b.type===\"text\")text+=b.text+\"\\\\n\";\\\n else if(b.type===\"tool_use\")text+=\"[tool_use: \"+b.name+\"]\\\\n\";\\\n else if(b.type===\"tool_result\")text+=\"[tool_result]\\\\n\";\\\n });\\\n }\\\n html+=\\'<div class=\"msg \\'+role+\\'\"><div class=\"msg-role\">\\'+role+\"</div>\"+esc(text.trim())+\"</div>\";\\\n });\\\n det.innerHTML=html;\\\n });\\\n}\\\n\\\n/* ---- send ---- */\\\nfunction sendMessage(){\\\n var agentSel=document.getElementById(\"agent-select\");\\\n var inputEl=document.getElementById(\"user-input\");\\\n var btn=document.getElementById(\"send-btn\");\\\n var agent=agentSel.value;\\\n var input=inputEl.value.trim();\\\n if(!input)return;\\\n btn.disabled=true;btn.textContent=\"Running\\\\u2026\";\\\n inputEl.value=\"\";\\\n var sid=sessionMap[agent]||undefined;\\\n fetch(\"/api/run\",{method:\"POST\",headers:{\"Content-Type\":\"application/json\"},body:JSON.stringify({agent:agent,input:input,session_id:sid})})\\\n .then(function(r){return r.json()})\\\n .then(function(result){\\\n if(result.session_id)sessionMap[agent]=result.session_id;\\\n if(result.output){\\\n addEvent({type:\"__output\",agent_name:agent,output:result.output});\\\n }\\\n refreshSessions();\\\n })\\\n .catch(function(err){addEvent({type:\"__error\",error:err.message||String(err)})})\\\n .finally(function(){btn.disabled=false;btn.textContent=\"Send\"});\\\n}\\\n\\\ndocument.getElementById(\"send-btn\").addEventListener(\"click\",sendMessage);\\\ndocument.getElementById(\"user-input\").addEventListener(\"keydown\",function(e){if(e.key===\"Enter\"&&!e.shiftKey){e.preventDefault();sendMessage()}});\\\n\\\n/* ---- init ---- */\\\nloadScore();\\\nconnectSSE();\\\n\\\n})();\\\n</script>\\\n</body>\\\n</html>';\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { createLogger } from \"@tuttiai/core\";\n\nconst logger = createLogger(\"tutti-cli\");\n\nconst REGISTRY_URL =\n \"https://raw.githubusercontent.com/tuttiai/voices/main/voices.json\";\n\ninterface VoiceEntry {\n name: string;\n package: string;\n description: string;\n tags: string[];\n official: boolean;\n tools: number;\n}\n\n// Built-in fallback when the remote registry is unreachable\nconst BUILTIN_VOICES: VoiceEntry[] = [\n {\n name: \"filesystem\",\n package: \"@tuttiai/filesystem\",\n description: \"Read, write, search, and manage files and directories\",\n tags: [\"filesystem\", \"files\", \"io\", \"read\", \"write\"],\n official: true,\n tools: 7,\n },\n {\n name: \"github\",\n package: \"@tuttiai/github\",\n description: \"Interact with GitHub repos, issues, PRs, and code search\",\n tags: [\"github\", \"git\", \"code\", \"issues\", \"pull-requests\", \"api\"],\n official: true,\n tools: 10,\n },\n {\n name: \"playwright\",\n package: \"@tuttiai/playwright\",\n description: \"Control a browser like a human — navigate, click, type, screenshot\",\n tags: [\"browser\", \"playwright\", \"web\", \"qa\", \"testing\", \"automation\", \"scraping\"],\n official: true,\n tools: 12,\n },\n {\n name: \"postgres\",\n package: \"pg\",\n description: \"PostgreSQL session persistence and database access\",\n tags: [\"database\", \"postgres\", \"sql\", \"persistence\", \"sessions\"],\n official: true,\n tools: 0,\n },\n];\n\ninterface RegistryEntry {\n name: string;\n package: string;\n description: string;\n tags: string[];\n}\n\nasync function fetchRegistry(): Promise<VoiceEntry[]> {\n try {\n const res = await fetch(REGISTRY_URL);\n if (!res.ok) throw new Error(\"HTTP \" + res.status);\n const data = (await res.json()) as { official?: RegistryEntry[]; community?: RegistryEntry[] };\n\n const voices: VoiceEntry[] = [];\n for (const entry of data.official ?? []) {\n voices.push({ ...entry, official: true, tools: toolCount(entry.name) });\n }\n for (const entry of data.community ?? []) {\n voices.push({ ...entry, official: false, tools: 0 });\n }\n if (voices.length === 0) throw new Error(\"Empty registry\");\n return voices;\n } catch {\n logger.debug(\"Registry unreachable, using built-in voice list\");\n return BUILTIN_VOICES;\n }\n}\n\nfunction toolCount(name: string): number {\n const counts: Record<string, number> = { filesystem: 7, github: 10, playwright: 12 };\n return counts[name] ?? 0;\n}\n\nfunction matchesQuery(voice: VoiceEntry, query: string): boolean {\n const q = query.toLowerCase();\n if (voice.name.toLowerCase().includes(q)) return true;\n if (voice.description.toLowerCase().includes(q)) return true;\n if (voice.tags.some((t) => t.toLowerCase().includes(q))) return true;\n return false;\n}\n\nfunction isInstalled(packageName: string): boolean {\n const pkgPath = resolve(process.cwd(), \"package.json\");\n if (!existsSync(pkgPath)) return false;\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\")) as { dependencies?: Record<string, string>; devDependencies?: Record<string, string> };\n const deps: Record<string, string> = { ...pkg.dependencies, ...pkg.devDependencies };\n return packageName in deps;\n } catch {\n return false;\n }\n}\n\nfunction printVoice(voice: VoiceEntry, showInstallStatus: boolean): void {\n const badge = voice.official\n ? chalk.green(\" [official]\")\n : chalk.blue(\" [community]\");\n const installed = showInstallStatus && isInstalled(voice.package);\n const status = showInstallStatus\n ? installed\n ? chalk.green(\" ✔ installed\")\n : chalk.dim(\" not installed\")\n : \"\";\n\n console.log();\n console.log(\" \" + chalk.bold(voice.package) + badge + status);\n console.log(\" \" + voice.description);\n\n const installCmd = voice.official && voice.name !== \"postgres\"\n ? \"tutti-ai add \" + voice.name\n : \"npm install \" + voice.package;\n console.log(\" \" + chalk.dim(\"Install: \") + chalk.cyan(installCmd));\n\n if (voice.tags.length > 0) {\n console.log(\" \" + chalk.dim(\"Tags: \") + voice.tags.join(\", \"));\n }\n}\n\nexport async function searchCommand(query: string): Promise<void> {\n const spinner = ora(\"Searching the Repertoire...\").start();\n\n const voices = await fetchRegistry();\n const results = voices.filter((v) => matchesQuery(v, query));\n\n spinner.stop();\n\n if (results.length === 0) {\n console.log();\n console.log(chalk.yellow(' No voices found for \"' + query + '\"'));\n console.log();\n console.log(chalk.dim(\" Browse all: https://tutti-ai.com/voices\"));\n console.log(chalk.dim(\" Build your own: tutti-ai create voice <name>\"));\n console.log();\n return;\n }\n\n console.log();\n console.log(\n \" Found \" +\n chalk.bold(String(results.length)) +\n \" voice\" +\n (results.length !== 1 ? \"s\" : \"\") +\n \" matching \" +\n chalk.cyan(\"'\" + query + \"'\") +\n \":\",\n );\n\n for (const voice of results) {\n printVoice(voice, false);\n }\n console.log();\n}\n\nexport async function voicesCommand(): Promise<void> {\n const spinner = ora(\"Loading voices...\").start();\n\n const voices = await fetchRegistry();\n const official = voices.filter((v) => v.official);\n\n spinner.stop();\n\n console.log();\n console.log(\" \" + chalk.bold(\"Official Tutti Voices\"));\n console.log();\n\n for (const voice of official) {\n printVoice(voice, true);\n }\n\n const community = voices.filter((v) => !v.official);\n if (community.length > 0) {\n console.log();\n console.log(\" \" + chalk.bold(\"Community Voices\"));\n for (const voice of community) {\n printVoice(voice, true);\n }\n }\n\n console.log();\n console.log(chalk.dim(\" Search: tutti-ai search <query>\"));\n console.log(chalk.dim(\" Browse: https://tutti-ai.com/voices\"));\n console.log();\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\";\nimport Enquirer from \"enquirer\";\nimport { createLogger, SecretsManager } from \"@tuttiai/core\";\n\nconst { prompt } = Enquirer;\nconst logger = createLogger(\"tutti-cli\");\n\ninterface PkgJson {\n name?: string;\n version?: string;\n description?: string;\n license?: string;\n exports?: unknown;\n}\n\nfunction readPkg(dir: string): PkgJson | undefined {\n const p = resolve(dir, \"package.json\");\n if (!existsSync(p)) return undefined;\n return JSON.parse(readFileSync(p, \"utf-8\")) as PkgJson;\n}\n\nfunction run(cmd: string, cwd: string): string {\n return execSync(cmd, { cwd, stdio: \"pipe\", encoding: \"utf-8\" });\n}\n\nfunction fail(msg: string): never {\n console.error(chalk.red(\" \" + msg));\n process.exit(1);\n}\n\nconst ok = (msg: string) => console.log(chalk.green(\" ✔ \" + msg));\n\nexport async function publishCommand(opts: { dryRun?: boolean }): Promise<void> {\n const cwd = process.cwd();\n const pkg = readPkg(cwd);\n\n console.log();\n console.log(chalk.bold(\" Tutti Voice Publisher\"));\n console.log();\n\n // ── Step 1: Pre-flight checks ──\n\n const spinner = ora(\"Running pre-flight checks...\").start();\n\n // 1a. Must be a voice directory\n if (!pkg) fail(\"No package.json found in the current directory.\");\n if (!existsSync(resolve(cwd, \"src/index.ts\"))) fail(\"No src/index.ts found — are you inside a voice directory?\");\n\n // 1b. Required fields\n const missing: string[] = [];\n if (!pkg.name) missing.push(\"name\");\n if (!pkg.version) missing.push(\"version\");\n if (!pkg.description) missing.push(\"description\");\n if (!pkg.license) missing.push(\"license\");\n if (!pkg.exports) missing.push(\"exports\");\n if (missing.length > 0) fail(\"package.json is missing: \" + missing.join(\", \"));\n\n const name = pkg.name!;\n const version = pkg.version!;\n\n // 1c. Name convention\n const validName = name.startsWith(\"@tuttiai/\") || name.startsWith(\"tutti\");\n if (!validName) fail(\"Package name must start with @tuttiai/ or tutti — got: \" + name);\n\n // 1d. Check required_permissions is declared in source\n const src = readFileSync(resolve(cwd, \"src/index.ts\"), \"utf-8\");\n if (!src.includes(\"required_permissions\")) {\n fail(\"Voice class must declare required_permissions in src/index.ts\");\n }\n\n spinner.succeed(\"Pre-flight checks passed\");\n\n // 1e. Build\n const buildSpinner = ora(\"Building...\").start();\n try {\n run(\"npm run build\", cwd);\n buildSpinner.succeed(\"Build succeeded\");\n } catch (err) {\n buildSpinner.fail(\"Build failed\");\n const msg = err instanceof Error ? err.message : String(err);\n console.error(chalk.dim(\" \" + msg.split(\"\\n\").slice(0, 5).join(\"\\n \")));\n process.exit(1);\n }\n\n // 1f. Tests\n const testSpinner = ora(\"Running tests...\").start();\n try {\n run(\"npx vitest run\", cwd);\n testSpinner.succeed(\"Tests passed\");\n } catch {\n testSpinner.fail(\"Tests failed\");\n process.exit(1);\n }\n\n // 1g. Audit\n const auditSpinner = ora(\"Checking vulnerabilities...\").start();\n try {\n run(\"npm audit --audit-level=high\", cwd);\n auditSpinner.succeed(\"No high/critical vulnerabilities\");\n } catch {\n auditSpinner.stopAndPersist({ symbol: chalk.yellow(\"⚠\"), text: \"Vulnerabilities found (npm audit)\" });\n }\n\n // ── Step 2: Dry run ──\n\n console.log();\n const drySpinner = ora(\"Packing (dry run)...\").start();\n let packOutput: string;\n try {\n packOutput = run(\"npm pack --dry-run 2>&1\", cwd);\n drySpinner.succeed(\"Pack dry-run complete\");\n } catch (err) {\n drySpinner.fail(\"Pack dry-run failed\");\n const msg = err instanceof Error ? err.message : String(err);\n console.error(chalk.dim(\" \" + msg));\n process.exit(1);\n }\n\n // Show files from the pack output\n const fileLines = packOutput\n .split(\"\\n\")\n .filter((l) => l.includes(\"npm notice\") && /\\d+(\\.\\d+)?\\s*[kM]?B\\s/.test(l))\n .map((l) => l.replace(/npm notice\\s*/, \"\"));\n\n if (fileLines.length > 0) {\n console.log(chalk.dim(\" Files:\"));\n for (const line of fileLines) {\n console.log(chalk.dim(\" \" + line.trim()));\n }\n }\n\n // Show totals\n const sizeLine = packOutput.split(\"\\n\").find((l) => l.includes(\"package size\"));\n const totalLine = packOutput.split(\"\\n\").find((l) => l.includes(\"total files\"));\n if (sizeLine) console.log(chalk.dim(\" \" + sizeLine.replace(/npm notice\\s*/, \"\").trim()));\n if (totalLine) console.log(chalk.dim(\" \" + totalLine.replace(/npm notice\\s*/, \"\").trim()));\n\n if (opts.dryRun) {\n console.log();\n ok(\"Dry run complete — no packages were published\");\n console.log(chalk.dim(\" Run without --dry-run to publish for real.\"));\n console.log();\n return;\n }\n\n // Prompt for confirmation\n console.log();\n const { confirm } = await prompt<{ confirm: boolean }>({\n type: \"confirm\",\n name: \"confirm\",\n message: \"Publish \" + chalk.cyan(name + \"@\" + version) + \"?\",\n });\n\n if (!confirm) {\n console.log(chalk.dim(\" Cancelled.\"));\n return;\n }\n\n // ── Step 3: Publish ──\n\n const pubSpinner = ora(\"Publishing to npm...\").start();\n try {\n run(\"npm publish --access public\", cwd);\n pubSpinner.succeed(\"Published \" + chalk.cyan(name + \"@\" + version));\n } catch (err) {\n pubSpinner.fail(\"Publish failed\");\n const msg = err instanceof Error ? err.message : String(err);\n logger.error({ error: msg }, \"npm publish failed\");\n process.exit(1);\n }\n\n // ── Step 4: Open PR to voice registry ──\n\n const ghToken = SecretsManager.optional(\"GITHUB_TOKEN\");\n let prUrl: string | undefined;\n\n if (ghToken) {\n const prSpinner = ora(\"Opening PR to voice registry...\").start();\n try {\n prUrl = await openRegistryPR(name, version, pkg.description ?? \"\", ghToken);\n prSpinner.succeed(\"PR opened: \" + prUrl);\n } catch (err) {\n prSpinner.fail(\"Failed to open PR\");\n const msg = err instanceof Error ? err.message : String(err);\n logger.error({ error: msg }, \"Registry PR failed\");\n }\n } else {\n console.log();\n console.log(chalk.dim(\" To list in the Repertoire, set GITHUB_TOKEN and re-run\"));\n console.log(chalk.dim(\" Or open a PR manually: github.com/tuttiai/voices\"));\n }\n\n // ── Step 5: Summary ──\n\n console.log();\n ok(name + \"@\" + version + \" published to npm\");\n if (prUrl) ok(\"PR opened to tuttiai/voices\");\n const shortName = name.replace(\"@tuttiai/\", \"\").replace(/^tutti-?/, \"\");\n ok(\"Install: tutti-ai add \" + shortName);\n ok(\"View: https://www.npmjs.com/package/\" + name);\n console.log();\n}\n\nasync function openRegistryPR(\n packageName: string,\n version: string,\n description: string,\n token: string,\n): Promise<string> {\n const owner = \"tuttiai\";\n const repo = \"voices\";\n const branch = \"add-\" + packageName.replace(/[@/]/g, \"-\").replace(/^-/, \"\");\n const shortName = packageName.replace(\"@tuttiai/\", \"\").replace(/^tutti-?/, \"\");\n const isOfficial = packageName.startsWith(\"@tuttiai/\");\n\n // 1. Get current voices.json content and SHA\n const fileRes = await fetch(\n \"https://api.github.com/repos/\" + owner + \"/\" + repo + \"/contents/voices.json\",\n { headers: { Authorization: \"Bearer \" + token, Accept: \"application/vnd.github.v3+json\" } },\n );\n if (!fileRes.ok) throw new Error(\"Failed to fetch voices.json: \" + fileRes.status);\n const fileData = (await fileRes.json()) as { content: string; sha: string };\n\n interface RegistryVoice { name: string; package: string; description: string; version: string; author: string; tags: string[]; repo?: string }\n interface Registry { official: RegistryVoice[]; community: RegistryVoice[] }\n\n const registry = JSON.parse(Buffer.from(fileData.content, \"base64\").toString(\"utf-8\")) as Registry;\n\n // 2. Add the new voice entry\n const section: keyof Registry = isOfficial ? \"official\" : \"community\";\n const entry: RegistryVoice = {\n name: shortName,\n package: packageName,\n description,\n repo: \"https://github.com/tuttiai/tutti/tree/main/voices/\" + shortName,\n version,\n author: isOfficial ? \"tuttiai\" : packageName.split(\"/\")[0]?.replace(\"@\", \"\") ?? \"community\",\n tags: [shortName],\n };\n\n if (!registry[section]) registry[section] = [];\n const exists = registry[section].some((v) => v.package === packageName);\n if (exists) {\n const idx = registry[section].findIndex((v) => v.package === packageName);\n registry[section][idx] = { ...registry[section][idx], ...entry };\n } else {\n registry[section].push(entry);\n }\n\n const updatedContent = Buffer.from(JSON.stringify(registry, null, 2) + \"\\n\").toString(\"base64\");\n\n // 3. Get default branch SHA\n const mainRes = await fetch(\n \"https://api.github.com/repos/\" + owner + \"/\" + repo + \"/git/ref/heads/main\",\n { headers: { Authorization: \"Bearer \" + token, Accept: \"application/vnd.github.v3+json\" } },\n );\n if (!mainRes.ok) throw new Error(\"Failed to get main ref: \" + mainRes.status);\n const mainData = (await mainRes.json()) as { object: { sha: string } };\n\n // 4. Create branch\n await fetch(\"https://api.github.com/repos/\" + owner + \"/\" + repo + \"/git/refs\", {\n method: \"POST\",\n headers: { Authorization: \"Bearer \" + token, \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ ref: \"refs/heads/\" + branch, sha: mainData.object.sha }),\n });\n\n // 5. Update voices.json on the new branch\n await fetch(\n \"https://api.github.com/repos/\" + owner + \"/\" + repo + \"/contents/voices.json\",\n {\n method: \"PUT\",\n headers: { Authorization: \"Bearer \" + token, \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n message: \"feat: add \" + packageName + \" to the Repertoire\",\n content: updatedContent,\n sha: fileData.sha,\n branch,\n }),\n },\n );\n\n // 6. Create PR\n const prRes = await fetch(\"https://api.github.com/repos/\" + owner + \"/\" + repo + \"/pulls\", {\n method: \"POST\",\n headers: { Authorization: \"Bearer \" + token, \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n title: \"feat: add \" + packageName + \" to the Repertoire\",\n head: branch,\n base: \"main\",\n body: \"## New voice: \" + packageName + \"@\" + version + \"\\n\\n\" + description + \"\\n\\nPublished via `tutti-ai publish`.\",\n }),\n });\n\n if (!prRes.ok) {\n const err = await prRes.text();\n throw new Error(\"Failed to create PR: \" + prRes.status + \" \" + err);\n }\n\n const prData = (await prRes.json()) as { html_url: string };\n return prData.html_url;\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport {\n ScoreLoader,\n EvalRunner,\n printEvalTable,\n createLogger,\n} from \"@tuttiai/core\";\nimport type { EvalSuite } from \"@tuttiai/core\";\n\nconst logger = createLogger(\"tutti-cli\");\n\nexport async function evalCommand(suitePath: string, opts: { ci?: boolean; score?: string }): Promise<void> {\n const suiteFile = resolve(suitePath);\n if (!existsSync(suiteFile)) {\n logger.error({ file: suiteFile }, \"Suite file not found\");\n process.exit(1);\n }\n\n // Load the eval suite JSON\n let suite: EvalSuite;\n try {\n suite = JSON.parse(readFileSync(suiteFile, \"utf-8\")) as EvalSuite;\n } catch (err) {\n logger.error({ error: err instanceof Error ? err.message : String(err) }, \"Failed to parse suite file\");\n process.exit(1);\n }\n\n // Load score\n const scoreFile = resolve(opts.score ?? \"./tutti.score.ts\");\n if (!existsSync(scoreFile)) {\n logger.error({ file: scoreFile }, \"Score file not found\");\n process.exit(1);\n }\n\n const spinner = ora(\"Loading score...\").start();\n let score;\n try {\n score = await ScoreLoader.load(scoreFile);\n } catch (err) {\n spinner.fail(\"Failed to load score\");\n logger.error({ error: err instanceof Error ? err.message : String(err) }, \"Score load failed\");\n process.exit(1);\n }\n spinner.succeed(\"Score loaded\");\n\n // Run eval\n const evalSpinner = ora(\"Running \" + suite.cases.length + \" eval cases...\").start();\n const runner = new EvalRunner(score);\n const report = await runner.run(suite);\n evalSpinner.stop();\n\n // Print results\n printEvalTable(report);\n\n // CI mode: exit 1 if any failed\n if (opts.ci && report.summary.failed > 0) {\n console.error(chalk.red(\" CI mode: \" + report.summary.failed + \" case(s) failed\"));\n process.exit(1);\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport chalk from \"chalk\";\nimport {\n TuttiRuntime,\n ScoreLoader,\n AnthropicProvider,\n OpenAIProvider,\n GeminiProvider,\n SecretsManager,\n InMemorySessionStore,\n createLogger,\n} from \"@tuttiai/core\";\nimport type { ScoreConfig, SessionStore } from \"@tuttiai/types\";\nimport { createServer, DEFAULT_PORT, SERVER_VERSION } from \"@tuttiai/server\";\nimport type { FastifyInstance } from \"fastify\";\nimport { ReactiveScore } from \"../watch/score-watcher.js\";\n\nconst logger = createLogger(\"tutti-serve\");\n\nexport interface ServeOptions {\n port?: string;\n host?: string;\n apiKey?: string;\n agent?: string;\n watch?: boolean;\n}\n\nexport async function serveCommand(\n scorePath?: string,\n options: ServeOptions = {},\n): Promise<void> {\n // ── Resolve score file ──────────────────────────────────────\n const file = resolve(scorePath ?? \"./tutti.score.ts\");\n\n if (!existsSync(file)) {\n logger.error({ file }, \"Score file not found\");\n console.error(chalk.dim('Run \"tutti-ai init\" to create a new project.'));\n process.exit(1);\n }\n\n let score: ScoreConfig;\n try {\n score = await ScoreLoader.load(file);\n } catch (err) {\n logger.error(\n { error: err instanceof Error ? err.message : String(err) },\n \"Failed to load score\",\n );\n process.exit(1);\n }\n\n // ── Validate provider 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 logger.error({ envVar }, \"Missing API key\");\n process.exit(1);\n }\n }\n }\n\n // ── Resolve agent name ──────────────────────────────────────\n const agentNames = Object.keys(score.agents);\n const agentName =\n options.agent ??\n (typeof score.entry === \"string\" ? score.entry : undefined) ??\n agentNames[0];\n\n if (!agentName || !score.agents[agentName]) {\n logger.error(\n { requested: agentName, available: agentNames },\n \"Agent not found in score\",\n );\n process.exit(1);\n }\n\n // ── Resolve port & host ─────────────────────────────────────\n const port = parsePort(options.port);\n const host = options.host ?? \"0.0.0.0\";\n\n // ── Build runtime and server ────────────────────────────────\n // Watch mode keeps a shared session store so hot-reloads don't\n // discard in-flight sessions.\n const sharedSessions: SessionStore | undefined = options.watch\n ? new InMemorySessionStore()\n : undefined;\n\n let runtime = buildRuntime(score, sharedSessions);\n let app = await buildApp(runtime, agentName, port, host, options.apiKey);\n\n // ── Watch mode ──────────────────────────────────────────────\n let reactive: ReactiveScore | undefined;\n if (options.watch) {\n reactive = new ReactiveScore(score, file);\n\n reactive.on(\"file-change\", () => {\n console.log(chalk.cyan(\"\\n[tutti] Score changed, reloading...\"));\n });\n\n reactive.on(\"reloaded\", () => {\n void (async () => {\n try {\n const nextScore = reactive!.current;\n const nextRuntime = buildRuntime(nextScore, sharedSessions);\n const nextApp = await buildApp(nextRuntime, agentName, port, host, options.apiKey);\n\n await app.close();\n runtime = nextRuntime;\n app = nextApp;\n await app.listen({ port, host });\n\n console.log(chalk.green(\"[tutti] Score reloaded. Server restarted.\"));\n } catch (err) {\n logger.error(\n { error: err instanceof Error ? err.message : String(err) },\n \"[tutti] Reload failed — server continues with previous config\",\n );\n }\n })();\n });\n\n reactive.on(\"reload-failed\", (err) => {\n logger.error(\n { error: err instanceof Error ? err.message : String(err) },\n \"[tutti] Reload failed — server continues with previous config\",\n );\n });\n }\n\n // ── Start listening ─────────────────────────────────────────\n await app.listen({ port, host });\n\n printBanner(port, host, agentName, score, file, options.watch);\n\n // ── Graceful shutdown ───────────────────────────────────────\n const shutdown = async (signal: string) => {\n console.log(chalk.dim(\"\\n\" + signal + \" received — shutting down...\"));\n if (reactive) await reactive.close();\n await app.close();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", () => void shutdown(\"SIGINT\"));\n process.on(\"SIGTERM\", () => void shutdown(\"SIGTERM\"));\n}\n\n// ── Helpers ──────────────────────────────────────────────────\n\nfunction parsePort(raw: string | undefined): number {\n if (raw === undefined) return DEFAULT_PORT;\n const n = Number.parseInt(raw, 10);\n if (!Number.isInteger(n) || n < 1 || n > 65535) {\n logger.error({ port: raw }, \"Invalid port number\");\n process.exit(1);\n }\n return n;\n}\n\nfunction buildRuntime(\n score: ScoreConfig,\n sessionStore: SessionStore | undefined,\n): TuttiRuntime {\n return new TuttiRuntime(\n score,\n sessionStore ? { sessionStore } : {},\n );\n}\n\nasync function buildApp(\n runtime: TuttiRuntime,\n agentName: string,\n port: number,\n host: string,\n apiKey: string | undefined,\n): Promise<FastifyInstance> {\n return createServer({\n port,\n host,\n runtime,\n agent_name: agentName,\n api_key: apiKey,\n });\n}\n\nfunction printBanner(\n port: number,\n host: string,\n agentName: string,\n score: ScoreConfig,\n file: string,\n watch: boolean | undefined,\n): void {\n const display = host === \"0.0.0.0\" || host === \"::\" ? \"localhost\" : host;\n const url = \"http://\" + display + \":\" + port;\n\n console.log();\n console.log(chalk.bold(\" Tutti Server v\" + SERVER_VERSION));\n console.log(chalk.dim(\" \" + url));\n console.log();\n console.log(chalk.dim(\" Score: \") + (score.name ?? file));\n console.log(chalk.dim(\" Agent: \") + agentName);\n console.log(chalk.dim(\" Agents: \") + Object.keys(score.agents).join(\", \"));\n if (watch) {\n console.log(chalk.dim(\" Watch: \") + chalk.cyan(\"enabled\"));\n }\n console.log();\n console.log(chalk.dim(\" Endpoints:\"));\n console.log(chalk.dim(\" POST \") + url + \"/run\");\n console.log(chalk.dim(\" POST \") + url + \"/run/stream\");\n console.log(chalk.dim(\" GET \") + url + \"/sessions/:id\");\n console.log(chalk.dim(\" GET \") + url + \"/health\");\n console.log();\n}\n"],"mappings":"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","names":["createLogger","existsSync","resolve","chalk","createLogger","logger","createLogger","resolve","existsSync","chalk","existsSync","resolve","createInterface","chalk","ora","AnthropicProvider","GeminiProvider","OpenAIProvider","ScoreLoader","SecretsManager","TuttiRuntime","createLogger","logger","existsSync","resolve","chalk","ora","createLogger","logger","existsSync","resolve","chalk","ScoreLoader","AnthropicProvider","OpenAIProvider","GeminiProvider","SecretsManager","createLogger","logger","existsSync","resolve","chalk","TuttiRuntime","ScoreLoader","createLogger","logger","existsSync","readFileSync","resolve","chalk","ora","createLogger","logger","existsSync","readFileSync","resolve","execSync","chalk","ora","Enquirer","createLogger","SecretsManager","prompt","logger","fail","ok","existsSync","readFileSync","resolve","chalk","ora","ScoreLoader","createLogger","logger","existsSync","resolve","chalk","TuttiRuntime","ScoreLoader","AnthropicProvider","OpenAIProvider","GeminiProvider","SecretsManager","InMemorySessionStore","createLogger","logger","createLogger","resolve","existsSync","chalk","ScoreLoader","AnthropicProvider","OpenAIProvider","GeminiProvider","SecretsManager","InMemorySessionStore","buildRuntime","TuttiRuntime","logger","createLogger"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/templates/index.ts","../src/commands/run.ts","../src/watch/score-watcher.ts","../src/commands/resume.ts","../src/commands/add.ts","../src/commands/check.ts","../src/commands/studio.ts","../src/commands/search.ts","../src/commands/publish.ts","../src/commands/eval.ts","../src/commands/serve.ts","../src/commands/schedule.ts","../src/commands/schedules.ts"],"sourcesContent":["import { config } from \"dotenv\";\nconfig();\n\nimport { createLogger } from \"@tuttiai/core\";\nconst logger = createLogger(\"tutti-cli\");\n\nprocess.on(\"unhandledRejection\", (reason) => {\n logger.error({ error: reason instanceof Error ? reason.message : String(reason) }, \"Unhandled rejection\");\n process.exit(1);\n});\n\nprocess.on(\"uncaughtException\", (err) => {\n logger.error({ error: err.message }, \"Fatal error\");\n process.exit(1);\n});\n\nimport { Command } from \"commander\";\nimport { initCommand, templatesCommand } from \"./commands/init.js\";\nimport { runCommand } from \"./commands/run.js\";\nimport { resumeCommand, type ResumeOptions } from \"./commands/resume.js\";\nimport { addCommand } from \"./commands/add.js\";\nimport { checkCommand } from \"./commands/check.js\";\nimport { studioCommand } from \"./commands/studio.js\";\nimport { searchCommand, voicesCommand } from \"./commands/search.js\";\nimport { publishCommand } from \"./commands/publish.js\";\nimport { evalCommand } from \"./commands/eval.js\";\nimport { serveCommand, type ServeOptions } from \"./commands/serve.js\";\nimport { scheduleCommand } from \"./commands/schedule.js\";\nimport {\n schedulesListCommand,\n schedulesEnableCommand,\n schedulesDisableCommand,\n schedulesTriggerCommand,\n schedulesRunsCommand,\n} from \"./commands/schedules.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.12.0\");\n\nprogram\n .command(\"init [project-name]\")\n .description(\"Create a new Tutti project\")\n .option(\"-t, --template <id>\", \"Project template to use\")\n .action(async (projectName: string | undefined, opts: { template?: string }) => {\n await initCommand(projectName, opts.template);\n });\n\nprogram\n .command(\"templates\")\n .description(\"List all available project templates\")\n .action(() => {\n templatesCommand();\n });\n\nprogram\n .command(\"run [score]\")\n .description(\"Run a Tutti score interactively\")\n .option(\"-w, --watch\", \"Reload the score on file changes\")\n .action(async (score: string | undefined, opts: { watch?: boolean }) => {\n await runCommand(score, { watch: opts.watch });\n });\n\nprogram\n .command(\"serve [score]\")\n .description(\"Start the Tutti HTTP server\")\n .option(\"-p, --port <number>\", \"Port to listen on (default: 3847)\")\n .option(\"-H, --host <address>\", \"Host to bind to (default: 0.0.0.0)\")\n .option(\"-k, --api-key <key>\", \"API key for bearer auth (or set TUTTI_API_KEY)\")\n .option(\"-a, --agent <name>\", \"Agent to expose (default: score entry or first agent)\")\n .option(\"-w, --watch\", \"Reload the score on file changes\")\n .action(async (score: string | undefined, opts: ServeOptions) => {\n await serveCommand(score, opts);\n });\n\nprogram\n .command(\"resume <session-id>\")\n .description(\"Resume a crashed or interrupted run from its last checkpoint\")\n .option(\n \"--store <backend>\",\n \"Durable store the checkpoint was written to (redis | postgres)\",\n \"redis\",\n )\n .option(\"-s, --score <path>\", \"Path to score file (default: ./tutti.score.ts)\")\n .option(\"-a, --agent <name>\", \"Agent key to resume (default: score.entry or the first agent)\")\n .option(\"-y, --yes\", \"Skip the confirmation prompt\")\n .action(\n async (\n sessionId: string,\n opts: { store?: string; score?: string; agent?: string; yes?: boolean },\n ) => {\n if (opts.store !== \"redis\" && opts.store !== \"postgres\") {\n console.error(\"--store must be 'redis' or 'postgres'\");\n process.exit(1);\n }\n const resolved: ResumeOptions = {\n store: opts.store,\n ...(opts.score !== undefined ? { score: opts.score } : {}),\n ...(opts.agent !== undefined ? { agent: opts.agent } : {}),\n ...(opts.yes !== undefined ? { yes: opts.yes } : {}),\n };\n await resumeCommand(sessionId, resolved);\n },\n );\n\nprogram\n .command(\"add <voice>\")\n .description(\"Add a voice to your project\")\n .action((voice: string) => {\n 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\n .command(\"studio [score]\")\n .description(\"Launch Tutti Studio — local web UI for inspecting agent runs\")\n .action(async (score?: string) => {\n await studioCommand(score);\n });\n\nprogram\n .command(\"search <query>\")\n .description(\"Search the voice registry for voices matching a query\")\n .action(async (query: string) => {\n await searchCommand(query);\n });\n\nprogram\n .command(\"voices\")\n .description(\"List all available official voices and install status\")\n .action(async () => {\n await voicesCommand();\n });\n\nprogram\n .command(\"publish\")\n .description(\"Publish the current voice to npm and the voice registry\")\n .option(\"--dry-run\", \"Run all checks without publishing\")\n .action(async (opts: { dryRun?: boolean }) => {\n await publishCommand(opts);\n });\n\nprogram\n .command(\"eval <suite-file>\")\n .description(\"Run an evaluation suite against a score\")\n .option(\"--ci\", \"Exit with code 1 if any case fails\")\n .option(\"-s, --score <path>\", \"Path to score file (default: ./tutti.score.ts)\")\n .action(async (suitePath: string, opts: { ci?: boolean; score?: string }) => {\n await evalCommand(suitePath, opts);\n });\n\nprogram\n .command(\"schedule [score]\")\n .description(\"Start the scheduler daemon — runs agents on their configured schedules\")\n .action(async (score?: string) => {\n await scheduleCommand(score);\n });\n\nconst schedulesCmd = program\n .command(\"schedules\")\n .description(\"Manage scheduled agents\");\n\nschedulesCmd\n .command(\"list\")\n .description(\"Show all registered schedules\")\n .action(async () => {\n await schedulesListCommand();\n });\n\nschedulesCmd\n .command(\"enable <id>\")\n .description(\"Enable a disabled schedule\")\n .action(async (id: string) => {\n await schedulesEnableCommand(id);\n });\n\nschedulesCmd\n .command(\"disable <id>\")\n .description(\"Disable a schedule without deleting it\")\n .action(async (id: string) => {\n await schedulesDisableCommand(id);\n });\n\nschedulesCmd\n .command(\"trigger <id>\")\n .description(\"Manually trigger a scheduled run immediately\")\n .option(\"-s, --score <path>\", \"Path to score file (default: ./tutti.score.ts)\")\n .action(async (id: string, opts: { score?: string }) => {\n await schedulesTriggerCommand(id, opts.score);\n });\n\nschedulesCmd\n .command(\"runs <id>\")\n .description(\"Show run history for a schedule (last 20 runs)\")\n .action(async (id: string) => {\n await schedulesRunsCommand(id);\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\";\nimport { createLogger } from \"@tuttiai/core\";\nimport { TEMPLATES, getTemplate } from \"../templates/index.js\";\nimport type { Template } from \"../templates/index.js\";\n\nconst logger = createLogger(\"tutti-cli\");\n\nconst { prompt } = Enquirer;\n\nexport async function initCommand(projectName?: string, templateId?: 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 logger.error(\"Project name is required\");\n process.exit(1);\n }\n\n const dir = join(process.cwd(), projectName);\n\n if (existsSync(dir)) {\n logger.error({ dir: `${projectName}/` }, \"Directory already exists\");\n process.exit(1);\n }\n\n // Resolve template\n let template: Template | undefined;\n if (templateId) {\n template = getTemplate(templateId);\n if (!template) {\n logger.error({ template: templateId }, \"Unknown template\");\n console.error(chalk.dim(\" Available: \" + TEMPLATES.map((t) => t.id).join(\", \")));\n process.exit(1);\n }\n } else {\n // Interactive picker\n const response = await prompt<{ templateId: string }>({\n type: \"select\",\n name: \"templateId\",\n message: \"Which template?\",\n choices: TEMPLATES.map((t) => ({\n name: t.id,\n message: t.name + chalk.dim(\" — \" + t.description),\n })),\n });\n template = getTemplate(response.templateId);\n if (!template) template = TEMPLATES[0];\n }\n\n mkdirSync(dir, { recursive: true });\n\n const deps: Record<string, string> = {\n \"@tuttiai/core\": \"*\",\n \"@tuttiai/types\": \"*\",\n ...template.deps,\n };\n\n const envLines = [\n \"ANTHROPIC_API_KEY=your_key_here\",\n ...template.envVars,\n \"\",\n \"# Log level: debug | info | warn | error (default: info)\",\n \"TUTTI_LOG_LEVEL=info\",\n \"\",\n \"# OpenTelemetry (optional)\",\n \"# OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318\",\n \"# OTEL_SERVICE_NAME=tutti\",\n ];\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: deps,\n devDependencies: {\n tsx: \"^4.0.0\",\n typescript: \"^5.7.0\",\n },\n },\n null,\n 2,\n ),\n\n \".env.example\": envLines.join(\"\\n\") + \"\\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\": template.score,\n\n \"README.md\": `# ${projectName}\n\nA Tutti agent project. All agents. All together.\n\n**Template:** ${template.name} — ${template.description}\n\n## Setup\n\n\\`\\`\\`bash\ncp .env.example .env\n# Add your API keys 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}/`) + chalk.dim(` (${template.name})`));\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\nexport function templatesCommand(): void {\n console.log();\n console.log(chalk.bold(\" Available Templates\"));\n console.log();\n for (const t of TEMPLATES) {\n console.log(\" \" + chalk.cyan(t.id.padEnd(18)) + t.description);\n }\n console.log();\n console.log(chalk.dim(\" Use: tutti-ai init my-project --template \" + TEMPLATES[0].id));\n console.log();\n}\n","export interface Template {\n id: string;\n name: string;\n description: string;\n deps: Record<string, string>;\n envVars: string[];\n score: string;\n}\n\nconst minimal: Template = {\n id: \"minimal\",\n name: \"Minimal\",\n description: \"One agent, no voices — the simplest starting point\",\n deps: {},\n envVars: [],\n score: `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\nconst codingAgent: Template = {\n id: \"coding-agent\",\n name: \"Coding Agent\",\n description: \"TypeScript developer with filesystem + GitHub access\",\n deps: { \"@tuttiai/filesystem\": \"*\", \"@tuttiai/github\": \"*\" },\n envVars: [\"GITHUB_TOKEN=ghp_your_token_here\"],\n score: `import { defineScore, AnthropicProvider } from \"@tuttiai/core\"\nimport { FilesystemVoice } from \"@tuttiai/filesystem\"\nimport { GitHubVoice } from \"@tuttiai/github\"\n\nexport default defineScore({\n provider: new AnthropicProvider(),\n default_model: \"claude-sonnet-4-20250514\",\n agents: {\n coder: {\n name: \"Coder\",\n system_prompt:\n \"You are an expert TypeScript developer. \" +\n \"You read and write code using the filesystem voice, \" +\n \"and manage issues and PRs via the GitHub voice. \" +\n \"Write clean, tested, well-documented code.\",\n voices: [new FilesystemVoice(), new GitHubVoice()],\n permissions: [\"filesystem\", \"network\"],\n streaming: true,\n }\n }\n})\n`,\n};\n\nconst researchAgent: Template = {\n id: \"research-agent\",\n name: \"Research Agent\",\n description: \"Researcher that saves structured notes to files\",\n deps: { \"@tuttiai/filesystem\": \"*\" },\n envVars: [],\n score: `import { defineScore, AnthropicProvider } from \"@tuttiai/core\"\nimport { FilesystemVoice } from \"@tuttiai/filesystem\"\n\nexport default defineScore({\n provider: new AnthropicProvider(),\n default_model: \"claude-sonnet-4-20250514\",\n agents: {\n researcher: {\n name: \"Researcher\",\n system_prompt:\n \"You are an expert researcher. \" +\n \"Analyze topics thoroughly, cite sources, and save \" +\n \"structured notes as markdown files using the filesystem voice. \" +\n \"Organize findings with clear headings and bullet points.\",\n voices: [new FilesystemVoice()],\n permissions: [\"filesystem\"],\n streaming: true,\n }\n }\n})\n`,\n};\n\nconst qaPipeline: Template = {\n id: \"qa-pipeline\",\n name: \"QA Pipeline\",\n description: \"Orchestrator + QA specialist with browser testing and HITL\",\n deps: { \"@tuttiai/playwright\": \"*\" },\n envVars: [],\n score: `import { defineScore, AnthropicProvider } from \"@tuttiai/core\"\nimport { PlaywrightVoice } from \"@tuttiai/playwright\"\n\nexport default defineScore({\n provider: new AnthropicProvider(),\n default_model: \"claude-sonnet-4-20250514\",\n entry: \"orchestrator\",\n agents: {\n orchestrator: {\n name: \"QA Lead\",\n system_prompt:\n \"You are a QA lead. Triage incoming bugs by delegating \" +\n \"browser testing to the QA specialist. Use human-in-the-loop \" +\n \"to ask for approval before marking bugs as verified.\",\n voices: [],\n role: \"orchestrator\",\n delegates: [\"qa\"],\n allow_human_input: true,\n streaming: true,\n },\n qa: {\n name: \"QA Specialist\",\n system_prompt:\n \"You are a QA engineer. Navigate to URLs, check elements, \" +\n \"take screenshots, and verify bug reports using the browser.\",\n voices: [new PlaywrightVoice()],\n permissions: [\"network\", \"browser\"],\n role: \"specialist\",\n budget: { max_cost_usd: 0.50, warn_at_percent: 80 },\n streaming: true,\n }\n }\n})\n`,\n};\n\nconst devTeam: Template = {\n id: \"dev-team\",\n name: \"Dev Team\",\n description: \"Full team: orchestrator + coder + PM + QA with all voices\",\n deps: {\n \"@tuttiai/filesystem\": \"*\",\n \"@tuttiai/github\": \"*\",\n \"@tuttiai/playwright\": \"*\",\n },\n envVars: [\"GITHUB_TOKEN=ghp_your_token_here\"],\n score: `import { defineScore, AnthropicProvider, createLoggingHook, createBlocklistHook, createLogger } from \"@tuttiai/core\"\nimport { FilesystemVoice } from \"@tuttiai/filesystem\"\nimport { GitHubVoice } from \"@tuttiai/github\"\nimport { PlaywrightVoice } from \"@tuttiai/playwright\"\n\nconst logger = createLogger(\"dev-team\")\n\nexport default defineScore({\n provider: new AnthropicProvider(),\n default_model: \"claude-sonnet-4-20250514\",\n entry: \"orchestrator\",\n hooks: {\n ...createLoggingHook(logger),\n ...createBlocklistHook([\"delete_file\"]),\n },\n agents: {\n orchestrator: {\n name: \"Tech Lead\",\n system_prompt:\n \"You are the tech lead. Break tasks into subtasks and delegate: \" +\n \"code tasks to Coder, documentation to PM, testing to QA. \" +\n \"Review outputs before presenting to the user.\",\n voices: [],\n role: \"orchestrator\",\n delegates: [\"coder\", \"pm\", \"qa\"],\n allow_human_input: true,\n streaming: true,\n },\n coder: {\n name: \"Coder\",\n system_prompt:\n \"You are a senior TypeScript developer. Write clean, tested code. \" +\n \"Use the filesystem voice to read/write files and GitHub to manage PRs.\",\n voices: [new FilesystemVoice(), new GitHubVoice()],\n permissions: [\"filesystem\", \"network\"],\n role: \"specialist\",\n streaming: true,\n },\n pm: {\n name: \"PM\",\n system_prompt:\n \"You are a product manager. Write specs, update documentation, \" +\n \"and create GitHub issues for tracking. Focus on clarity and completeness.\",\n voices: [new FilesystemVoice(), new GitHubVoice()],\n permissions: [\"filesystem\", \"network\"],\n role: \"specialist\",\n streaming: true,\n },\n qa: {\n name: \"QA\",\n system_prompt:\n \"You are a QA engineer. Test features in the browser, verify bugs, \" +\n \"and write test reports. Screenshot evidence for every finding.\",\n voices: [new PlaywrightVoice()],\n permissions: [\"network\", \"browser\"],\n role: \"specialist\",\n budget: { max_cost_usd: 1.00 },\n streaming: true,\n }\n }\n})\n`,\n};\n\nexport const TEMPLATES: Template[] = [minimal, codingAgent, researchAgent, qaPipeline, devTeam];\n\nexport function getTemplate(id: string): Template | undefined {\n return TEMPLATES.find((t) => t.id === id);\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 InMemorySessionStore,\n createLogger,\n} from \"@tuttiai/core\";\nimport type { ScoreConfig, SessionStore } from \"@tuttiai/types\";\nimport { ReactiveScore } from \"../watch/score-watcher.js\";\n\nconst logger = createLogger(\"tutti-cli\");\n\nexport interface RunOptions {\n /** Reload the score on file changes. */\n watch?: boolean;\n}\n\nexport async function runCommand(\n scorePath?: string,\n options: RunOptions = {},\n): Promise<void> {\n const file = resolve(scorePath ?? \"./tutti.score.ts\");\n\n if (!existsSync(file)) {\n logger.error({ file }, \"Score file not found\");\n console.error(chalk.dim('Run \"tutti-ai init\" to create a new project.'));\n process.exit(1);\n }\n\n let score;\n try {\n score = await ScoreLoader.load(file);\n } catch (err) {\n logger.error(\n { error: err instanceof Error ? err.message : String(err) },\n \"Failed to load score\",\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 logger.error({ envVar }, \"Missing API key\");\n process.exit(1);\n }\n }\n }\n\n // Enable streaming on every agent in the score. Factored out so we can\n // reapply it after a hot-reload in watch mode.\n const applyRunDefaults = (cfg: ScoreConfig): void => {\n for (const agent of Object.values(cfg.agents)) {\n agent.streaming = true;\n }\n };\n applyRunDefaults(score);\n\n // Build a single session store up front in watch mode so the\n // conversation history survives runtime swaps. Non-watch runs can let\n // TuttiRuntime provision its own store from score.memory as usual.\n const sharedSessions: SessionStore | undefined = options.watch\n ? new InMemorySessionStore()\n : undefined;\n\n const spinner = ora({ color: \"cyan\" });\n\n // REPL-level state. `streaming` resets per turn; `runtime` may be\n // swapped by the hot-reload path below.\n let streaming = false;\n let runtime = buildRuntime(score, sharedSessions);\n\n attachListeners(runtime);\n\n // REPL readline — created early so the HITL handler below can use it.\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n // Wire per-runtime listeners. Separated from the REPL so a hot-reload\n // can swap the runtime and re-wire without touching the outer loop.\n function attachListeners(r: TuttiRuntime): void {\n r.events.on(\"agent:start\", (e) => {\n logger.info({ agent: e.agent_name }, \"Running agent\");\n });\n\n r.events.on(\"llm:request\", () => {\n spinner.start(\"Thinking...\");\n });\n\n r.events.on(\"token:stream\", (e) => {\n if (!streaming) {\n spinner.stop();\n streaming = true;\n }\n process.stdout.write(e.text);\n });\n\n r.events.on(\"llm:response\", () => {\n if (streaming) {\n process.stdout.write(\"\\n\");\n } else {\n spinner.stop();\n }\n });\n\n r.events.on(\"tool:start\", (e) => {\n if (streaming) {\n process.stdout.write(chalk.dim(\"\\n [using: \" + e.tool_name + \"]\"));\n } else {\n spinner.stop();\n console.log(chalk.dim(\" [using: \" + e.tool_name + \"]\"));\n }\n });\n\n r.events.on(\"tool:end\", (e) => {\n if (streaming) {\n process.stdout.write(chalk.dim(\" [done: \" + e.tool_name + \"]\\n\"));\n }\n });\n\n r.events.on(\"tool:error\", (e) => {\n spinner.stop();\n logger.error({ tool: e.tool_name }, \"Tool error\");\n });\n\n r.events.on(\"security:injection_detected\", (e) => {\n logger.warn({ tool: e.tool_name }, \"Potential prompt injection detected\");\n });\n\n r.events.on(\"budget:warning\", () => {\n logger.warn(\"Approaching token budget (80%)\");\n });\n\n r.events.on(\"budget:exceeded\", () => {\n logger.error(\"Token budget exceeded — stopping\");\n });\n\n r.events.on(\"hitl:requested\", (e) => {\n spinner.stop();\n if (streaming) {\n process.stdout.write(\"\\n\");\n streaming = false;\n }\n console.log();\n console.log(\n chalk.yellow(\n \" \" + chalk.bold(\"[Agent needs input]\") + \" \" + e.question,\n ),\n );\n if (e.options) {\n e.options.forEach((opt, i) => {\n console.log(chalk.yellow(\" \" + (i + 1) + \". \" + opt));\n });\n }\n void rl.question(chalk.yellow(\" > \")).then((answer) => {\n runtime.answer(e.session_id, answer.trim());\n });\n });\n }\n\n // --- Watch mode wiring ---------------------------------------------------\n // Scope: set up a ReactiveScore that reloads the score file on change\n // and surfaces status to the REPL. The REPL checks `pendingReload`\n // between turns (so we never interrupt a mid-turn call) and swaps\n // `runtime` when appropriate.\n let reactive: ReactiveScore | undefined;\n if (options.watch) {\n reactive = new ReactiveScore(score, file);\n reactive.on(\"file-change\", () => {\n console.log(chalk.cyan(\"\\n[tutti] Score changed, reloading...\"));\n });\n reactive.on(\"reloaded\", () => {\n // Defer the actual swap to the next turn boundary — the REPL loop\n // checks `pendingReload` before each iteration. Applying mid-turn\n // would either interrupt a tool call or strand events listeners\n // pointing at the old runtime instance.\n console.log(chalk.green(\"[tutti] Score reloaded. Changes applied.\"));\n });\n reactive.on(\"reload-failed\", (err) => {\n logger.error(\n { error: err instanceof Error ? err.message : String(err) },\n \"[tutti] Reload failed — using previous config\",\n );\n });\n }\n\n // REPL\n console.log(chalk.dim('Tutti REPL — type \"exit\" to quit\\n'));\n if (options.watch) {\n console.log(chalk.dim(\"Watching \" + file + \" for changes…\\n\"));\n }\n\n let sessionId: string | undefined;\n\n // Handle Ctrl+C cleanly\n process.on(\"SIGINT\", () => {\n if (streaming) process.stdout.write(\"\\n\");\n spinner.stop();\n console.log(chalk.dim(\"Goodbye!\"));\n rl.close();\n if (reactive) void reactive.close();\n process.exit(0);\n });\n\n try {\n while (true) {\n // Apply any pending hot-reload before we start the next turn. This\n // is the \"don't interrupt mid-tool-call\" guarantee — we only swap\n // at a REPL-loop boundary, after the previous `run()` resolved.\n if (reactive?.pendingReload) {\n const nextScore = reactive.current;\n applyRunDefaults(nextScore);\n runtime = buildRuntime(nextScore, sharedSessions);\n attachListeners(runtime);\n reactive.consumePendingReload();\n }\n\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 // Reset streaming state for this run\n streaming = false;\n\n try {\n const result = await runtime.run(\"assistant\", trimmed, sessionId);\n sessionId = result.session_id;\n\n if (!streaming) {\n console.log(\"\\n\" + result.output + \"\\n\");\n } else {\n console.log();\n }\n } catch (err) {\n if (streaming) process.stdout.write(\"\\n\");\n spinner.stop();\n logger.error(\n { error: err instanceof Error ? err.message : String(err) },\n \"Something went wrong\",\n );\n }\n }\n } catch {\n // readline closed\n }\n\n console.log(chalk.dim(\"Goodbye!\"));\n rl.close();\n if (reactive) await reactive.close();\n process.exit(0);\n}\n\nfunction buildRuntime(\n score: ScoreConfig,\n sessionStore: SessionStore | undefined,\n): TuttiRuntime {\n return new TuttiRuntime(\n score,\n sessionStore ? { sessionStore } : {},\n );\n}\n","import { dirname, resolve } from \"node:path\";\nimport { EventEmitter } from \"node:events\";\nimport chokidar, { type FSWatcher } from \"chokidar\";\nimport type { ScoreConfig } from \"@tuttiai/types\";\nimport { validateScore } from \"@tuttiai/core\";\n\n/** How long to wait after the last change event before reloading. */\nconst DEFAULT_DEBOUNCE_MS = 200;\n\n/** Default ignore-patterns for the directory-tree watch. */\nconst DEFAULT_IGNORED = [\n /(^|[/\\\\])\\../, // dotfiles (.git, .env, etc.)\n /node_modules/,\n /[/\\\\]dist[/\\\\]/,\n /[/\\\\]coverage[/\\\\]/,\n];\n\n/**\n * Load a score module with ESM cache-busting. Node's ESM cache is per-URL\n * and cannot be invalidated, so we append a unique query parameter on\n * each reload to force a fresh module instance. The old instance stays in\n * memory — acceptable leak for a development-only watch loop.\n */\nasync function defaultLoadScore(path: string): Promise<ScoreConfig> {\n const absolute = resolve(path);\n // Node's ESM cache is per-URL and can't be invalidated — append a\n // unique query parameter so each reload gets a fresh module instance.\n // The previous instance stays in memory (small leak, acceptable for a\n // development-only watch loop).\n const { pathToFileURL } = await import(\"node:url\");\n const url = pathToFileURL(absolute).href + \"?t=\" + Date.now().toString(36);\n const mod = (await import(url)) as { default?: ScoreConfig };\n if (!mod.default) {\n throw new Error(\n \"Score file has no default export: \" + path +\n \" — your score must export `defineScore({ ... })` as its default.\",\n );\n }\n // Validate the freshly-loaded score. `ScoreLoader.load` would have run\n // the same validator but on a stale cache entry, so we inline it.\n validateScore(mod.default);\n return mod.default;\n}\n\nexport interface ReactiveScoreEvents {\n /** Emitted immediately when a watched file changes (before debounce settles). */\n \"file-change\": (changedPath: string) => void;\n /** Emitted when a reload attempt starts (after debounce). */\n reloading: () => void;\n /** Emitted when a reload succeeds — `current` now returns the new score. */\n reloaded: (score: ScoreConfig) => void;\n /**\n * Emitted when a reload fails. The previous `current` score is kept so\n * the REPL can continue with the last-known-good config.\n */\n \"reload-failed\": (error: Error) => void;\n}\n\nexport interface ReactiveScoreOptions {\n /**\n * Additional paths or glob patterns to watch beyond the score file and\n * its parent directory. Useful when voices live elsewhere.\n */\n extraPaths?: string[];\n /** Debounce window in ms. Default 200. */\n debounceMs?: number;\n /**\n * Override the score loader. Primarily a test seam — production code\n * uses the default cache-busting ESM importer.\n */\n load?: (path: string) => Promise<ScoreConfig>;\n}\n\n/**\n * A {@link ScoreConfig} that refreshes itself when the underlying file\n * (or any file in its directory) changes on disk.\n *\n * Consumers read `reactive.current` before each turn and get the most\n * recent successfully-loaded score. On a reload failure (syntax error in\n * the score file, schema validation, etc.), `current` keeps returning the\n * previous value — callers can listen for `reload-failed` to surface the\n * error in their UI.\n */\nexport class ReactiveScore extends EventEmitter {\n private _current: ScoreConfig;\n private readonly scorePath: string;\n private readonly load: (path: string) => Promise<ScoreConfig>;\n private readonly debounceMs: number;\n private readonly watcher: FSWatcher;\n private debounceTimer: ReturnType<typeof setTimeout> | undefined;\n private closed = false;\n private _pendingReload = false;\n\n constructor(\n initialScore: ScoreConfig,\n scorePath: string,\n options: ReactiveScoreOptions = {},\n ) {\n super();\n this._current = initialScore;\n this.scorePath = resolve(scorePath);\n this.load = options.load ?? defaultLoadScore;\n this.debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;\n\n // Watch the score file, its parent directory tree, and any extras.\n // Directory-tree watching catches voice files and local utility\n // modules without needing a proper import-graph resolver; the\n // trade-off is that unrelated files in the tree also trigger reloads.\n const watchTargets = [\n this.scorePath,\n dirname(this.scorePath),\n ...(options.extraPaths ?? []),\n ];\n this.watcher = chokidar.watch(watchTargets, {\n ignored: DEFAULT_IGNORED,\n ignoreInitial: true,\n // awaitWriteFinish: guard against partial writes from editors that\n // save atomically via rename/move.\n awaitWriteFinish: {\n stabilityThreshold: 50,\n pollInterval: 20,\n },\n });\n\n this.watcher.on(\"change\", (path) => this.handleChange(path));\n this.watcher.on(\"add\", (path) => this.handleChange(path));\n }\n\n /** The most recent successfully-loaded score. Never stale. */\n get current(): ScoreConfig {\n return this._current;\n }\n\n /**\n * True when a file change has been observed and a reload is pending\n * (or just completed and not yet consumed). Readers call\n * {@link consumePendingReload} to clear the flag when they've taken\n * action on the new config.\n */\n get pendingReload(): boolean {\n return this._pendingReload;\n }\n\n consumePendingReload(): void {\n this._pendingReload = false;\n }\n\n /** Release the underlying filesystem watchers. */\n async close(): Promise<void> {\n this.closed = true;\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n await this.watcher.close();\n }\n\n /**\n * Force an immediate reload without waiting for a filesystem event.\n * Exposed for tests and for the `reload` REPL command.\n */\n async reloadNow(): Promise<void> {\n if (this.closed) return;\n this.emit(\"reloading\");\n try {\n const next = await this.load(this.scorePath);\n this._current = next;\n this._pendingReload = true;\n this.emit(\"reloaded\", next);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n this.emit(\"reload-failed\", error);\n }\n }\n\n private handleChange(path: string): void {\n if (this.closed) return;\n this.emit(\"file-change\", path);\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n this.debounceTimer = setTimeout(() => {\n void this.reloadNow();\n }, this.debounceMs);\n }\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 AnthropicProvider,\n GeminiProvider,\n OpenAIProvider,\n ScoreLoader,\n SecretsManager,\n TuttiRuntime,\n createCheckpointStore,\n createLogger,\n type Checkpoint,\n type ChatMessage,\n} from \"@tuttiai/core\";\nconst logger = createLogger(\"tutti-cli\");\n\nexport interface ResumeOptions {\n /** Which durable store the checkpoint was written to. */\n store: \"redis\" | \"postgres\";\n /** Path to the score file (defaults to ./tutti.score.ts). */\n score?: string;\n /** Agent key to resume; defaults to the score's entry agent. */\n agent?: string;\n /** Skip the confirmation prompt — for scripted use. */\n yes?: boolean;\n}\n\nexport async function resumeCommand(\n sessionId: string,\n opts: ResumeOptions,\n): Promise<void> {\n // --- Score loading (same flow as `run`) -------------------------------\n const scoreFile = resolve(opts.score ?? \"./tutti.score.ts\");\n if (!existsSync(scoreFile)) {\n logger.error({ file: scoreFile }, \"Score file not found\");\n console.error(chalk.dim('Run \"tutti-ai init\" to create a new project.'));\n process.exit(1);\n }\n\n let score;\n try {\n score = await ScoreLoader.load(scoreFile);\n } catch (err) {\n logger.error(\n { error: err instanceof Error ? err.message : String(err) },\n \"Failed to load score\",\n );\n process.exit(1);\n }\n\n // --- Provider API-key check (same shortlist as `run`) -----------------\n const providerKeyMap: [unknown, string][] = [\n [AnthropicProvider, \"ANTHROPIC_API_KEY\"],\n [OpenAIProvider, \"OPENAI_API_KEY\"],\n [GeminiProvider, \"GEMINI_API_KEY\"],\n ];\n for (const [ProviderClass, envVar] of providerKeyMap) {\n if (\n score.provider instanceof\n (ProviderClass as new (...args: unknown[]) => unknown)\n ) {\n if (!SecretsManager.optional(envVar)) {\n logger.error({ envVar }, \"Missing API key\");\n process.exit(1);\n }\n }\n }\n\n // --- Resolve the target agent -----------------------------------------\n const agentName = resolveAgentName(score, opts.agent);\n const agent = score.agents[agentName];\n if (!agent) {\n logger.error(\n { agent: agentName, available: Object.keys(score.agents) },\n \"Agent not found in score\",\n );\n process.exit(1);\n }\n if (!agent.durable) {\n console.error(\n chalk.yellow(\n \"Agent '\" +\n agentName +\n \"' does not have `durable: true` set — resume has nothing to restore.\",\n ),\n );\n console.error(\n chalk.dim(\n \"Enable durable checkpointing on the agent before the run that created this session.\",\n ),\n );\n process.exit(1);\n }\n\n // --- Load the checkpoint ----------------------------------------------\n const spinner = ora({ color: \"cyan\" }).start(\"Loading checkpoint...\");\n let checkpointStore;\n let checkpoint: Checkpoint | null;\n try {\n checkpointStore = createCheckpointStore({ store: opts.store });\n checkpoint = await checkpointStore.loadLatest(sessionId);\n } catch (err) {\n spinner.fail(\"Failed to load checkpoint\");\n logger.error(\n { error: err instanceof Error ? err.message : String(err), store: opts.store },\n \"Checkpoint store error\",\n );\n process.exit(1);\n }\n spinner.stop();\n\n if (!checkpoint) {\n console.error(\n chalk.red(\"No checkpoint found for session \" + sessionId + \".\"),\n );\n console.error(\n chalk.dim(\n \"Verify TUTTI_\" +\n (opts.store === \"redis\" ? \"REDIS\" : \"PG\") +\n \"_URL points to the same \" +\n opts.store +\n \" the original run used.\",\n ),\n );\n process.exit(1);\n }\n\n // --- Render the summary -----------------------------------------------\n printSummary(checkpoint);\n\n // --- Confirm (unless --yes) -------------------------------------------\n if (!opts.yes && !(await confirmResume(checkpoint.turn))) {\n console.log(chalk.dim(\"Cancelled.\"));\n process.exit(0);\n }\n\n // --- Build the runtime and hand off to AgentRunner --------------------\n const runtime = new TuttiRuntime(score, { checkpointStore });\n\n // Seed the session store with a synthetic Session so the runner's\n // `sessions.get(id)` lookup succeeds. The agent loop immediately\n // overwrites `messages` from the checkpoint — the seeded messages\n // array only exists so the initial get() call doesn't miss.\n const sessions = runtime.sessions;\n if (\"save\" in sessions && typeof sessions.save === \"function\") {\n (sessions.save as (s: { id: string; agent_name: string; messages: ChatMessage[]; created_at: Date; updated_at: Date }) => void)({\n id: sessionId,\n agent_name: agentName,\n messages: [...checkpoint.messages],\n created_at: checkpoint.saved_at,\n updated_at: new Date(),\n });\n } else {\n console.error(\n chalk.red(\n \"Session store does not support resume seeding. Use the default InMemorySessionStore or PostgresSessionStore.\",\n ),\n );\n process.exit(1);\n }\n\n wireProgress(runtime);\n\n try {\n // Input is ignored when the runner sees a mid-cycle checkpoint, but\n // we still need a non-empty value to satisfy the method signature.\n const result = await runtime.run(agentName, \"[resume]\", sessionId);\n console.log();\n console.log(chalk.green(\"✓ Resumed run complete.\"));\n console.log(chalk.dim(\" Final turn: \" + result.turns));\n console.log(chalk.dim(\" Session ID: \" + result.session_id));\n console.log(\n chalk.dim(\n \" Token usage: \" +\n result.usage.input_tokens +\n \" in / \" +\n result.usage.output_tokens +\n \" out\",\n ),\n );\n console.log();\n console.log(result.output);\n } catch (err) {\n logger.error(\n { error: err instanceof Error ? err.message : String(err) },\n \"Resume failed\",\n );\n process.exit(1);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction resolveAgentName(\n score: { entry?: string | { agents: string[] }; agents: Record<string, unknown> },\n override?: string,\n): string {\n if (override) return override;\n if (typeof score.entry === \"string\") return score.entry;\n const first = Object.keys(score.agents)[0];\n if (!first) {\n console.error(chalk.red(\"Score has no agents defined.\"));\n process.exit(1);\n }\n return first;\n}\n\nfunction printSummary(checkpoint: Checkpoint): void {\n console.log();\n console.log(chalk.cyan.bold(\"Checkpoint summary\"));\n console.log(\n chalk.dim(\" Session ID: \") + checkpoint.session_id,\n );\n console.log(\n chalk.dim(\" Last turn: \") + String(checkpoint.turn),\n );\n console.log(\n chalk.dim(\" Saved at: \") +\n checkpoint.saved_at.toISOString(),\n );\n console.log(\n chalk.dim(\" Messages: \") +\n String(checkpoint.messages.length) +\n \" total\",\n );\n console.log();\n console.log(chalk.cyan(\"First messages\"));\n const preview = checkpoint.messages.slice(0, 3);\n for (const msg of preview) {\n const text = excerpt(messageToText(msg), 200);\n console.log(chalk.dim(\" [\" + msg.role + \"] \") + text);\n }\n if (checkpoint.messages.length > preview.length) {\n console.log(\n chalk.dim(\n \" … \" +\n String(checkpoint.messages.length - preview.length) +\n \" more\",\n ),\n );\n }\n console.log();\n}\n\nfunction messageToText(msg: ChatMessage): string {\n if (typeof msg.content === \"string\") return msg.content;\n const parts: string[] = [];\n for (const block of msg.content) {\n if (block.type === \"text\") {\n parts.push(block.text);\n } else if (block.type === \"tool_use\") {\n parts.push(\"[tool_use \" + block.name + \"]\");\n } else if (block.type === \"tool_result\") {\n parts.push(\"[tool_result \" + excerpt(block.content, 80) + \"]\");\n }\n }\n return parts.join(\" \");\n}\n\nfunction excerpt(text: string, max: number): string {\n const oneLine = text.replace(/\\s+/g, \" \").trim();\n return oneLine.length > max ? oneLine.slice(0, max - 1) + \"…\" : oneLine;\n}\n\nasync function confirmResume(turn: number): Promise<boolean> {\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n try {\n const answer = (\n await rl.question(\n chalk.cyan(\"Resume from turn \" + turn + \"? \") + chalk.dim(\"(y/n) \"),\n )\n )\n .trim()\n .toLowerCase();\n return answer === \"y\" || answer === \"yes\";\n } finally {\n rl.close();\n }\n}\n\nfunction wireProgress(runtime: TuttiRuntime): void {\n const spinner = ora({ color: \"cyan\" });\n let streaming = false;\n\n runtime.events.on(\"checkpoint:restored\", (e) => {\n console.log(\n chalk.dim(\"↻ Restored from turn \" + e.turn) +\n chalk.dim(\" (session \" + e.session_id.slice(0, 8) + \"…)\"),\n );\n });\n runtime.events.on(\"checkpoint:saved\", (e) => {\n console.log(chalk.dim(\"· Checkpoint saved at turn \" + e.turn));\n });\n runtime.events.on(\"llm:request\", () => {\n spinner.start(\"Thinking...\");\n });\n runtime.events.on(\"token:stream\", (e) => {\n if (!streaming) {\n spinner.stop();\n streaming = true;\n }\n process.stdout.write(e.text);\n });\n runtime.events.on(\"llm:response\", () => {\n if (streaming) {\n process.stdout.write(\"\\n\");\n } else {\n spinner.stop();\n }\n });\n runtime.events.on(\"tool:start\", (e) => {\n if (streaming) {\n process.stdout.write(chalk.dim(\"\\n [using: \" + e.tool_name + \"]\"));\n } else {\n spinner.stop();\n console.log(chalk.dim(\" [using: \" + e.tool_name + \"]\"));\n }\n });\n runtime.events.on(\"tool:end\", (e) => {\n if (streaming) {\n process.stdout.write(chalk.dim(\" [done: \" + e.tool_name + \"]\\n\"));\n }\n });\n runtime.events.on(\"tool:error\", (e) => {\n spinner.stop();\n logger.error({ tool: e.tool_name }, \"Tool error\");\n });\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\";\nimport { createLogger } from \"@tuttiai/core\";\n\nconst logger = createLogger(\"tutti-cli\");\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 postgres: {\n package: \"pg\",\n setup: ` Add ${chalk.bold(\"DATABASE_URL\")} to your .env file:\n ${chalk.cyan(\"DATABASE_URL=postgres://user:pass@localhost:5432/tutti\")}\n\n Add to your score:\n ${chalk.cyan(\"memory: { provider: 'postgres' }\")}\n\n Or with an explicit URL:\n ${chalk.cyan(\"memory: { provider: 'postgres', url: process.env.DATABASE_URL }\")}\n\n Use the async factory for initialization:\n ${chalk.cyan(\"const tutti = await TuttiRuntime.create(score)\")}`,\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\")) as { dependencies?: Record<string, string>; devDependencies?: Record<string, string> };\n const deps: Record<string, string> = { ...pkg.dependencies, ...pkg.devDependencies };\n return packageName in deps;\n } catch {\n return false;\n }\n}\n\nexport function addCommand(voiceName: string): 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 logger.error(\"No package.json found in the current directory\");\n console.error(chalk.dim('Run \"tutti-ai init\" to create a new project first.'));\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 = error instanceof Error ? error.message : String(error);\n logger.error({ error: message, package: packageName }, \"Installation failed\");\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 createLogger,\n} from \"@tuttiai/core\";\n\nconst logger = createLogger(\"tutti-cli\");\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 logger.error(\n { error: err instanceof Error ? err.message : String(err) },\n \"Score validation failed\",\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","import { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { execFile } from \"node:child_process\";\nimport express from \"express\";\nimport chalk from \"chalk\";\nimport {\n TuttiRuntime,\n ScoreLoader,\n createLogger,\n} from \"@tuttiai/core\";\nimport type { Response as ExpressResponse } from \"express\";\n\nconst logger = createLogger(\"tutti-studio\");\nconst envPort = Number.parseInt(process.env.PORT ?? \"\", 10);\nconst PORT = Number.isInteger(envPort) && envPort > 0 && envPort <= 65535 ? envPort : 4747;\n\nfunction safeStringify(obj: unknown): string {\n return JSON.stringify(obj, (_key, value: unknown) => {\n if (value instanceof Error) return { message: value.message, name: value.name };\n if (typeof value === \"function\") return undefined;\n return value;\n });\n}\n\nfunction openBrowser(url: string): void {\n if (process.platform === \"win32\") {\n execFile(\"cmd.exe\", [\"/c\", \"start\", \"\", url]);\n return;\n }\n const cmd = process.platform === \"darwin\" ? \"open\" : \"xdg-open\";\n execFile(cmd, [url]);\n}\n\nexport async function studioCommand(scorePath?: string): Promise<void> {\n const file = resolve(scorePath ?? \"./tutti.score.ts\");\n\n if (!existsSync(file)) {\n logger.error({ file }, \"Score file not found\");\n console.error(chalk.dim('Run \"tutti-ai init\" to create a new project.'));\n process.exit(1);\n }\n\n let score;\n try {\n score = await ScoreLoader.load(file);\n } catch (err) {\n logger.error({ error: err instanceof Error ? err.message : String(err) }, \"Failed to load score\");\n process.exit(1);\n }\n\n const runtime = new TuttiRuntime(score);\n\n // Track sessions via events\n const sessionRegistry = new Map<string, { agent_name: string; created_at: Date }>();\n runtime.events.on(\"agent:start\", (e) => {\n if (!sessionRegistry.has(e.session_id)) {\n sessionRegistry.set(e.session_id, { agent_name: e.agent_name, created_at: new Date() });\n }\n });\n\n // SSE clients\n const sseClients = new Set<ExpressResponse>();\n runtime.events.onAny((event) => {\n const data = safeStringify(event);\n for (const client of sseClients) {\n client.write(\"event: tutti\\ndata: \" + data + \"\\n\\n\");\n }\n });\n\n // Express\n const app = express();\n app.use(express.json());\n\n // SSE endpoint\n app.get(\"/events\", (_req, res) => {\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n });\n res.write(\":\\n\\n\");\n sseClients.add(res);\n _req.on(\"close\", () => sseClients.delete(res));\n });\n\n // REST API\n app.get(\"/api/score\", (_req, res) => {\n const agents = Object.fromEntries(\n Object.entries(runtime.score.agents).map(([id, agent]) => [\n id,\n {\n name: agent.name,\n description: agent.description,\n model: agent.model,\n role: agent.role,\n delegates: agent.delegates,\n voice_count: agent.voices.length,\n voices: agent.voices.map((v) => v.name),\n },\n ]),\n );\n res.json({\n name: runtime.score.name,\n description: runtime.score.description,\n default_model: runtime.score.default_model,\n entry: runtime.score.entry,\n agents,\n });\n });\n\n app.get(\"/api/sessions\", (_req, res) => {\n const sessions = Array.from(sessionRegistry.entries()).map(([id, meta]) => {\n const session = runtime.getSession(id);\n return {\n id,\n agent_name: meta.agent_name,\n message_count: session?.messages.length ?? 0,\n created_at: meta.created_at,\n };\n });\n res.json(sessions.reverse());\n });\n\n app.get(\"/api/sessions/:id\", (req, res) => {\n const session = runtime.getSession(req.params.id);\n if (!session) {\n res.status(404).json({ error: \"Session not found\" });\n return;\n }\n res.json(session);\n });\n\n app.post(\"/api/run\", async (req, res) => {\n const body: unknown = req.body;\n if (typeof body !== \"object\" || body === null) {\n res.status(400).json({ error: \"Invalid request body\" });\n return;\n }\n const agent = (body as Record<string, unknown>).agent;\n const input = (body as Record<string, unknown>).input;\n const session_id = (body as Record<string, unknown>).session_id;\n if (typeof agent !== \"string\" || agent.trim().length === 0) {\n res.status(400).json({ error: \"agent must be a non-empty string\" });\n return;\n }\n if (typeof input !== \"string\" || input.trim().length === 0) {\n res.status(400).json({ error: \"input must be a non-empty string\" });\n return;\n }\n if (session_id !== undefined && (typeof session_id !== \"string\" || session_id.trim().length === 0)) {\n res.status(400).json({ error: \"session_id must be a non-empty string when provided\" });\n return;\n }\n try {\n const result = await runtime.run(agent, input, session_id);\n res.json(result);\n } catch (err) {\n res.status(500).json({ error: err instanceof Error ? err.message : String(err) });\n }\n });\n\n // Serve UI\n app.get(\"/\", (_req, res) => {\n res.type(\"html\").send(getStudioHtml());\n });\n\n app.listen(PORT, () => {\n const url = \"http://localhost:\" + PORT;\n console.log();\n console.log(chalk.bold(\" Tutti Studio\"));\n console.log(chalk.dim(\" \" + url));\n console.log();\n console.log(chalk.dim(\" Score: \") + (runtime.score.name ?? file));\n console.log(chalk.dim(\" Agents: \") + Object.keys(runtime.score.agents).join(\", \"));\n console.log();\n openBrowser(url);\n });\n\n process.on(\"SIGINT\", () => {\n console.log(chalk.dim(\"\\nShutting down Tutti Studio...\"));\n process.exit(0);\n });\n}\n\n// ---------------------------------------------------------------------------\n// Inline HTML UI\n// ---------------------------------------------------------------------------\n\nfunction getStudioHtml(): string {\n return '<!DOCTYPE html>\\\n<html lang=\"en\">\\\n<head>\\\n<meta charset=\"utf-8\">\\\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\\\n<title>Tutti Studio</title>\\\n<style>\\\n*{margin:0;padding:0;box-sizing:border-box}\\\n:root{\\\n--bg:#0a0a0f;--panel:#12121a;--card:#1a1a26;--input:#0f0f17;\\\n--border:#2a2a3a;--text:#e2e8f0;--muted:#64748b;\\\n--purple:#8b5cf6;--teal:#14b8a6;--blue:#3b82f6;--green:#10b981;\\\n--red:#ef4444;--orange:#f97316;--amber:#f59e0b;--indigo:#6366f1;\\\n}\\\nhtml,body{height:100%;font-family:system-ui,-apple-system,sans-serif;background:var(--bg);color:var(--text);font-size:13px}\\\n#app{display:flex;flex-direction:column;height:100vh}\\\n\\\nheader{display:flex;align-items:center;justify-content:space-between;padding:10px 20px;border-bottom:1px solid var(--border);background:var(--panel)}\\\nheader .logo{font-weight:700;font-size:15px;letter-spacing:.5px}\\\nheader .logo span{color:var(--purple)}\\\nheader .meta{color:var(--muted);font-size:12px}\\\nheader .status{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--muted)}\\\nheader .dot{width:7px;height:7px;border-radius:50%;background:var(--green)}\\\nheader .dot.off{background:var(--red)}\\\n\\\nmain{display:grid;grid-template-columns:260px 1fr 280px;flex:1;overflow:hidden;border-bottom:1px solid var(--border)}\\\n\\\n.panel{display:flex;flex-direction:column;border-right:1px solid var(--border);overflow:hidden}\\\n.panel:last-child{border-right:none}\\\n.panel-title{padding:10px 14px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.8px;color:var(--muted);border-bottom:1px solid var(--border);background:var(--panel);flex-shrink:0}\\\n.panel-body{flex:1;overflow-y:auto;padding:10px}\\\n.panel-body::-webkit-scrollbar{width:5px}\\\n.panel-body::-webkit-scrollbar-track{background:transparent}\\\n.panel-body::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}\\\n\\\n#graph-panel .panel-body{padding:0;display:flex;align-items:center;justify-content:center}\\\n#graph-panel svg text{font-family:system-ui,-apple-system,sans-serif}\\\n\\\n#events-panel{display:flex;flex-direction:column}\\\n#event-stream{flex:1;overflow-y:auto;padding:10px}\\\n#event-stream::-webkit-scrollbar{width:5px}\\\n#event-stream::-webkit-scrollbar-track{background:transparent}\\\n#event-stream::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}\\\n\\\n.ev{padding:7px 10px;margin-bottom:6px;border-radius:6px;background:var(--card);border-left:3px solid var(--muted);font-size:12px;line-height:1.5}\\\n.ev .ev-head{display:flex;justify-content:space-between;align-items:center}\\\n.ev .ev-type{font-weight:600;font-family:\"SF Mono\",Menlo,monospace;font-size:11px}\\\n.ev .ev-time{color:var(--muted);font-size:10px;font-family:\"SF Mono\",Menlo,monospace}\\\n.ev .ev-detail{color:var(--muted);margin-top:3px;font-size:11px;word-break:break-all}\\\n.ev.agent{border-left-color:var(--purple)}.ev.agent .ev-type{color:var(--purple)}\\\n.ev.turn{border-left-color:var(--blue)}.ev.turn .ev-type{color:var(--blue)}\\\n.ev.llm{border-left-color:var(--green)}.ev.llm .ev-type{color:var(--green)}\\\n.ev.tool{border-left-color:var(--teal)}.ev.tool .ev-type{color:var(--teal)}\\\n.ev.tool-error{border-left-color:var(--red)}.ev.tool-error .ev-type{color:var(--red)}\\\n.ev.security{border-left-color:var(--orange)}.ev.security .ev-type{color:var(--orange)}\\\n.ev.budget-warn{border-left-color:var(--amber)}.ev.budget-warn .ev-type{color:var(--amber)}\\\n.ev.budget-exceed{border-left-color:var(--red)}.ev.budget-exceed .ev-type{color:var(--red)}\\\n.ev.delegate{border-left-color:var(--indigo)}.ev.delegate .ev-type{color:var(--indigo)}\\\n\\\n#input-bar{display:flex;gap:8px;padding:10px 12px;border-top:1px solid var(--border);background:var(--panel);flex-shrink:0}\\\n#agent-select{background:var(--input);color:var(--text);border:1px solid var(--border);border-radius:6px;padding:6px 10px;font-size:12px;outline:none;cursor:pointer;min-width:110px}\\\n#user-input{flex:1;background:var(--input);color:var(--text);border:1px solid var(--border);border-radius:6px;padding:6px 12px;font-size:13px;outline:none}\\\n#user-input:focus{border-color:var(--purple)}\\\n#send-btn{background:var(--purple);color:#fff;border:none;border-radius:6px;padding:6px 16px;font-size:12px;font-weight:600;cursor:pointer;white-space:nowrap}\\\n#send-btn:hover{opacity:.9}\\\n#send-btn:disabled{opacity:.4;cursor:default}\\\n\\\n.session-item{padding:8px 10px;margin-bottom:4px;border-radius:6px;background:var(--card);cursor:pointer;transition:background .15s}\\\n.session-item:hover{background:#22223a}\\\n.session-item.active{background:#22223a;border:1px solid var(--purple)}\\\n.session-id{font-family:\"SF Mono\",Menlo,monospace;font-size:11px;color:var(--purple)}\\\n.session-meta{font-size:11px;color:var(--muted);margin-top:2px}\\\n\\\n#session-detail{margin-top:10px;border-top:1px solid var(--border);padding-top:10px}\\\n.msg{padding:6px 8px;margin-bottom:4px;border-radius:5px;font-size:12px;line-height:1.5;word-break:break-word}\\\n.msg.user{background:#1c1c3a;border-left:2px solid var(--blue)}\\\n.msg.assistant{background:#1a2a1a;border-left:2px solid var(--green)}\\\n.msg .msg-role{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;margin-bottom:2px}\\\n.msg.user .msg-role{color:var(--blue)}\\\n.msg.assistant .msg-role{color:var(--green)}\\\n\\\nfooter{display:flex;align-items:center;gap:32px;padding:8px 20px;background:var(--panel);font-size:12px}\\\n.token-item{display:flex;align-items:center;gap:6px}\\\n.token-label{color:var(--muted)}\\\n.token-val{font-family:\"SF Mono\",Menlo,monospace;font-weight:600}\\\n.token-val.input{color:var(--blue)}\\\n.token-val.output{color:var(--green)}\\\n.token-val.cost{color:var(--amber)}\\\n\\\n.empty{color:var(--muted);text-align:center;padding:30px 10px;font-size:12px}\\\n</style>\\\n</head>\\\n<body>\\\n<div id=\"app\">\\\n\\\n<header>\\\n <div class=\"logo\"><span>&#9835;</span> Tutti Studio</div>\\\n <div class=\"meta\" id=\"score-name\"></div>\\\n <div class=\"status\"><div class=\"dot\" id=\"sse-dot\"></div><span id=\"sse-label\">connecting</span></div>\\\n</header>\\\n\\\n<main>\\\n <div class=\"panel\" id=\"graph-panel\">\\\n <div class=\"panel-title\">Agent Graph</div>\\\n <div class=\"panel-body\" id=\"graph-body\"></div>\\\n </div>\\\n\\\n <div class=\"panel\" id=\"events-panel\">\\\n <div class=\"panel-title\">Live Event Stream</div>\\\n <div id=\"event-stream\"><div class=\"empty\">Waiting for events&hellip;<br>Send a message below to start an agent run.</div></div>\\\n <div id=\"input-bar\">\\\n <select id=\"agent-select\"></select>\\\n <input id=\"user-input\" placeholder=\"Type a message&hellip;\" autocomplete=\"off\">\\\n <button id=\"send-btn\">Send</button>\\\n </div>\\\n </div>\\\n\\\n <div class=\"panel\" id=\"sessions-panel\">\\\n <div class=\"panel-title\">Sessions</div>\\\n <div class=\"panel-body\" id=\"sessions-body\"><div class=\"empty\">No sessions yet</div></div>\\\n </div>\\\n</main>\\\n\\\n<footer>\\\n <div class=\"token-item\"><span class=\"token-label\">&#x2193; Input</span><span class=\"token-val input\" id=\"tok-in\">0</span></div>\\\n <div class=\"token-item\"><span class=\"token-label\">&#x2191; Output</span><span class=\"token-val output\" id=\"tok-out\">0</span></div>\\\n <div class=\"token-item\"><span class=\"token-label\">$ Est. cost</span><span class=\"token-val cost\" id=\"tok-cost\">0.0000</span></div>\\\n</footer>\\\n\\\n</div>\\\n\\\n<script>\\\n(function(){\\\n\\\nvar tokIn=0,tokOut=0;\\\nvar sessionMap={};\\\nvar activeSession=null;\\\n\\\n/* ---- helpers ---- */\\\nfunction esc(s){var d=document.createElement(\"div\");d.textContent=s;return d.innerHTML}\\\nfunction fmt(n){return n.toLocaleString()}\\\nfunction timeStr(){var d=new Date();return (\"0\"+d.getHours()).slice(-2)+\":\"+(\"0\"+d.getMinutes()).slice(-2)+\":\"+(\"0\"+d.getSeconds()).slice(-2)}\\\nfunction truncId(id){return id.slice(0,8)}\\\n\\\n/* ---- score + graph ---- */\\\nfunction loadScore(){\\\n fetch(\"/api/score\").then(function(r){return r.json()}).then(function(s){\\\n document.getElementById(\"score-name\").textContent=s.name||\"tutti.score.ts\";\\\n var sel=document.getElementById(\"agent-select\");\\\n sel.innerHTML=\"\";\\\n Object.keys(s.agents).forEach(function(id){\\\n var o=document.createElement(\"option\");o.value=id;o.textContent=s.agents[id].name;sel.appendChild(o);\\\n });\\\n renderGraph(s);\\\n });\\\n}\\\n\\\nfunction renderGraph(score){\\\n var body=document.getElementById(\"graph-body\");\\\n var W=260,ids=Object.keys(score.agents),N=ids.length;\\\n if(N===0){body.innerHTML=\"<div class=\\\\\"empty\\\\\">No agents</div>\";return}\\\n var hasDelegate=false;\\\n ids.forEach(function(id){if(score.agents[id].delegates&&score.agents[id].delegates.length)hasDelegate=true});\\\n var nodeR=26,padY=90,padTop=50;\\\n var leftIds=[],rightIds=[];\\\n if(hasDelegate){\\\n ids.forEach(function(id){var a=score.agents[id];if(a.delegates&&a.delegates.length)leftIds.push(id);else rightIds.push(id)});\\\n }else{leftIds=ids}\\\n var cols=hasDelegate?2:1;\\\n var cx1=cols===1?W/2:72,cx2=W-72;\\\n var H=Math.max(leftIds.length,rightIds.length)*padY+padTop*2;\\\n if(H<200)H=200;\\\n var pos={};\\\n var svg=\\'<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"\\'+W+\\'\" height=\"\\'+H+\\'\" viewBox=\"0 0 \\'+W+\" \"+H+\\'\">\\';\\\n svg+=\\'<defs><marker id=\"ah\" viewBox=\"0 0 10 10\" refX=\"10\" refY=\"5\" markerWidth=\"5\" markerHeight=\"5\" orient=\"auto\"><path d=\"M0 0L10 5L0 10z\" fill=\"#64748b\"/></marker></defs>\\';\\\n function drawNode(id,cx,cy){\\\n var a=score.agents[id];\\\n var col=a.role===\"orchestrator\"?\"#8b5cf6\":\"#14b8a6\";\\\n pos[id]={x:cx,y:cy};\\\n svg+=\\'<circle cx=\"\\'+cx+\\'\" cy=\"\\'+cy+\\'\" r=\"\\'+nodeR+\\'\" fill=\"\\'+col+\\'\" fill-opacity=\"0.15\" stroke=\"\\'+col+\\'\" stroke-width=\"2\"/>\\';\\\n svg+=\\'<text x=\"\\'+cx+\\'\" y=\"\\'+(cy+4)+\\'\" text-anchor=\"middle\" fill=\"#e2e8f0\" font-size=\"10\" font-weight=\"600\">\\'+esc(a.name)+\\'</text>\\';\\\n var model=a.model||score.default_model||\"\";\\\n if(model){var sh=model.replace(/-\\\\d{8}$/,\"\");if(sh.length>18)sh=sh.slice(0,18)+\"\\\\u2026\";svg+=\\'<text x=\"\\'+cx+\\'\" y=\"\\'+(cy+nodeR+14)+\\'\" text-anchor=\"middle\" fill=\"#64748b\" font-size=\"9\">\\'+esc(sh)+\\'</text>\\'}\\\n svg+=\\'<text x=\"\\'+cx+\\'\" y=\"\\'+(cy+nodeR+26)+\\'\" text-anchor=\"middle\" fill=\"#64748b\" font-size=\"9\">\\'+a.voice_count+\" voice\"+(a.voice_count!==1?\"s\":\"\")+\\'</text>\\';\\\n }\\\n leftIds.forEach(function(id,i){drawNode(id,cx1,padTop+i*padY)});\\\n rightIds.forEach(function(id,i){drawNode(id,cx2,padTop+i*padY)});\\\n ids.forEach(function(id){\\\n var a=score.agents[id];\\\n if(a.delegates)a.delegates.forEach(function(did){\\\n if(pos[id]&&pos[did]){\\\n var x1=pos[id].x+nodeR,y1=pos[id].y,x2=pos[did].x-nodeR,y2=pos[did].y;\\\n var mx=(x1+x2)/2;\\\n svg+=\\'<path d=\"M\\'+x1+\" \"+y1+\" C\"+mx+\" \"+y1+\" \"+mx+\" \"+y2+\" \"+x2+\" \"+y2+\\'\" fill=\"none\" stroke=\"#64748b\" stroke-width=\"1.5\" stroke-dasharray=\"4 3\" marker-end=\"url(#ah)\"/>\\';\\\n }\\\n });\\\n });\\\n svg+=\"</svg>\";\\\n body.innerHTML=svg;\\\n}\\\n\\\n/* ---- SSE ---- */\\\nfunction connectSSE(){\\\n var es=new EventSource(\"/events\");\\\n es.addEventListener(\"tutti\",function(e){\\\n var ev=JSON.parse(e.data);\\\n addEvent(ev);\\\n if(ev.type===\"llm:response\"&&ev.response&&ev.response.usage){\\\n tokIn+=ev.response.usage.input_tokens||0;\\\n tokOut+=ev.response.usage.output_tokens||0;\\\n document.getElementById(\"tok-in\").textContent=fmt(tokIn);\\\n document.getElementById(\"tok-out\").textContent=fmt(tokOut);\\\n document.getElementById(\"tok-cost\").textContent=estimateCost(tokIn,tokOut);\\\n }\\\n if(ev.type===\"agent:start\"||ev.type===\"agent:end\")refreshSessions();\\\n });\\\n es.onopen=function(){document.getElementById(\"sse-dot\").className=\"dot\";document.getElementById(\"sse-label\").textContent=\"connected\"};\\\n es.onerror=function(){document.getElementById(\"sse-dot\").className=\"dot off\";document.getElementById(\"sse-label\").textContent=\"disconnected\"};\\\n}\\\n\\\n/* Pricing: USD per 1M tokens (Sonnet-class default) */\\\nvar INPUT_PRICE_PER_MILLION=3;\\\nvar OUTPUT_PRICE_PER_MILLION=15;\\\nfunction estimateCost(inp,out){\\\n var c=(inp/1e6)*INPUT_PRICE_PER_MILLION+(out/1e6)*OUTPUT_PRICE_PER_MILLION;\\\n return c.toFixed(4);\\\n}\\\n\\\nfunction evClass(t){\\\n if(t.indexOf(\"agent\")===0)return \"agent\";\\\n if(t.indexOf(\"turn\")===0)return \"turn\";\\\n if(t===\"llm:request\"||t===\"llm:response\")return \"llm\";\\\n if(t===\"tool:error\")return \"tool-error\";\\\n if(t.indexOf(\"tool\")===0)return \"tool\";\\\n if(t.indexOf(\"security\")===0)return \"security\";\\\n if(t===\"budget:warning\")return \"budget-warn\";\\\n if(t===\"budget:exceeded\")return \"budget-exceed\";\\\n if(t.indexOf(\"delegate\")===0)return \"delegate\";\\\n return \"\";\\\n}\\\n\\\nfunction evDetail(ev){\\\n var parts=[];\\\n if(ev.agent_name)parts.push(\"agent: \"+ev.agent_name);\\\n if(ev.session_id)parts.push(\"session: \"+truncId(ev.session_id));\\\n if(ev.turn!==undefined)parts.push(\"turn: \"+ev.turn);\\\n if(ev.tool_name)parts.push(\"tool: \"+ev.tool_name);\\\n if(ev.from)parts.push(\"from: \"+ev.from);\\\n if(ev.to)parts.push(\"to: \"+ev.to);\\\n if(ev.tokens!==undefined)parts.push(\"tokens: \"+fmt(ev.tokens));\\\n if(ev.cost_usd!==undefined)parts.push(\"cost: $\"+ev.cost_usd.toFixed(4));\\\n if(ev.response&&ev.response.usage)parts.push(\"tokens: \"+fmt(ev.response.usage.input_tokens)+\" in / \"+fmt(ev.response.usage.output_tokens)+\" out\");\\\n if(ev.error){var em=typeof ev.error===\"object\"?ev.error.message||\"\":ev.error;if(em)parts.push(\"error: \"+em)}\\\n if(ev.patterns)parts.push(\"patterns: \"+ev.patterns.join(\", \"));\\\n return parts.join(\" &middot; \");\\\n}\\\n\\\nvar firstEvent=true;\\\nfunction addEvent(ev){\\\n var stream=document.getElementById(\"event-stream\");\\\n if(firstEvent){stream.innerHTML=\"\";firstEvent=false}\\\n var div=document.createElement(\"div\");\\\n div.className=\"ev \"+evClass(ev.type);\\\n div.innerHTML=\\'<div class=\"ev-head\"><span class=\"ev-type\">\\'+esc(ev.type)+\\'</span><span class=\"ev-time\">\\'+timeStr()+\\'</span></div>\\';\\\n var det=evDetail(ev);\\\n if(det)div.innerHTML+=\\'<div class=\"ev-detail\">\\'+det+\"</div>\";\\\n stream.appendChild(div);\\\n stream.scrollTop=stream.scrollHeight;\\\n}\\\n\\\n/* ---- sessions ---- */\\\nfunction refreshSessions(){\\\n fetch(\"/api/sessions\").then(function(r){return r.json()}).then(function(list){\\\n var body=document.getElementById(\"sessions-body\");\\\n if(!list.length){body.innerHTML=\\'<div class=\"empty\">No sessions yet</div>\\';return}\\\n var html=\"\";\\\n list.forEach(function(s){\\\n var cls=\"session-item\"+(activeSession===s.id?\" active\":\"\");\\\n html+=\\'<div class=\"\\'+cls+\\'\" data-id=\"\\'+s.id+\\'\">\\';\\\n html+=\\'<div class=\"session-id\">\\'+truncId(s.id)+\"</div>\";\\\n html+=\\'<div class=\"session-meta\">\\'+esc(s.agent_name)+\" &middot; \"+s.message_count+\" msgs</div>\";\\\n html+=\"</div>\";\\\n });\\\n if(activeSession)html+=\\'<div id=\"session-detail\"></div>\\';\\\n body.innerHTML=html;\\\n body.querySelectorAll(\".session-item\").forEach(function(el){\\\n el.addEventListener(\"click\",function(){selectSession(el.getAttribute(\"data-id\"))});\\\n });\\\n if(activeSession)loadSessionDetail(activeSession);\\\n });\\\n}\\\n\\\nfunction selectSession(id){\\\n activeSession=activeSession===id?null:id;\\\n refreshSessions();\\\n}\\\n\\\nfunction loadSessionDetail(id){\\\n var det=document.getElementById(\"session-detail\");\\\n if(!det)return;\\\n fetch(\"/api/sessions/\"+id).then(function(r){return r.json()}).then(function(session){\\\n if(!session||session.error){det.innerHTML=\\'<div class=\"empty\">Session not found</div>\\';return}\\\n var html=\"\";\\\n (session.messages||[]).forEach(function(m){\\\n var role=m.role;\\\n var text=\"\";\\\n if(typeof m.content===\"string\")text=m.content;\\\n else if(Array.isArray(m.content)){\\\n m.content.forEach(function(b){\\\n if(b.type===\"text\")text+=b.text+\"\\\\n\";\\\n else if(b.type===\"tool_use\")text+=\"[tool_use: \"+b.name+\"]\\\\n\";\\\n else if(b.type===\"tool_result\")text+=\"[tool_result]\\\\n\";\\\n });\\\n }\\\n html+=\\'<div class=\"msg \\'+role+\\'\"><div class=\"msg-role\">\\'+role+\"</div>\"+esc(text.trim())+\"</div>\";\\\n });\\\n det.innerHTML=html;\\\n });\\\n}\\\n\\\n/* ---- send ---- */\\\nfunction sendMessage(){\\\n var agentSel=document.getElementById(\"agent-select\");\\\n var inputEl=document.getElementById(\"user-input\");\\\n var btn=document.getElementById(\"send-btn\");\\\n var agent=agentSel.value;\\\n var input=inputEl.value.trim();\\\n if(!input)return;\\\n btn.disabled=true;btn.textContent=\"Running\\\\u2026\";\\\n inputEl.value=\"\";\\\n var sid=sessionMap[agent]||undefined;\\\n fetch(\"/api/run\",{method:\"POST\",headers:{\"Content-Type\":\"application/json\"},body:JSON.stringify({agent:agent,input:input,session_id:sid})})\\\n .then(function(r){return r.json()})\\\n .then(function(result){\\\n if(result.session_id)sessionMap[agent]=result.session_id;\\\n if(result.output){\\\n addEvent({type:\"__output\",agent_name:agent,output:result.output});\\\n }\\\n refreshSessions();\\\n })\\\n .catch(function(err){addEvent({type:\"__error\",error:err.message||String(err)})})\\\n .finally(function(){btn.disabled=false;btn.textContent=\"Send\"});\\\n}\\\n\\\ndocument.getElementById(\"send-btn\").addEventListener(\"click\",sendMessage);\\\ndocument.getElementById(\"user-input\").addEventListener(\"keydown\",function(e){if(e.key===\"Enter\"&&!e.shiftKey){e.preventDefault();sendMessage()}});\\\n\\\n/* ---- init ---- */\\\nloadScore();\\\nconnectSSE();\\\n\\\n})();\\\n</script>\\\n</body>\\\n</html>';\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { createLogger } from \"@tuttiai/core\";\n\nconst logger = createLogger(\"tutti-cli\");\n\nconst REGISTRY_URL =\n \"https://raw.githubusercontent.com/tuttiai/voices/main/voices.json\";\n\ninterface VoiceEntry {\n name: string;\n package: string;\n description: string;\n tags: string[];\n official: boolean;\n tools: number;\n}\n\n// Built-in fallback when the remote registry is unreachable\nconst BUILTIN_VOICES: VoiceEntry[] = [\n {\n name: \"filesystem\",\n package: \"@tuttiai/filesystem\",\n description: \"Read, write, search, and manage files and directories\",\n tags: [\"filesystem\", \"files\", \"io\", \"read\", \"write\"],\n official: true,\n tools: 7,\n },\n {\n name: \"github\",\n package: \"@tuttiai/github\",\n description: \"Interact with GitHub repos, issues, PRs, and code search\",\n tags: [\"github\", \"git\", \"code\", \"issues\", \"pull-requests\", \"api\"],\n official: true,\n tools: 10,\n },\n {\n name: \"playwright\",\n package: \"@tuttiai/playwright\",\n description: \"Control a browser like a human — navigate, click, type, screenshot\",\n tags: [\"browser\", \"playwright\", \"web\", \"qa\", \"testing\", \"automation\", \"scraping\"],\n official: true,\n tools: 12,\n },\n {\n name: \"postgres\",\n package: \"pg\",\n description: \"PostgreSQL session persistence and database access\",\n tags: [\"database\", \"postgres\", \"sql\", \"persistence\", \"sessions\"],\n official: true,\n tools: 0,\n },\n];\n\ninterface RegistryEntry {\n name: string;\n package: string;\n description: string;\n tags: string[];\n}\n\nasync function fetchRegistry(): Promise<VoiceEntry[]> {\n try {\n const res = await fetch(REGISTRY_URL);\n if (!res.ok) throw new Error(\"HTTP \" + res.status);\n const data = (await res.json()) as { official?: RegistryEntry[]; community?: RegistryEntry[] };\n\n const voices: VoiceEntry[] = [];\n for (const entry of data.official ?? []) {\n voices.push({ ...entry, official: true, tools: toolCount(entry.name) });\n }\n for (const entry of data.community ?? []) {\n voices.push({ ...entry, official: false, tools: 0 });\n }\n if (voices.length === 0) throw new Error(\"Empty registry\");\n return voices;\n } catch {\n logger.debug(\"Registry unreachable, using built-in voice list\");\n return BUILTIN_VOICES;\n }\n}\n\nfunction toolCount(name: string): number {\n const counts: Record<string, number> = { filesystem: 7, github: 10, playwright: 12 };\n return counts[name] ?? 0;\n}\n\nfunction matchesQuery(voice: VoiceEntry, query: string): boolean {\n const q = query.toLowerCase();\n if (voice.name.toLowerCase().includes(q)) return true;\n if (voice.description.toLowerCase().includes(q)) return true;\n if (voice.tags.some((t) => t.toLowerCase().includes(q))) return true;\n return false;\n}\n\nfunction isInstalled(packageName: string): boolean {\n const pkgPath = resolve(process.cwd(), \"package.json\");\n if (!existsSync(pkgPath)) return false;\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\")) as { dependencies?: Record<string, string>; devDependencies?: Record<string, string> };\n const deps: Record<string, string> = { ...pkg.dependencies, ...pkg.devDependencies };\n return packageName in deps;\n } catch {\n return false;\n }\n}\n\nfunction printVoice(voice: VoiceEntry, showInstallStatus: boolean): void {\n const badge = voice.official\n ? chalk.green(\" [official]\")\n : chalk.blue(\" [community]\");\n const installed = showInstallStatus && isInstalled(voice.package);\n const status = showInstallStatus\n ? installed\n ? chalk.green(\" ✔ installed\")\n : chalk.dim(\" not installed\")\n : \"\";\n\n console.log();\n console.log(\" \" + chalk.bold(voice.package) + badge + status);\n console.log(\" \" + voice.description);\n\n const installCmd = voice.official && voice.name !== \"postgres\"\n ? \"tutti-ai add \" + voice.name\n : \"npm install \" + voice.package;\n console.log(\" \" + chalk.dim(\"Install: \") + chalk.cyan(installCmd));\n\n if (voice.tags.length > 0) {\n console.log(\" \" + chalk.dim(\"Tags: \") + voice.tags.join(\", \"));\n }\n}\n\nexport async function searchCommand(query: string): Promise<void> {\n const spinner = ora(\"Searching the Repertoire...\").start();\n\n const voices = await fetchRegistry();\n const results = voices.filter((v) => matchesQuery(v, query));\n\n spinner.stop();\n\n if (results.length === 0) {\n console.log();\n console.log(chalk.yellow(' No voices found for \"' + query + '\"'));\n console.log();\n console.log(chalk.dim(\" Browse all: https://tutti-ai.com/voices\"));\n console.log(chalk.dim(\" Build your own: tutti-ai create voice <name>\"));\n console.log();\n return;\n }\n\n console.log();\n console.log(\n \" Found \" +\n chalk.bold(String(results.length)) +\n \" voice\" +\n (results.length !== 1 ? \"s\" : \"\") +\n \" matching \" +\n chalk.cyan(\"'\" + query + \"'\") +\n \":\",\n );\n\n for (const voice of results) {\n printVoice(voice, false);\n }\n console.log();\n}\n\nexport async function voicesCommand(): Promise<void> {\n const spinner = ora(\"Loading voices...\").start();\n\n const voices = await fetchRegistry();\n const official = voices.filter((v) => v.official);\n\n spinner.stop();\n\n console.log();\n console.log(\" \" + chalk.bold(\"Official Tutti Voices\"));\n console.log();\n\n for (const voice of official) {\n printVoice(voice, true);\n }\n\n const community = voices.filter((v) => !v.official);\n if (community.length > 0) {\n console.log();\n console.log(\" \" + chalk.bold(\"Community Voices\"));\n for (const voice of community) {\n printVoice(voice, true);\n }\n }\n\n console.log();\n console.log(chalk.dim(\" Search: tutti-ai search <query>\"));\n console.log(chalk.dim(\" Browse: https://tutti-ai.com/voices\"));\n console.log();\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\";\nimport Enquirer from \"enquirer\";\nimport { createLogger, SecretsManager } from \"@tuttiai/core\";\n\nconst { prompt } = Enquirer;\nconst logger = createLogger(\"tutti-cli\");\n\ninterface PkgJson {\n name?: string;\n version?: string;\n description?: string;\n license?: string;\n exports?: unknown;\n}\n\nfunction readPkg(dir: string): PkgJson | undefined {\n const p = resolve(dir, \"package.json\");\n if (!existsSync(p)) return undefined;\n return JSON.parse(readFileSync(p, \"utf-8\")) as PkgJson;\n}\n\nfunction run(cmd: string, cwd: string): string {\n return execSync(cmd, { cwd, stdio: \"pipe\", encoding: \"utf-8\" });\n}\n\nfunction fail(msg: string): never {\n console.error(chalk.red(\" \" + msg));\n process.exit(1);\n}\n\nconst ok = (msg: string) => console.log(chalk.green(\" ✔ \" + msg));\n\nexport async function publishCommand(opts: { dryRun?: boolean }): Promise<void> {\n const cwd = process.cwd();\n const pkg = readPkg(cwd);\n\n console.log();\n console.log(chalk.bold(\" Tutti Voice Publisher\"));\n console.log();\n\n // ── Step 1: Pre-flight checks ──\n\n const spinner = ora(\"Running pre-flight checks...\").start();\n\n // 1a. Must be a voice directory\n if (!pkg) fail(\"No package.json found in the current directory.\");\n if (!existsSync(resolve(cwd, \"src/index.ts\"))) fail(\"No src/index.ts found — are you inside a voice directory?\");\n\n // 1b. Required fields\n const missing: string[] = [];\n if (!pkg.name) missing.push(\"name\");\n if (!pkg.version) missing.push(\"version\");\n if (!pkg.description) missing.push(\"description\");\n if (!pkg.license) missing.push(\"license\");\n if (!pkg.exports) missing.push(\"exports\");\n if (missing.length > 0) fail(\"package.json is missing: \" + missing.join(\", \"));\n\n const name = pkg.name!;\n const version = pkg.version!;\n\n // 1c. Name convention\n const validName = name.startsWith(\"@tuttiai/\") || name.startsWith(\"tutti\");\n if (!validName) fail(\"Package name must start with @tuttiai/ or tutti — got: \" + name);\n\n // 1d. Check required_permissions is declared in source\n const src = readFileSync(resolve(cwd, \"src/index.ts\"), \"utf-8\");\n if (!src.includes(\"required_permissions\")) {\n fail(\"Voice class must declare required_permissions in src/index.ts\");\n }\n\n spinner.succeed(\"Pre-flight checks passed\");\n\n // 1e. Build\n const buildSpinner = ora(\"Building...\").start();\n try {\n run(\"npm run build\", cwd);\n buildSpinner.succeed(\"Build succeeded\");\n } catch (err) {\n buildSpinner.fail(\"Build failed\");\n const msg = err instanceof Error ? err.message : String(err);\n console.error(chalk.dim(\" \" + msg.split(\"\\n\").slice(0, 5).join(\"\\n \")));\n process.exit(1);\n }\n\n // 1f. Tests\n const testSpinner = ora(\"Running tests...\").start();\n try {\n run(\"npx vitest run\", cwd);\n testSpinner.succeed(\"Tests passed\");\n } catch {\n testSpinner.fail(\"Tests failed\");\n process.exit(1);\n }\n\n // 1g. Audit\n const auditSpinner = ora(\"Checking vulnerabilities...\").start();\n try {\n run(\"npm audit --audit-level=high\", cwd);\n auditSpinner.succeed(\"No high/critical vulnerabilities\");\n } catch {\n auditSpinner.stopAndPersist({ symbol: chalk.yellow(\"⚠\"), text: \"Vulnerabilities found (npm audit)\" });\n }\n\n // ── Step 2: Dry run ──\n\n console.log();\n const drySpinner = ora(\"Packing (dry run)...\").start();\n let packOutput: string;\n try {\n packOutput = run(\"npm pack --dry-run 2>&1\", cwd);\n drySpinner.succeed(\"Pack dry-run complete\");\n } catch (err) {\n drySpinner.fail(\"Pack dry-run failed\");\n const msg = err instanceof Error ? err.message : String(err);\n console.error(chalk.dim(\" \" + msg));\n process.exit(1);\n }\n\n // Show files from the pack output\n const fileLines = packOutput\n .split(\"\\n\")\n .filter((l) => l.includes(\"npm notice\") && /\\d+(\\.\\d+)?\\s*[kM]?B\\s/.test(l))\n .map((l) => l.replace(/npm notice\\s*/, \"\"));\n\n if (fileLines.length > 0) {\n console.log(chalk.dim(\" Files:\"));\n for (const line of fileLines) {\n console.log(chalk.dim(\" \" + line.trim()));\n }\n }\n\n // Show totals\n const sizeLine = packOutput.split(\"\\n\").find((l) => l.includes(\"package size\"));\n const totalLine = packOutput.split(\"\\n\").find((l) => l.includes(\"total files\"));\n if (sizeLine) console.log(chalk.dim(\" \" + sizeLine.replace(/npm notice\\s*/, \"\").trim()));\n if (totalLine) console.log(chalk.dim(\" \" + totalLine.replace(/npm notice\\s*/, \"\").trim()));\n\n if (opts.dryRun) {\n console.log();\n ok(\"Dry run complete — no packages were published\");\n console.log(chalk.dim(\" Run without --dry-run to publish for real.\"));\n console.log();\n return;\n }\n\n // Prompt for confirmation\n console.log();\n const { confirm } = await prompt<{ confirm: boolean }>({\n type: \"confirm\",\n name: \"confirm\",\n message: \"Publish \" + chalk.cyan(name + \"@\" + version) + \"?\",\n });\n\n if (!confirm) {\n console.log(chalk.dim(\" Cancelled.\"));\n return;\n }\n\n // ── Step 3: Publish ──\n\n const pubSpinner = ora(\"Publishing to npm...\").start();\n try {\n run(\"npm publish --access public\", cwd);\n pubSpinner.succeed(\"Published \" + chalk.cyan(name + \"@\" + version));\n } catch (err) {\n pubSpinner.fail(\"Publish failed\");\n const msg = err instanceof Error ? err.message : String(err);\n logger.error({ error: msg }, \"npm publish failed\");\n process.exit(1);\n }\n\n // ── Step 4: Open PR to voice registry ──\n\n const ghToken = SecretsManager.optional(\"GITHUB_TOKEN\");\n let prUrl: string | undefined;\n\n if (ghToken) {\n const prSpinner = ora(\"Opening PR to voice registry...\").start();\n try {\n prUrl = await openRegistryPR(name, version, pkg.description ?? \"\", ghToken);\n prSpinner.succeed(\"PR opened: \" + prUrl);\n } catch (err) {\n prSpinner.fail(\"Failed to open PR\");\n const msg = err instanceof Error ? err.message : String(err);\n logger.error({ error: msg }, \"Registry PR failed\");\n }\n } else {\n console.log();\n console.log(chalk.dim(\" To list in the Repertoire, set GITHUB_TOKEN and re-run\"));\n console.log(chalk.dim(\" Or open a PR manually: github.com/tuttiai/voices\"));\n }\n\n // ── Step 5: Summary ──\n\n console.log();\n ok(name + \"@\" + version + \" published to npm\");\n if (prUrl) ok(\"PR opened to tuttiai/voices\");\n const shortName = name.replace(\"@tuttiai/\", \"\").replace(/^tutti-?/, \"\");\n ok(\"Install: tutti-ai add \" + shortName);\n ok(\"View: https://www.npmjs.com/package/\" + name);\n console.log();\n}\n\nasync function openRegistryPR(\n packageName: string,\n version: string,\n description: string,\n token: string,\n): Promise<string> {\n const owner = \"tuttiai\";\n const repo = \"voices\";\n const branch = \"add-\" + packageName.replace(/[@/]/g, \"-\").replace(/^-/, \"\");\n const shortName = packageName.replace(\"@tuttiai/\", \"\").replace(/^tutti-?/, \"\");\n const isOfficial = packageName.startsWith(\"@tuttiai/\");\n\n // 1. Get current voices.json content and SHA\n const fileRes = await fetch(\n \"https://api.github.com/repos/\" + owner + \"/\" + repo + \"/contents/voices.json\",\n { headers: { Authorization: \"Bearer \" + token, Accept: \"application/vnd.github.v3+json\" } },\n );\n if (!fileRes.ok) throw new Error(\"Failed to fetch voices.json: \" + fileRes.status);\n const fileData = (await fileRes.json()) as { content: string; sha: string };\n\n interface RegistryVoice { name: string; package: string; description: string; version: string; author: string; tags: string[]; repo?: string }\n interface Registry { official: RegistryVoice[]; community: RegistryVoice[] }\n\n const registry = JSON.parse(Buffer.from(fileData.content, \"base64\").toString(\"utf-8\")) as Registry;\n\n // 2. Add the new voice entry\n const section: keyof Registry = isOfficial ? \"official\" : \"community\";\n const entry: RegistryVoice = {\n name: shortName,\n package: packageName,\n description,\n repo: \"https://github.com/tuttiai/tutti/tree/main/voices/\" + shortName,\n version,\n author: isOfficial ? \"tuttiai\" : packageName.split(\"/\")[0]?.replace(\"@\", \"\") ?? \"community\",\n tags: [shortName],\n };\n\n if (!registry[section]) registry[section] = [];\n const exists = registry[section].some((v) => v.package === packageName);\n if (exists) {\n const idx = registry[section].findIndex((v) => v.package === packageName);\n registry[section][idx] = { ...registry[section][idx], ...entry };\n } else {\n registry[section].push(entry);\n }\n\n const updatedContent = Buffer.from(JSON.stringify(registry, null, 2) + \"\\n\").toString(\"base64\");\n\n // 3. Get default branch SHA\n const mainRes = await fetch(\n \"https://api.github.com/repos/\" + owner + \"/\" + repo + \"/git/ref/heads/main\",\n { headers: { Authorization: \"Bearer \" + token, Accept: \"application/vnd.github.v3+json\" } },\n );\n if (!mainRes.ok) throw new Error(\"Failed to get main ref: \" + mainRes.status);\n const mainData = (await mainRes.json()) as { object: { sha: string } };\n\n // 4. Create branch\n await fetch(\"https://api.github.com/repos/\" + owner + \"/\" + repo + \"/git/refs\", {\n method: \"POST\",\n headers: { Authorization: \"Bearer \" + token, \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ ref: \"refs/heads/\" + branch, sha: mainData.object.sha }),\n });\n\n // 5. Update voices.json on the new branch\n await fetch(\n \"https://api.github.com/repos/\" + owner + \"/\" + repo + \"/contents/voices.json\",\n {\n method: \"PUT\",\n headers: { Authorization: \"Bearer \" + token, \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n message: \"feat: add \" + packageName + \" to the Repertoire\",\n content: updatedContent,\n sha: fileData.sha,\n branch,\n }),\n },\n );\n\n // 6. Create PR\n const prRes = await fetch(\"https://api.github.com/repos/\" + owner + \"/\" + repo + \"/pulls\", {\n method: \"POST\",\n headers: { Authorization: \"Bearer \" + token, \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n title: \"feat: add \" + packageName + \" to the Repertoire\",\n head: branch,\n base: \"main\",\n body: \"## New voice: \" + packageName + \"@\" + version + \"\\n\\n\" + description + \"\\n\\nPublished via `tutti-ai publish`.\",\n }),\n });\n\n if (!prRes.ok) {\n const err = await prRes.text();\n throw new Error(\"Failed to create PR: \" + prRes.status + \" \" + err);\n }\n\n const prData = (await prRes.json()) as { html_url: string };\n return prData.html_url;\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport {\n ScoreLoader,\n EvalRunner,\n printEvalTable,\n createLogger,\n} from \"@tuttiai/core\";\nimport type { EvalSuite } from \"@tuttiai/core\";\n\nconst logger = createLogger(\"tutti-cli\");\n\nexport async function evalCommand(suitePath: string, opts: { ci?: boolean; score?: string }): Promise<void> {\n const suiteFile = resolve(suitePath);\n if (!existsSync(suiteFile)) {\n logger.error({ file: suiteFile }, \"Suite file not found\");\n process.exit(1);\n }\n\n // Load the eval suite JSON\n let suite: EvalSuite;\n try {\n suite = JSON.parse(readFileSync(suiteFile, \"utf-8\")) as EvalSuite;\n } catch (err) {\n logger.error({ error: err instanceof Error ? err.message : String(err) }, \"Failed to parse suite file\");\n process.exit(1);\n }\n\n // Load score\n const scoreFile = resolve(opts.score ?? \"./tutti.score.ts\");\n if (!existsSync(scoreFile)) {\n logger.error({ file: scoreFile }, \"Score file not found\");\n process.exit(1);\n }\n\n const spinner = ora(\"Loading score...\").start();\n let score;\n try {\n score = await ScoreLoader.load(scoreFile);\n } catch (err) {\n spinner.fail(\"Failed to load score\");\n logger.error({ error: err instanceof Error ? err.message : String(err) }, \"Score load failed\");\n process.exit(1);\n }\n spinner.succeed(\"Score loaded\");\n\n // Run eval\n const evalSpinner = ora(\"Running \" + suite.cases.length + \" eval cases...\").start();\n const runner = new EvalRunner(score);\n const report = await runner.run(suite);\n evalSpinner.stop();\n\n // Print results\n printEvalTable(report);\n\n // CI mode: exit 1 if any failed\n if (opts.ci && report.summary.failed > 0) {\n console.error(chalk.red(\" CI mode: \" + report.summary.failed + \" case(s) failed\"));\n process.exit(1);\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport chalk from \"chalk\";\nimport {\n TuttiRuntime,\n ScoreLoader,\n AnthropicProvider,\n OpenAIProvider,\n GeminiProvider,\n SecretsManager,\n InMemorySessionStore,\n createLogger,\n} from \"@tuttiai/core\";\nimport type { ScoreConfig, SessionStore } from \"@tuttiai/types\";\nimport { createServer, DEFAULT_PORT, SERVER_VERSION } from \"@tuttiai/server\";\nimport type { FastifyInstance } from \"fastify\";\nimport { ReactiveScore } from \"../watch/score-watcher.js\";\n\nconst logger = createLogger(\"tutti-serve\");\n\nexport interface ServeOptions {\n port?: string;\n host?: string;\n apiKey?: string;\n agent?: string;\n watch?: boolean;\n}\n\nexport async function serveCommand(\n scorePath?: string,\n options: ServeOptions = {},\n): Promise<void> {\n // ── Resolve score file ──────────────────────────────────────\n const file = resolve(scorePath ?? \"./tutti.score.ts\");\n\n if (!existsSync(file)) {\n logger.error({ file }, \"Score file not found\");\n console.error(chalk.dim('Run \"tutti-ai init\" to create a new project.'));\n process.exit(1);\n }\n\n let score: ScoreConfig;\n try {\n score = await ScoreLoader.load(file);\n } catch (err) {\n logger.error(\n { error: err instanceof Error ? err.message : String(err) },\n \"Failed to load score\",\n );\n process.exit(1);\n }\n\n // ── Validate provider 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 logger.error({ envVar }, \"Missing API key\");\n process.exit(1);\n }\n }\n }\n\n // ── Resolve agent name ──────────────────────────────────────\n const agentNames = Object.keys(score.agents);\n const agentName =\n options.agent ??\n (typeof score.entry === \"string\" ? score.entry : undefined) ??\n agentNames[0];\n\n if (!agentName || !score.agents[agentName]) {\n logger.error(\n { requested: agentName, available: agentNames },\n \"Agent not found in score\",\n );\n process.exit(1);\n }\n\n // ── Resolve port & host ─────────────────────────────────────\n const port = parsePort(options.port);\n const host = options.host ?? \"0.0.0.0\";\n\n // ── Build runtime and server ────────────────────────────────\n // Watch mode keeps a shared session store so hot-reloads don't\n // discard in-flight sessions.\n const sharedSessions: SessionStore | undefined = options.watch\n ? new InMemorySessionStore()\n : undefined;\n\n let runtime = buildRuntime(score, sharedSessions);\n let app = await buildApp(runtime, agentName, port, host, options.apiKey);\n\n // ── Watch mode ──────────────────────────────────────────────\n let reactive: ReactiveScore | undefined;\n if (options.watch) {\n reactive = new ReactiveScore(score, file);\n\n reactive.on(\"file-change\", () => {\n console.log(chalk.cyan(\"\\n[tutti] Score changed, reloading...\"));\n });\n\n reactive.on(\"reloaded\", () => {\n void (async () => {\n try {\n const nextScore = reactive!.current;\n const nextRuntime = buildRuntime(nextScore, sharedSessions);\n const nextApp = await buildApp(nextRuntime, agentName, port, host, options.apiKey);\n\n await app.close();\n runtime = nextRuntime;\n app = nextApp;\n await app.listen({ port, host });\n\n console.log(chalk.green(\"[tutti] Score reloaded. Server restarted.\"));\n } catch (err) {\n logger.error(\n { error: err instanceof Error ? err.message : String(err) },\n \"[tutti] Reload failed — server continues with previous config\",\n );\n }\n })();\n });\n\n reactive.on(\"reload-failed\", (err) => {\n logger.error(\n { error: err instanceof Error ? err.message : String(err) },\n \"[tutti] Reload failed — server continues with previous config\",\n );\n });\n }\n\n // ── Start listening ─────────────────────────────────────────\n await app.listen({ port, host });\n\n printBanner(port, host, agentName, score, file, options.watch);\n\n // ── Graceful shutdown ───────────────────────────────────────\n const shutdown = async (signal: string) => {\n console.log(chalk.dim(\"\\n\" + signal + \" received — shutting down...\"));\n if (reactive) await reactive.close();\n await app.close();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", () => void shutdown(\"SIGINT\"));\n process.on(\"SIGTERM\", () => void shutdown(\"SIGTERM\"));\n}\n\n// ── Helpers ──────────────────────────────────────────────────\n\nfunction parsePort(raw: string | undefined): number {\n if (raw === undefined) return DEFAULT_PORT;\n const n = Number.parseInt(raw, 10);\n if (!Number.isInteger(n) || n < 1 || n > 65535) {\n logger.error({ port: raw }, \"Invalid port number\");\n process.exit(1);\n }\n return n;\n}\n\nfunction buildRuntime(\n score: ScoreConfig,\n sessionStore: SessionStore | undefined,\n): TuttiRuntime {\n return new TuttiRuntime(\n score,\n sessionStore ? { sessionStore } : {},\n );\n}\n\nasync function buildApp(\n runtime: TuttiRuntime,\n agentName: string,\n port: number,\n host: string,\n apiKey: string | undefined,\n): Promise<FastifyInstance> {\n return createServer({\n port,\n host,\n runtime,\n agent_name: agentName,\n api_key: apiKey,\n });\n}\n\nfunction printBanner(\n port: number,\n host: string,\n agentName: string,\n score: ScoreConfig,\n file: string,\n watch: boolean | undefined,\n): void {\n const display = host === \"0.0.0.0\" || host === \"::\" ? \"localhost\" : host;\n const url = \"http://\" + display + \":\" + port;\n\n console.log();\n console.log(chalk.bold(\" Tutti Server v\" + SERVER_VERSION));\n console.log(chalk.dim(\" \" + url));\n console.log();\n console.log(chalk.dim(\" Score: \") + (score.name ?? file));\n console.log(chalk.dim(\" Agent: \") + agentName);\n console.log(chalk.dim(\" Agents: \") + Object.keys(score.agents).join(\", \"));\n if (watch) {\n console.log(chalk.dim(\" Watch: \") + chalk.cyan(\"enabled\"));\n }\n console.log();\n console.log(chalk.dim(\" Endpoints:\"));\n console.log(chalk.dim(\" POST \") + url + \"/run\");\n console.log(chalk.dim(\" POST \") + url + \"/run/stream\");\n console.log(chalk.dim(\" GET \") + url + \"/sessions/:id\");\n console.log(chalk.dim(\" GET \") + url + \"/health\");\n console.log();\n}\n","/**\n * `tutti-ai schedule [score]` — start the scheduler daemon.\n *\n * Reads the score file, registers all agents that have a `schedule`\n * config, then runs until killed. Uses PostgreSQL via `TUTTI_PG_URL`\n * for schedule persistence, falling back to in-memory for local dev.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport chalk from \"chalk\";\nimport {\n ScoreLoader,\n SchedulerEngine,\n PostgresScheduleStore,\n MemoryScheduleStore,\n AgentRunner,\n EventBus,\n InMemorySessionStore,\n SecretsManager,\n createLogger,\n} from \"@tuttiai/core\";\nimport type { ScheduleStore } from \"@tuttiai/core\";\n\nconst logger = createLogger(\"tutti-cli\");\n\nfunction resolveStore(): ScheduleStore {\n const pgUrl = SecretsManager.optional(\"TUTTI_PG_URL\");\n if (pgUrl) {\n return new PostgresScheduleStore({ connection_string: pgUrl });\n }\n logger.warn(\"TUTTI_PG_URL not set — using in-memory store (not durable across restarts)\");\n return new MemoryScheduleStore();\n}\n\nexport async function scheduleCommand(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(chalk.dim('Run \"tutti-ai init\" to create a new project.'));\n process.exit(1);\n }\n\n const score = await ScoreLoader.load(file);\n const events = new EventBus();\n const sessions = new InMemorySessionStore();\n const runner = new AgentRunner(\n score.provider,\n events,\n sessions,\n );\n\n const store = resolveStore();\n const engine = new SchedulerEngine(store, runner, events);\n\n // Register agents with schedule config\n let registered = 0;\n for (const [agentId, agent] of Object.entries(score.agents)) {\n if (!agent.schedule) continue;\n const resolvedAgent = agent.model\n ? agent\n : { ...agent, model: score.default_model ?? \"claude-sonnet-4-20250514\" };\n await engine.schedule(agentId, resolvedAgent, agent.schedule);\n registered++;\n }\n\n if (registered === 0) {\n console.log(chalk.yellow(\"No agents have a schedule config. Nothing to run.\"));\n console.log(chalk.dim(\"Add schedule: { cron: '...', input: '...' } to an agent in your score.\"));\n process.exit(0);\n }\n\n // Event logging\n events.onAny((e) => {\n if (e.type === \"schedule:triggered\") {\n const ev = e as { schedule_id: string; agent_name: string };\n console.log(\n chalk.dim(new Date().toISOString()) + \" \" +\n chalk.cyan(\"triggered\") + \" \" +\n chalk.bold(ev.schedule_id) + \" → \" + ev.agent_name,\n );\n }\n if (e.type === \"schedule:completed\") {\n const ev = e as { schedule_id: string; agent_name: string; duration_ms: number };\n console.log(\n chalk.dim(new Date().toISOString()) + \" \" +\n chalk.green(\"completed\") + \" \" +\n chalk.bold(ev.schedule_id) + \" \" +\n chalk.dim(\"(\" + ev.duration_ms + \"ms)\"),\n );\n }\n if (e.type === \"schedule:error\") {\n const ev = e as { schedule_id: string; agent_name: string; error: Error };\n console.log(\n chalk.dim(new Date().toISOString()) + \" \" +\n chalk.red(\"error\") + \" \" +\n chalk.bold(ev.schedule_id) + \" — \" + ev.error.message,\n );\n }\n });\n\n engine.start();\n\n // Banner\n console.log(\"\");\n console.log(chalk.cyan.bold(\" Tutti Scheduler\"));\n console.log(chalk.dim(\" Score: \" + (score.name ?? file)));\n console.log(chalk.dim(\" Schedules: \" + registered));\n console.log(chalk.dim(\" Store: \" + (SecretsManager.optional(\"TUTTI_PG_URL\") ? \"postgres\" : \"memory\")));\n console.log(\"\");\n console.log(chalk.dim(\" Press Ctrl+C to stop.\"));\n console.log(\"\");\n\n // Graceful shutdown\n const shutdown = () => {\n console.log(chalk.dim(\"\\n Shutting down scheduler...\"));\n engine.stop();\n if (\"close\" in store && typeof (store as { close: () => Promise<void> }).close === \"function\") {\n void (store as { close: () => Promise<void> }).close();\n }\n process.exit(0);\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n // Keep process alive\n await new Promise(() => undefined);\n}\n","/**\n * `tutti-ai schedules <subcommand>` — schedule management commands.\n *\n * All subcommands connect to the schedule store via TUTTI_PG_URL.\n * Falls back to in-memory (ephemeral) when TUTTI_PG_URL is not set.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport chalk from \"chalk\";\nimport {\n ScoreLoader,\n SchedulerEngine,\n PostgresScheduleStore,\n MemoryScheduleStore,\n AgentRunner,\n EventBus,\n InMemorySessionStore,\n SecretsManager,\n createLogger,\n} from \"@tuttiai/core\";\nimport type { ScheduleStore, ScheduleRecord } from \"@tuttiai/core\";\n\nconst logger = createLogger(\"tutti-cli\");\n\nfunction resolveStore(): ScheduleStore {\n const pgUrl = SecretsManager.optional(\"TUTTI_PG_URL\");\n if (pgUrl) {\n return new PostgresScheduleStore({ connection_string: pgUrl });\n }\n logger.warn(\"TUTTI_PG_URL not set — using in-memory store (schedules are ephemeral)\");\n return new MemoryScheduleStore();\n}\n\nasync function closeStore(store: ScheduleStore): Promise<void> {\n if (\"close\" in store && typeof (store as { close: () => Promise<void> }).close === \"function\") {\n await (store as { close: () => Promise<void> }).close();\n }\n}\n\nfunction formatTrigger(r: ScheduleRecord): string {\n if (r.config.cron) return \"cron: \" + r.config.cron;\n if (r.config.every) return \"every \" + r.config.every;\n if (r.config.at) return \"at \" + r.config.at;\n return \"?\";\n}\n\nfunction pad(s: string, len: number): string {\n return s.length >= len ? s : s + \" \".repeat(len - s.length);\n}\n\n// ── list ──────────────────────────────────────────────────────\n\nexport async function schedulesListCommand(): Promise<void> {\n const store = resolveStore();\n try {\n const records = await store.list();\n\n if (records.length === 0) {\n console.log(chalk.dim(\"No schedules found.\"));\n console.log(chalk.dim('Run \"tutti-ai schedule\" to start the scheduler daemon.'));\n return;\n }\n\n console.log(\"\");\n console.log(\n chalk.dim(\n \" \" + pad(\"ID\", 20) + pad(\"AGENT\", 16) +\n pad(\"TRIGGER\", 22) + pad(\"ENABLED\", 10) +\n pad(\"RUNS\", 8) + \"CREATED\",\n ),\n );\n console.log(chalk.dim(\" \" + \"─\".repeat(90)));\n\n for (const r of records) {\n const enabled = r.enabled\n ? chalk.green(\"yes\")\n : chalk.red(\"no\") + \" \";\n const maxLabel = r.config.max_runs\n ? r.run_count + \"/\" + r.config.max_runs\n : String(r.run_count);\n\n console.log(\n \" \" +\n chalk.bold(pad(r.id, 20)) +\n pad(r.agent_id, 16) +\n pad(formatTrigger(r), 22) +\n pad(enabled, 10) +\n pad(maxLabel, 8) +\n chalk.dim(r.created_at.toISOString().slice(0, 10)),\n );\n }\n console.log(\"\");\n } finally {\n await closeStore(store);\n }\n}\n\n// ── enable ────────────────────────────────────────────────────\n\nexport async function schedulesEnableCommand(id: string): Promise<void> {\n const store = resolveStore();\n try {\n const record = await store.get(id);\n if (!record) {\n console.error(chalk.red('Schedule \"' + id + '\" not found.'));\n process.exit(1);\n }\n await store.setEnabled(id, true);\n console.log(chalk.green('Schedule \"' + id + '\" enabled.'));\n } finally {\n await closeStore(store);\n }\n}\n\n// ── disable ───────────────────────────────────────────────────\n\nexport async function schedulesDisableCommand(id: string): Promise<void> {\n const store = resolveStore();\n try {\n const record = await store.get(id);\n if (!record) {\n console.error(chalk.red('Schedule \"' + id + '\" not found.'));\n process.exit(1);\n }\n await store.setEnabled(id, false);\n console.log(chalk.yellow('Schedule \"' + id + '\" disabled.'));\n } finally {\n await closeStore(store);\n }\n}\n\n// ── trigger ───────────────────────────────────────────────────\n\nexport async function schedulesTriggerCommand(\n id: string,\n scorePath?: string,\n): Promise<void> {\n const file = resolve(scorePath ?? \"./tutti.score.ts\");\n if (!existsSync(file)) {\n console.error(chalk.red(\"Score file not found: \" + file));\n process.exit(1);\n }\n\n const score = await ScoreLoader.load(file);\n const events = new EventBus();\n const sessions = new InMemorySessionStore();\n const runner = new AgentRunner(score.provider, events, sessions);\n const store = resolveStore();\n\n try {\n const record = await store.get(id);\n if (!record) {\n console.error(chalk.red('Schedule \"' + id + '\" not found.'));\n process.exit(1);\n }\n\n const agent = score.agents[record.agent_id];\n if (!agent) {\n console.error(chalk.red('Agent \"' + record.agent_id + '\" not found in score.'));\n process.exit(1);\n }\n\n const resolvedAgent = agent.model\n ? agent\n : { ...agent, model: score.default_model ?? \"claude-sonnet-4-20250514\" };\n\n const engine = new SchedulerEngine(store, runner, events);\n await engine.schedule(id, resolvedAgent, record.config);\n engine.start();\n\n console.log(chalk.cyan('Triggering \"' + id + '\" (' + record.agent_id + \")...\"));\n\n const run = await engine.trigger(id);\n\n engine.stop();\n\n if (run.error) {\n console.log(chalk.red(\" Error: \" + run.error));\n process.exit(1);\n }\n\n const duration = run.completed_at && run.triggered_at\n ? run.completed_at.getTime() - run.triggered_at.getTime()\n : 0;\n\n console.log(chalk.green(\" Completed in \" + duration + \"ms\"));\n if (run.result) {\n const preview = run.result.length > 200\n ? run.result.slice(0, 200) + \"...\"\n : run.result;\n console.log(chalk.dim(\" Output: \" + preview));\n }\n } finally {\n await closeStore(store);\n }\n}\n\n// ── runs ──────────────────────────────────────────────────────\n\nexport async function schedulesRunsCommand(id: string): Promise<void> {\n const store = resolveStore();\n try {\n const record = await store.get(id);\n if (!record) {\n console.error(chalk.red('Schedule \"' + id + '\" not found.'));\n process.exit(1);\n }\n\n // MemoryScheduleStore exposes getRuns(); Postgres tracks only run_count.\n if (\"getRuns\" in store && typeof (store as { getRuns: (id: string) => unknown[] }).getRuns === \"function\") {\n const runs = (store as { getRuns: (id: string) => Array<{\n triggered_at: Date;\n completed_at?: Date;\n result?: string;\n error?: string;\n }> }).getRuns(id);\n\n if (runs.length === 0) {\n console.log(chalk.dim(\"No runs recorded for this schedule.\"));\n return;\n }\n\n const recent = runs.slice(-20);\n console.log(\"\");\n console.log(chalk.dim(\" Showing last \" + recent.length + \" of \" + runs.length + \" runs:\"));\n console.log(\"\");\n\n for (const run of recent) {\n const duration = run.completed_at && run.triggered_at\n ? (run.completed_at.getTime() - run.triggered_at.getTime()) + \"ms\"\n : \"?\";\n const status = run.error\n ? chalk.red(\"error\")\n : chalk.green(\"ok\");\n const preview = run.error\n ? run.error.slice(0, 80)\n : (run.result ?? \"\").slice(0, 80);\n console.log(\n \" \" + chalk.dim(run.triggered_at.toISOString()) + \" \" +\n status + \" \" + chalk.dim(duration) + \" \" + preview,\n );\n }\n console.log(\"\");\n } else {\n // Postgres store — only has run_count, not full history\n console.log(chalk.dim('Schedule \"' + id + '\" has completed ' + record.run_count + \" runs.\"));\n console.log(chalk.dim(\"Full run history requires the MemoryScheduleStore or a future tutti_schedule_runs table.\"));\n }\n } finally {\n await closeStore(store);\n }\n}\n"],"mappings":"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","names":["createLogger","existsSync","resolve","chalk","createLogger","logger","createLogger","resolve","existsSync","chalk","existsSync","resolve","createInterface","chalk","ora","AnthropicProvider","GeminiProvider","OpenAIProvider","ScoreLoader","SecretsManager","TuttiRuntime","createLogger","logger","existsSync","resolve","chalk","ora","createLogger","logger","existsSync","resolve","chalk","ScoreLoader","AnthropicProvider","OpenAIProvider","GeminiProvider","SecretsManager","createLogger","logger","existsSync","resolve","chalk","TuttiRuntime","ScoreLoader","createLogger","logger","existsSync","readFileSync","resolve","chalk","ora","createLogger","logger","existsSync","readFileSync","resolve","execSync","chalk","ora","Enquirer","createLogger","SecretsManager","prompt","logger","fail","ok","existsSync","readFileSync","resolve","chalk","ora","ScoreLoader","createLogger","logger","existsSync","resolve","chalk","TuttiRuntime","ScoreLoader","AnthropicProvider","OpenAIProvider","GeminiProvider","SecretsManager","InMemorySessionStore","createLogger","logger","createLogger","resolve","existsSync","chalk","ScoreLoader","AnthropicProvider","OpenAIProvider","GeminiProvider","SecretsManager","InMemorySessionStore","buildRuntime","TuttiRuntime","existsSync","resolve","chalk","ScoreLoader","InMemorySessionStore","SecretsManager","createLogger","logger","existsSync","resolve","chalk","ScoreLoader","SchedulerEngine","PostgresScheduleStore","MemoryScheduleStore","AgentRunner","EventBus","InMemorySessionStore","SecretsManager","createLogger","logger","resolveStore","run","logger","createLogger"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tuttiai/cli",
3
- "version": "0.11.1",
3
+ "version": "0.12.0",
4
4
  "description": "Tutti CLI — scaffold and run multi-agent projects",
5
5
  "type": "module",
6
6
  "bin": {