@tuttiai/cli 0.11.0 → 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 +90 -0
- package/dist/index.js +310 -21
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
5
|
+
import { createLogger as createLogger13 } from "@tuttiai/core";
|
|
6
6
|
import { Command } from "commander";
|
|
7
7
|
|
|
8
8
|
// src/commands/init.ts
|
|
@@ -1782,22 +1782,24 @@ async function serveCommand(scorePath, options = {}) {
|
|
|
1782
1782
|
reactive.on("file-change", () => {
|
|
1783
1783
|
console.log(chalk10.cyan("\n[tutti] Score changed, reloading..."));
|
|
1784
1784
|
});
|
|
1785
|
-
reactive.on("reloaded",
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1785
|
+
reactive.on("reloaded", () => {
|
|
1786
|
+
void (async () => {
|
|
1787
|
+
try {
|
|
1788
|
+
const nextScore = reactive.current;
|
|
1789
|
+
const nextRuntime = buildRuntime2(nextScore, sharedSessions);
|
|
1790
|
+
const nextApp = await buildApp(nextRuntime, agentName, port, host, options.apiKey);
|
|
1791
|
+
await app.close();
|
|
1792
|
+
runtime = nextRuntime;
|
|
1793
|
+
app = nextApp;
|
|
1794
|
+
await app.listen({ port, host });
|
|
1795
|
+
console.log(chalk10.green("[tutti] Score reloaded. Server restarted."));
|
|
1796
|
+
} catch (err) {
|
|
1797
|
+
logger10.error(
|
|
1798
|
+
{ error: err instanceof Error ? err.message : String(err) },
|
|
1799
|
+
"[tutti] Reload failed \u2014 server continues with previous config"
|
|
1800
|
+
);
|
|
1801
|
+
}
|
|
1802
|
+
})();
|
|
1801
1803
|
});
|
|
1802
1804
|
reactive.on("reload-failed", (err) => {
|
|
1803
1805
|
logger10.error(
|
|
@@ -1863,19 +1865,287 @@ function printBanner(port, host, agentName, score, file, watch) {
|
|
|
1863
1865
|
console.log();
|
|
1864
1866
|
}
|
|
1865
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
|
+
|
|
1866
2136
|
// src/index.ts
|
|
1867
2137
|
config();
|
|
1868
|
-
var
|
|
2138
|
+
var logger13 = createLogger13("tutti-cli");
|
|
1869
2139
|
process.on("unhandledRejection", (reason) => {
|
|
1870
|
-
|
|
2140
|
+
logger13.error({ error: reason instanceof Error ? reason.message : String(reason) }, "Unhandled rejection");
|
|
1871
2141
|
process.exit(1);
|
|
1872
2142
|
});
|
|
1873
2143
|
process.on("uncaughtException", (err) => {
|
|
1874
|
-
|
|
2144
|
+
logger13.error({ error: err.message }, "Fatal error");
|
|
1875
2145
|
process.exit(1);
|
|
1876
2146
|
});
|
|
1877
2147
|
var program = new Command();
|
|
1878
|
-
program.name("tutti-ai").description("Tutti \u2014 multi-agent orchestration. All agents. All together.").version("0.
|
|
2148
|
+
program.name("tutti-ai").description("Tutti \u2014 multi-agent orchestration. All agents. All together.").version("0.12.0");
|
|
1879
2149
|
program.command("init [project-name]").description("Create a new Tutti project").option("-t, --template <id>", "Project template to use").action(async (projectName, opts) => {
|
|
1880
2150
|
await initCommand(projectName, opts.template);
|
|
1881
2151
|
});
|
|
@@ -1931,5 +2201,24 @@ program.command("publish").description("Publish the current voice to npm and the
|
|
|
1931
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) => {
|
|
1932
2202
|
await evalCommand(suitePath, opts);
|
|
1933
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
|
+
});
|
|
1934
2223
|
program.parse();
|
|
1935
2224
|
//# sourceMappingURL=index.js.map
|