@otto-code/cli 0.5.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/bin/otto +3 -0
- package/dist/classify.d.ts +19 -0
- package/dist/classify.js +49 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +113 -0
- package/dist/commands/agent/archive.d.ts +18 -0
- package/dist/commands/agent/archive.js +102 -0
- package/dist/commands/agent/attach.d.ts +11 -0
- package/dist/commands/agent/attach.js +159 -0
- package/dist/commands/agent/delete.d.ts +15 -0
- package/dist/commands/agent/delete.js +107 -0
- package/dist/commands/agent/import.d.ts +14 -0
- package/dist/commands/agent/import.js +122 -0
- package/dist/commands/agent/index.d.ts +3 -0
- package/dist/commands/agent/index.js +48 -0
- package/dist/commands/agent/inspect.d.ts +15 -0
- package/dist/commands/agent/inspect.js +209 -0
- package/dist/commands/agent/logs.d.ts +19 -0
- package/dist/commands/agent/logs.js +180 -0
- package/dist/commands/agent/ls.d.ts +44 -0
- package/dist/commands/agent/ls.js +204 -0
- package/dist/commands/agent/mode.d.ts +18 -0
- package/dist/commands/agent/mode.js +100 -0
- package/dist/commands/agent/reload.d.ts +15 -0
- package/dist/commands/agent/reload.js +75 -0
- package/dist/commands/agent/run.d.ts +44 -0
- package/dist/commands/agent/run.js +464 -0
- package/dist/commands/agent/send.d.ts +19 -0
- package/dist/commands/agent/send.js +187 -0
- package/dist/commands/agent/stop.d.ts +17 -0
- package/dist/commands/agent/stop.js +115 -0
- package/dist/commands/agent/update.d.ts +18 -0
- package/dist/commands/agent/update.js +139 -0
- package/dist/commands/agent/wait.d.ts +17 -0
- package/dist/commands/agent/wait.js +158 -0
- package/dist/commands/chat/create.d.ts +9 -0
- package/dist/commands/chat/create.js +23 -0
- package/dist/commands/chat/delete.d.ts +6 -0
- package/dist/commands/chat/delete.js +20 -0
- package/dist/commands/chat/index.d.ts +3 -0
- package/dist/commands/chat/index.js +47 -0
- package/dist/commands/chat/inspect.d.ts +6 -0
- package/dist/commands/chat/inspect.js +20 -0
- package/dist/commands/chat/ls.d.ts +6 -0
- package/dist/commands/chat/ls.js +20 -0
- package/dist/commands/chat/post.d.ts +9 -0
- package/dist/commands/chat/post.js +28 -0
- package/dist/commands/chat/read.d.ts +11 -0
- package/dist/commands/chat/read.js +40 -0
- package/dist/commands/chat/schema.d.ts +36 -0
- package/dist/commands/chat/schema.js +81 -0
- package/dist/commands/chat/shared.d.ts +19 -0
- package/dist/commands/chat/shared.js +118 -0
- package/dist/commands/chat/wait.d.ts +9 -0
- package/dist/commands/chat/wait.js +45 -0
- package/dist/commands/daemon/index.d.ts +3 -0
- package/dist/commands/daemon/index.js +57 -0
- package/dist/commands/daemon/local-daemon.d.ts +78 -0
- package/dist/commands/daemon/local-daemon.js +544 -0
- package/dist/commands/daemon/pair.d.ts +9 -0
- package/dist/commands/daemon/pair.js +76 -0
- package/dist/commands/daemon/restart.d.ts +12 -0
- package/dist/commands/daemon/restart.js +99 -0
- package/dist/commands/daemon/runtime-toolchain.d.ts +6 -0
- package/dist/commands/daemon/runtime-toolchain.js +87 -0
- package/dist/commands/daemon/set-password.d.ts +17 -0
- package/dist/commands/daemon/set-password.js +82 -0
- package/dist/commands/daemon/start.d.ts +6 -0
- package/dist/commands/daemon/start.js +56 -0
- package/dist/commands/daemon/status.d.ts +10 -0
- package/dist/commands/daemon/status.js +338 -0
- package/dist/commands/daemon/stop.d.ts +15 -0
- package/dist/commands/daemon/stop.js +60 -0
- package/dist/commands/hooks.d.ts +19 -0
- package/dist/commands/hooks.js +89 -0
- package/dist/commands/loop/index.d.ts +3 -0
- package/dist/commands/loop/index.js +18 -0
- package/dist/commands/loop/inspect.d.ts +13 -0
- package/dist/commands/loop/inspect.js +100 -0
- package/dist/commands/loop/logs.d.ts +8 -0
- package/dist/commands/loop/logs.js +69 -0
- package/dist/commands/loop/ls.d.ts +18 -0
- package/dist/commands/loop/ls.js +62 -0
- package/dist/commands/loop/run.d.ts +30 -0
- package/dist/commands/loop/run.js +162 -0
- package/dist/commands/loop/stop.d.ts +15 -0
- package/dist/commands/loop/stop.js +56 -0
- package/dist/commands/loop/types.d.ts +138 -0
- package/dist/commands/loop/types.js +2 -0
- package/dist/commands/onboard.d.ts +10 -0
- package/dist/commands/onboard.js +416 -0
- package/dist/commands/open.d.ts +2 -0
- package/dist/commands/open.js +81 -0
- package/dist/commands/permit/allow.d.ts +20 -0
- package/dist/commands/permit/allow.js +133 -0
- package/dist/commands/permit/deny.d.ts +12 -0
- package/dist/commands/permit/deny.js +105 -0
- package/dist/commands/permit/index.d.ts +3 -0
- package/dist/commands/permit/index.js +27 -0
- package/dist/commands/permit/ls.d.ts +18 -0
- package/dist/commands/permit/ls.js +66 -0
- package/dist/commands/provider/index.d.ts +3 -0
- package/dist/commands/provider/index.js +16 -0
- package/dist/commands/provider/ls.d.ts +19 -0
- package/dist/commands/provider/ls.js +73 -0
- package/dist/commands/provider/models.d.ts +20 -0
- package/dist/commands/provider/models.js +53 -0
- package/dist/commands/schedule/create.d.ts +18 -0
- package/dist/commands/schedule/create.js +40 -0
- package/dist/commands/schedule/delete.d.ts +10 -0
- package/dist/commands/schedule/delete.js +32 -0
- package/dist/commands/schedule/index.d.ts +3 -0
- package/dist/commands/schedule/index.js +66 -0
- package/dist/commands/schedule/inspect.d.ts +6 -0
- package/dist/commands/schedule/inspect.js +24 -0
- package/dist/commands/schedule/logs.d.ts +6 -0
- package/dist/commands/schedule/logs.js +23 -0
- package/dist/commands/schedule/ls.d.ts +5 -0
- package/dist/commands/schedule/ls.js +23 -0
- package/dist/commands/schedule/pause.d.ts +5 -0
- package/dist/commands/schedule/pause.js +23 -0
- package/dist/commands/schedule/resume.d.ts +5 -0
- package/dist/commands/schedule/resume.js +23 -0
- package/dist/commands/schedule/run-once.d.ts +5 -0
- package/dist/commands/schedule/run-once.js +23 -0
- package/dist/commands/schedule/schema.d.ts +21 -0
- package/dist/commands/schedule/schema.js +67 -0
- package/dist/commands/schedule/shared.d.ts +56 -0
- package/dist/commands/schedule/shared.js +346 -0
- package/dist/commands/schedule/types.d.ts +168 -0
- package/dist/commands/schedule/types.js +2 -0
- package/dist/commands/schedule/update.d.ts +21 -0
- package/dist/commands/schedule/update.js +39 -0
- package/dist/commands/speech/index.d.ts +3 -0
- package/dist/commands/speech/index.js +5 -0
- package/dist/commands/terminal/capture.d.ts +10 -0
- package/dist/commands/terminal/capture.js +68 -0
- package/dist/commands/terminal/create.d.ts +10 -0
- package/dist/commands/terminal/create.js +38 -0
- package/dist/commands/terminal/index.d.ts +3 -0
- package/dist/commands/terminal/index.js +43 -0
- package/dist/commands/terminal/kill.d.ts +6 -0
- package/dist/commands/terminal/kill.js +36 -0
- package/dist/commands/terminal/ls.d.ts +10 -0
- package/dist/commands/terminal/ls.js +21 -0
- package/dist/commands/terminal/schema.d.ts +18 -0
- package/dist/commands/terminal/schema.js +23 -0
- package/dist/commands/terminal/send-keys.d.ts +7 -0
- package/dist/commands/terminal/send-keys.js +76 -0
- package/dist/commands/terminal/shared.d.ts +12 -0
- package/dist/commands/terminal/shared.js +61 -0
- package/dist/commands/worktree/archive.d.ts +20 -0
- package/dist/commands/worktree/archive.js +104 -0
- package/dist/commands/worktree/create-input.d.ts +15 -0
- package/dist/commands/worktree/create-input.js +56 -0
- package/dist/commands/worktree/create.d.ts +11 -0
- package/dist/commands/worktree/create.js +58 -0
- package/dist/commands/worktree/index.d.ts +3 -0
- package/dist/commands/worktree/index.js +25 -0
- package/dist/commands/worktree/ls.d.ts +19 -0
- package/dist/commands/worktree/ls.js +97 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +6 -0
- package/dist/output/index.d.ts +45 -0
- package/dist/output/index.js +47 -0
- package/dist/output/json.d.ts +11 -0
- package/dist/output/json.js +37 -0
- package/dist/output/quiet.d.ts +9 -0
- package/dist/output/quiet.js +22 -0
- package/dist/output/render.d.ts +15 -0
- package/dist/output/render.js +83 -0
- package/dist/output/table.d.ts +13 -0
- package/dist/output/table.js +135 -0
- package/dist/output/types.d.ts +73 -0
- package/dist/output/types.js +8 -0
- package/dist/output/with-output.d.ts +41 -0
- package/dist/output/with-output.js +87 -0
- package/dist/output/yaml.d.ts +11 -0
- package/dist/output/yaml.js +38 -0
- package/dist/run.d.ts +14 -0
- package/dist/run.js +33 -0
- package/dist/utils/client-id.d.ts +2 -0
- package/dist/utils/client-id.js +37 -0
- package/dist/utils/client.d.ts +44 -0
- package/dist/utils/client.js +330 -0
- package/dist/utils/command-options.d.ts +6 -0
- package/dist/utils/command-options.js +17 -0
- package/dist/utils/duration.d.ts +7 -0
- package/dist/utils/duration.js +38 -0
- package/dist/utils/errors.d.ts +5 -0
- package/dist/utils/errors.js +10 -0
- package/dist/utils/paths.d.ts +12 -0
- package/dist/utils/paths.js +22 -0
- package/dist/utils/provider-model.d.ts +11 -0
- package/dist/utils/provider-model.js +49 -0
- package/dist/utils/timeline.d.ts +11 -0
- package/dist/utils/timeline.js +11 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +10 -0
- package/package.json +48 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { ListResult } from "../../output/index.js";
|
|
3
|
+
import { type ScheduleCommandOptions, type ScheduleRow } from "./shared.js";
|
|
4
|
+
export declare function runLsCommand(options: ScheduleCommandOptions, _command: Command): Promise<ListResult<ScheduleRow>>;
|
|
5
|
+
//# sourceMappingURL=ls.d.ts.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { scheduleSchema } from "./schema.js";
|
|
2
|
+
import { connectScheduleClient, toScheduleCommandError, toScheduleRow, } from "./shared.js";
|
|
3
|
+
export async function runLsCommand(options, _command) {
|
|
4
|
+
const { client } = await connectScheduleClient(options.host);
|
|
5
|
+
try {
|
|
6
|
+
const payload = await client.scheduleList();
|
|
7
|
+
if (payload.error) {
|
|
8
|
+
throw new Error(payload.error);
|
|
9
|
+
}
|
|
10
|
+
return {
|
|
11
|
+
type: "list",
|
|
12
|
+
data: payload.schedules.map(toScheduleRow),
|
|
13
|
+
schema: scheduleSchema,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
throw toScheduleCommandError("SCHEDULE_LIST_FAILED", "list schedules", error);
|
|
18
|
+
}
|
|
19
|
+
finally {
|
|
20
|
+
await client.close().catch(() => { });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=ls.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { SingleResult } from "../../output/index.js";
|
|
3
|
+
import { type ScheduleCommandOptions, type ScheduleRow } from "./shared.js";
|
|
4
|
+
export declare function runPauseCommand(id: string, options: ScheduleCommandOptions, _command: Command): Promise<SingleResult<ScheduleRow>>;
|
|
5
|
+
//# sourceMappingURL=pause.d.ts.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { scheduleSchema } from "./schema.js";
|
|
2
|
+
import { connectScheduleClient, toScheduleCommandError, toScheduleRow, } from "./shared.js";
|
|
3
|
+
export async function runPauseCommand(id, options, _command) {
|
|
4
|
+
const { client } = await connectScheduleClient(options.host);
|
|
5
|
+
try {
|
|
6
|
+
const payload = await client.schedulePause({ id });
|
|
7
|
+
if (payload.error || !payload.schedule) {
|
|
8
|
+
throw new Error(payload.error ?? `Failed to pause schedule: ${id}`);
|
|
9
|
+
}
|
|
10
|
+
return {
|
|
11
|
+
type: "single",
|
|
12
|
+
data: toScheduleRow(payload.schedule),
|
|
13
|
+
schema: scheduleSchema,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
throw toScheduleCommandError("SCHEDULE_PAUSE_FAILED", "pause schedule", error);
|
|
18
|
+
}
|
|
19
|
+
finally {
|
|
20
|
+
await client.close().catch(() => { });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=pause.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { SingleResult } from "../../output/index.js";
|
|
3
|
+
import { type ScheduleCommandOptions, type ScheduleRow } from "./shared.js";
|
|
4
|
+
export declare function runResumeCommand(id: string, options: ScheduleCommandOptions, _command: Command): Promise<SingleResult<ScheduleRow>>;
|
|
5
|
+
//# sourceMappingURL=resume.d.ts.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { scheduleSchema } from "./schema.js";
|
|
2
|
+
import { connectScheduleClient, toScheduleCommandError, toScheduleRow, } from "./shared.js";
|
|
3
|
+
export async function runResumeCommand(id, options, _command) {
|
|
4
|
+
const { client } = await connectScheduleClient(options.host);
|
|
5
|
+
try {
|
|
6
|
+
const payload = await client.scheduleResume({ id });
|
|
7
|
+
if (payload.error || !payload.schedule) {
|
|
8
|
+
throw new Error(payload.error ?? `Failed to resume schedule: ${id}`);
|
|
9
|
+
}
|
|
10
|
+
return {
|
|
11
|
+
type: "single",
|
|
12
|
+
data: toScheduleRow(payload.schedule),
|
|
13
|
+
schema: scheduleSchema,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
throw toScheduleCommandError("SCHEDULE_RESUME_FAILED", "resume schedule", error);
|
|
18
|
+
}
|
|
19
|
+
finally {
|
|
20
|
+
await client.close().catch(() => { });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=resume.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { SingleResult } from "../../output/index.js";
|
|
3
|
+
import { type ScheduleCommandOptions, type ScheduleRow } from "./shared.js";
|
|
4
|
+
export declare function runRunOnceCommand(id: string, options: ScheduleCommandOptions, _command: Command): Promise<SingleResult<ScheduleRow>>;
|
|
5
|
+
//# sourceMappingURL=run-once.d.ts.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { scheduleSchema } from "./schema.js";
|
|
2
|
+
import { connectScheduleClient, toScheduleCommandError, toScheduleRow, } from "./shared.js";
|
|
3
|
+
export async function runRunOnceCommand(id, options, _command) {
|
|
4
|
+
const { client } = await connectScheduleClient(options.host);
|
|
5
|
+
try {
|
|
6
|
+
const payload = await client.scheduleRunOnce({ id });
|
|
7
|
+
if (payload.error || !payload.schedule) {
|
|
8
|
+
throw new Error(payload.error ?? `Failed to run schedule once: ${id}`);
|
|
9
|
+
}
|
|
10
|
+
return {
|
|
11
|
+
type: "single",
|
|
12
|
+
data: toScheduleRow(payload.schedule),
|
|
13
|
+
schema: scheduleSchema,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
throw toScheduleCommandError("SCHEDULE_RUN_ONCE_FAILED", "run schedule once", error);
|
|
18
|
+
}
|
|
19
|
+
finally {
|
|
20
|
+
await client.close().catch(() => { });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=run-once.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { OutputSchema } from "../../output/index.js";
|
|
2
|
+
import { type ScheduleRow } from "./shared.js";
|
|
3
|
+
import type { ScheduleRecord, ScheduleRunRecord } from "./types.js";
|
|
4
|
+
export declare const scheduleSchema: OutputSchema<ScheduleRow>;
|
|
5
|
+
export interface ScheduleInspectRow {
|
|
6
|
+
key: string;
|
|
7
|
+
value: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function createScheduleInspectSchema(record: ScheduleRecord): OutputSchema<ScheduleInspectRow>;
|
|
10
|
+
export interface ScheduleLogRow {
|
|
11
|
+
id: string;
|
|
12
|
+
status: string;
|
|
13
|
+
startedAt: string;
|
|
14
|
+
agentId: string | null;
|
|
15
|
+
output: string | null;
|
|
16
|
+
error: string | null;
|
|
17
|
+
}
|
|
18
|
+
export declare const scheduleLogSchema: OutputSchema<ScheduleLogRow>;
|
|
19
|
+
export declare function toScheduleLogRow(run: ScheduleRunRecord): ScheduleLogRow;
|
|
20
|
+
export declare function createScheduleInspectRows(schedule: ScheduleRecord): ScheduleInspectRow[];
|
|
21
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { formatCadence, formatTarget } from "./shared.js";
|
|
2
|
+
export const scheduleSchema = {
|
|
3
|
+
idField: "id",
|
|
4
|
+
columns: [
|
|
5
|
+
{ header: "ID", field: "id", width: 10 },
|
|
6
|
+
{ header: "NAME", field: "name", width: 20 },
|
|
7
|
+
{ header: "CADENCE", field: "cadence", width: 20 },
|
|
8
|
+
{ header: "TARGET", field: "target", width: 20 },
|
|
9
|
+
{ header: "STATUS", field: "status", width: 12 },
|
|
10
|
+
{ header: "NEXT RUN", field: "nextRunAt", width: 24 },
|
|
11
|
+
],
|
|
12
|
+
};
|
|
13
|
+
export function createScheduleInspectSchema(record) {
|
|
14
|
+
return {
|
|
15
|
+
idField: "key",
|
|
16
|
+
columns: [
|
|
17
|
+
{ header: "KEY", field: "key", width: 18 },
|
|
18
|
+
{ header: "VALUE", field: "value", width: 80 },
|
|
19
|
+
],
|
|
20
|
+
serialize: () => record,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export const scheduleLogSchema = {
|
|
24
|
+
idField: "id",
|
|
25
|
+
columns: [
|
|
26
|
+
{ header: "RUN ID", field: "id", width: 14 },
|
|
27
|
+
{ header: "STATUS", field: "status", width: 12 },
|
|
28
|
+
{ header: "STARTED", field: "startedAt", width: 24 },
|
|
29
|
+
{ header: "AGENT", field: "agentId", width: 12 },
|
|
30
|
+
{ header: "OUTPUT", field: "output", width: 40 },
|
|
31
|
+
{ header: "ERROR", field: "error", width: 40 },
|
|
32
|
+
],
|
|
33
|
+
};
|
|
34
|
+
export function toScheduleLogRow(run) {
|
|
35
|
+
return {
|
|
36
|
+
id: run.id,
|
|
37
|
+
status: run.status,
|
|
38
|
+
startedAt: run.startedAt,
|
|
39
|
+
agentId: run.agentId ? run.agentId.slice(0, 7) : null,
|
|
40
|
+
output: run.output,
|
|
41
|
+
error: run.error,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export function createScheduleInspectRows(schedule) {
|
|
45
|
+
return [
|
|
46
|
+
{ key: "Id", value: schedule.id },
|
|
47
|
+
{ key: "Name", value: schedule.name ?? "null" },
|
|
48
|
+
{ key: "Prompt", value: schedule.prompt },
|
|
49
|
+
{
|
|
50
|
+
key: "Cadence",
|
|
51
|
+
value: schedule.cadence.type === "cron"
|
|
52
|
+
? formatCadence(schedule.cadence)
|
|
53
|
+
: `every:${schedule.cadence.everyMs}ms`,
|
|
54
|
+
},
|
|
55
|
+
{ key: "Target", value: formatTarget(schedule.target) },
|
|
56
|
+
{ key: "Status", value: schedule.status },
|
|
57
|
+
{ key: "CreatedAt", value: schedule.createdAt },
|
|
58
|
+
{ key: "UpdatedAt", value: schedule.updatedAt },
|
|
59
|
+
{ key: "NextRunAt", value: schedule.nextRunAt ?? "null" },
|
|
60
|
+
{ key: "LastRunAt", value: schedule.lastRunAt ?? "null" },
|
|
61
|
+
{ key: "PausedAt", value: schedule.pausedAt ?? "null" },
|
|
62
|
+
{ key: "ExpiresAt", value: schedule.expiresAt ?? "null" },
|
|
63
|
+
{ key: "MaxRuns", value: schedule.maxRuns == null ? "null" : `${schedule.maxRuns}` },
|
|
64
|
+
{ key: "RunCount", value: `${schedule.runs.length}` },
|
|
65
|
+
];
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { CommandError, CommandOptions } from "../../output/index.js";
|
|
2
|
+
import type { CreateScheduleInput, ScheduleCadence, ScheduleDaemonClient, ScheduleListItem, ScheduleRecord, ScheduleTarget, UpdateScheduleInput } from "./types.js";
|
|
3
|
+
export interface ScheduleCommandOptions extends CommandOptions {
|
|
4
|
+
host?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function connectScheduleClient(host: string | undefined): Promise<{
|
|
7
|
+
client: ScheduleDaemonClient;
|
|
8
|
+
host: string;
|
|
9
|
+
}>;
|
|
10
|
+
export declare function toScheduleCommandError(code: string, action: string, error: unknown): CommandError;
|
|
11
|
+
export declare function formatCadence(cadence: ScheduleCadence): string;
|
|
12
|
+
export declare function formatTarget(target: ScheduleTarget | ScheduleListItem["target"]): string;
|
|
13
|
+
export declare function formatDurationMs(durationMs: number): string;
|
|
14
|
+
export declare function parseScheduleCreateInput(options: {
|
|
15
|
+
prompt: string;
|
|
16
|
+
every?: string;
|
|
17
|
+
cron?: string;
|
|
18
|
+
timezone?: string;
|
|
19
|
+
name?: string;
|
|
20
|
+
target?: string;
|
|
21
|
+
provider?: string;
|
|
22
|
+
mode?: string;
|
|
23
|
+
cwd?: string;
|
|
24
|
+
host?: string;
|
|
25
|
+
maxRuns?: string;
|
|
26
|
+
expiresIn?: string;
|
|
27
|
+
runNow?: boolean;
|
|
28
|
+
}): CreateScheduleInput;
|
|
29
|
+
export interface ScheduleUpdateOptionsInput {
|
|
30
|
+
id: string;
|
|
31
|
+
every?: string;
|
|
32
|
+
cron?: string;
|
|
33
|
+
timezone?: string;
|
|
34
|
+
name?: string;
|
|
35
|
+
prompt?: string;
|
|
36
|
+
provider?: string;
|
|
37
|
+
model?: string;
|
|
38
|
+
mode?: string;
|
|
39
|
+
cwd?: string;
|
|
40
|
+
maxRuns?: string;
|
|
41
|
+
expiresIn?: string;
|
|
42
|
+
clearMaxRuns?: boolean;
|
|
43
|
+
clearExpires?: boolean;
|
|
44
|
+
}
|
|
45
|
+
export declare function parseScheduleUpdateInput(options: ScheduleUpdateOptionsInput): UpdateScheduleInput;
|
|
46
|
+
export interface ScheduleRow {
|
|
47
|
+
id: string;
|
|
48
|
+
name: string | null;
|
|
49
|
+
cadence: string;
|
|
50
|
+
target: string;
|
|
51
|
+
status: string;
|
|
52
|
+
nextRunAt: string | null;
|
|
53
|
+
lastRunAt: string | null;
|
|
54
|
+
}
|
|
55
|
+
export declare function toScheduleRow(schedule: ScheduleListItem | ScheduleRecord): ScheduleRow;
|
|
56
|
+
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import { connectToDaemon, getDaemonHost } from "../../utils/client.js";
|
|
2
|
+
import { parseDuration } from "../../utils/duration.js";
|
|
3
|
+
import { resolveProviderAndModel } from "../../utils/provider-model.js";
|
|
4
|
+
export async function connectScheduleClient(host) {
|
|
5
|
+
const resolvedHost = getDaemonHost({ host });
|
|
6
|
+
try {
|
|
7
|
+
const client = (await connectToDaemon({
|
|
8
|
+
host,
|
|
9
|
+
}));
|
|
10
|
+
return { client, host: resolvedHost };
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
14
|
+
throw {
|
|
15
|
+
code: "DAEMON_NOT_RUNNING",
|
|
16
|
+
message: `Cannot connect to daemon at ${resolvedHost}: ${message}`,
|
|
17
|
+
details: "Start the daemon with: otto daemon start",
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function toScheduleCommandError(code, action, error) {
|
|
22
|
+
if (error && typeof error === "object" && "code" in error) {
|
|
23
|
+
return error;
|
|
24
|
+
}
|
|
25
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
26
|
+
return {
|
|
27
|
+
code,
|
|
28
|
+
message: `Failed to ${action}: ${message}`,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export function formatCadence(cadence) {
|
|
32
|
+
if (cadence.type === "cron") {
|
|
33
|
+
const timezoneSuffix = cadence.timezone ? ` (${cadence.timezone})` : "";
|
|
34
|
+
return `cron:${cadence.expression}${timezoneSuffix}`;
|
|
35
|
+
}
|
|
36
|
+
return `every:${formatDurationMs(cadence.everyMs)}`;
|
|
37
|
+
}
|
|
38
|
+
export function formatTarget(target) {
|
|
39
|
+
if (target.type === "self") {
|
|
40
|
+
return `self:${target.agentId.slice(0, 7)}`;
|
|
41
|
+
}
|
|
42
|
+
if (target.type === "agent") {
|
|
43
|
+
return `agent:${target.agentId.slice(0, 7)}`;
|
|
44
|
+
}
|
|
45
|
+
const modelSuffix = target.config.model ? `/${target.config.model}` : "";
|
|
46
|
+
return `new-agent:${target.config.provider}${modelSuffix}`;
|
|
47
|
+
}
|
|
48
|
+
export function formatDurationMs(durationMs) {
|
|
49
|
+
const parts = [];
|
|
50
|
+
let remainingMs = durationMs;
|
|
51
|
+
const hours = Math.floor(remainingMs / (60 * 60 * 1000));
|
|
52
|
+
if (hours > 0) {
|
|
53
|
+
parts.push(`${hours}h`);
|
|
54
|
+
remainingMs -= hours * 60 * 60 * 1000;
|
|
55
|
+
}
|
|
56
|
+
const minutes = Math.floor(remainingMs / (60 * 1000));
|
|
57
|
+
if (minutes > 0) {
|
|
58
|
+
parts.push(`${minutes}m`);
|
|
59
|
+
remainingMs -= minutes * 60 * 1000;
|
|
60
|
+
}
|
|
61
|
+
const seconds = Math.floor(remainingMs / 1000);
|
|
62
|
+
if (seconds > 0 || parts.length === 0) {
|
|
63
|
+
parts.push(`${seconds}s`);
|
|
64
|
+
}
|
|
65
|
+
return parts.join("");
|
|
66
|
+
}
|
|
67
|
+
function resolveScheduleTarget(args) {
|
|
68
|
+
const { targetValue, hasExplicitNewAgentOption, createNewAgentTarget } = args;
|
|
69
|
+
const currentAgentId = process.env.OTTO_AGENT_ID?.trim();
|
|
70
|
+
if (!targetValue) {
|
|
71
|
+
if (currentAgentId && !hasExplicitNewAgentOption) {
|
|
72
|
+
return { type: "self", agentId: currentAgentId };
|
|
73
|
+
}
|
|
74
|
+
return createNewAgentTarget();
|
|
75
|
+
}
|
|
76
|
+
if (targetValue === "new-agent") {
|
|
77
|
+
return createNewAgentTarget();
|
|
78
|
+
}
|
|
79
|
+
if (hasExplicitNewAgentOption) {
|
|
80
|
+
throw {
|
|
81
|
+
code: "INVALID_TARGET",
|
|
82
|
+
message: "--provider/--mode can only be used with a new-agent target",
|
|
83
|
+
details: "Use --target new-agent or omit --target to create a new agent schedule",
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
if (targetValue === "self") {
|
|
87
|
+
if (!currentAgentId) {
|
|
88
|
+
throw {
|
|
89
|
+
code: "INVALID_TARGET",
|
|
90
|
+
message: "--target self requires running inside a Otto agent",
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
return { type: "self", agentId: currentAgentId };
|
|
94
|
+
}
|
|
95
|
+
return { type: "agent", agentId: targetValue };
|
|
96
|
+
}
|
|
97
|
+
export function parseScheduleCreateInput(options) {
|
|
98
|
+
const prompt = options.prompt.trim();
|
|
99
|
+
if (!prompt) {
|
|
100
|
+
throw {
|
|
101
|
+
code: "INVALID_PROMPT",
|
|
102
|
+
message: "Schedule prompt cannot be empty",
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
const cadence = parseCadenceFromFlags(options.every, options.cron, options.timezone);
|
|
106
|
+
if (!cadence) {
|
|
107
|
+
throw {
|
|
108
|
+
code: "INVALID_CADENCE",
|
|
109
|
+
message: "Specify exactly one of --every or --cron",
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const cwdInput = options.cwd?.trim();
|
|
113
|
+
if (options.host !== undefined && !cwdInput) {
|
|
114
|
+
throw {
|
|
115
|
+
code: "MISSING_CWD",
|
|
116
|
+
message: "--cwd is required when --host is specified (the local working directory will not exist on the remote daemon)",
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
const runOnCreate = resolveRunOnCreate(options.runNow, cadence.type);
|
|
120
|
+
const targetValue = options.target?.trim();
|
|
121
|
+
const modeId = options.mode?.trim();
|
|
122
|
+
const hasExplicitNewAgentOption = options.provider !== undefined || options.mode !== undefined;
|
|
123
|
+
const createNewAgentTarget = () => {
|
|
124
|
+
const resolvedProviderModel = resolveProviderAndModel({
|
|
125
|
+
provider: options.provider,
|
|
126
|
+
});
|
|
127
|
+
return {
|
|
128
|
+
type: "new-agent",
|
|
129
|
+
config: {
|
|
130
|
+
provider: resolvedProviderModel.provider,
|
|
131
|
+
cwd: cwdInput ?? process.cwd(),
|
|
132
|
+
...(resolvedProviderModel.model ? { model: resolvedProviderModel.model } : {}),
|
|
133
|
+
...(modeId ? { modeId } : {}),
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
const target = resolveScheduleTarget({
|
|
138
|
+
targetValue,
|
|
139
|
+
hasExplicitNewAgentOption,
|
|
140
|
+
createNewAgentTarget,
|
|
141
|
+
});
|
|
142
|
+
const maxRuns = options.maxRuns === undefined ? undefined : parsePositiveInt(options.maxRuns, "--max-runs");
|
|
143
|
+
const expiresAt = options.expiresIn === undefined
|
|
144
|
+
? undefined
|
|
145
|
+
: new Date(Date.now() + parseDuration(options.expiresIn)).toISOString();
|
|
146
|
+
return {
|
|
147
|
+
prompt,
|
|
148
|
+
cadence,
|
|
149
|
+
target,
|
|
150
|
+
runOnCreate,
|
|
151
|
+
...(options.name?.trim() ? { name: options.name.trim() } : {}),
|
|
152
|
+
...(maxRuns !== undefined ? { maxRuns } : {}),
|
|
153
|
+
...(expiresAt ? { expiresAt } : {}),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function resolveRunOnCreate(runNow, cadenceType) {
|
|
157
|
+
if (runNow === true && cadenceType === "every") {
|
|
158
|
+
throw {
|
|
159
|
+
code: "REDUNDANT_RUN_NOW",
|
|
160
|
+
message: "--run-now is redundant with --every (interval schedules already fire on creation)",
|
|
161
|
+
details: "Drop --run-now, or use --no-run-now to wait the full interval before the first run",
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
if (runNow === false && cadenceType === "cron") {
|
|
165
|
+
throw {
|
|
166
|
+
code: "REDUNDANT_NO_RUN_NOW",
|
|
167
|
+
message: "--no-run-now is redundant with --cron (cron schedules never fire on creation)",
|
|
168
|
+
details: "Drop --no-run-now, or use --run-now to fire one immediate run on creation",
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
return runNow ?? cadenceType === "every";
|
|
172
|
+
}
|
|
173
|
+
export function parseScheduleUpdateInput(options) {
|
|
174
|
+
const id = options.id.trim();
|
|
175
|
+
if (!id) {
|
|
176
|
+
throw {
|
|
177
|
+
code: "INVALID_SCHEDULE_ID",
|
|
178
|
+
message: "Schedule id cannot be empty",
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
const cadence = parseCadenceFromFlags(options.every, options.cron, options.timezone);
|
|
182
|
+
const newAgentConfig = buildNewAgentConfigPatch(options);
|
|
183
|
+
const maxRuns = parseUpdateMaxRuns(options);
|
|
184
|
+
const expiresAt = parseUpdateExpiresAt(options);
|
|
185
|
+
const name = parseUpdateName(options);
|
|
186
|
+
const prompt = parseUpdatePrompt(options);
|
|
187
|
+
if (name === undefined &&
|
|
188
|
+
prompt === undefined &&
|
|
189
|
+
cadence === undefined &&
|
|
190
|
+
newAgentConfig === undefined &&
|
|
191
|
+
maxRuns === undefined &&
|
|
192
|
+
expiresAt === undefined) {
|
|
193
|
+
throw {
|
|
194
|
+
code: "NO_UPDATES",
|
|
195
|
+
message: "Specify at least one field to update",
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
id,
|
|
200
|
+
...(name !== undefined ? { name } : {}),
|
|
201
|
+
...(prompt !== undefined ? { prompt } : {}),
|
|
202
|
+
...(cadence !== undefined ? { cadence } : {}),
|
|
203
|
+
...(newAgentConfig !== undefined ? { newAgentConfig } : {}),
|
|
204
|
+
...(maxRuns !== undefined ? { maxRuns } : {}),
|
|
205
|
+
...(expiresAt !== undefined ? { expiresAt } : {}),
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
function parseCadenceFromFlags(every, cron, timezone) {
|
|
209
|
+
if (every !== undefined && cron !== undefined) {
|
|
210
|
+
throw {
|
|
211
|
+
code: "INVALID_CADENCE",
|
|
212
|
+
message: "Specify at most one of --every or --cron",
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
const trimmedTimeZone = parseTimeZoneFlag(timezone);
|
|
216
|
+
if (trimmedTimeZone !== undefined && cron === undefined) {
|
|
217
|
+
throw {
|
|
218
|
+
code: "INVALID_TIME_ZONE",
|
|
219
|
+
message: "--timezone can only be used with --cron",
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
if (every !== undefined) {
|
|
223
|
+
return { type: "every", everyMs: parseDuration(every) };
|
|
224
|
+
}
|
|
225
|
+
if (cron !== undefined) {
|
|
226
|
+
return {
|
|
227
|
+
type: "cron",
|
|
228
|
+
expression: cron.trim(),
|
|
229
|
+
...(trimmedTimeZone ? { timezone: trimmedTimeZone } : {}),
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
return undefined;
|
|
233
|
+
}
|
|
234
|
+
function parseTimeZoneFlag(timeZone) {
|
|
235
|
+
if (timeZone === undefined) {
|
|
236
|
+
return undefined;
|
|
237
|
+
}
|
|
238
|
+
const trimmed = timeZone.trim();
|
|
239
|
+
if (!trimmed) {
|
|
240
|
+
throw {
|
|
241
|
+
code: "INVALID_TIME_ZONE",
|
|
242
|
+
message: "--timezone cannot be empty",
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
return trimmed;
|
|
246
|
+
}
|
|
247
|
+
function parseUpdateMaxRuns(options) {
|
|
248
|
+
if (options.maxRuns !== undefined && options.clearMaxRuns) {
|
|
249
|
+
throw {
|
|
250
|
+
code: "CONFLICTING_MAX_RUNS",
|
|
251
|
+
message: "Use either --max-runs <n> or --no-max-runs, not both",
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
if (options.clearMaxRuns) {
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
if (options.maxRuns !== undefined) {
|
|
258
|
+
return parsePositiveInt(options.maxRuns, "--max-runs");
|
|
259
|
+
}
|
|
260
|
+
return undefined;
|
|
261
|
+
}
|
|
262
|
+
function parseUpdateExpiresAt(options) {
|
|
263
|
+
if (options.expiresIn !== undefined && options.clearExpires) {
|
|
264
|
+
throw {
|
|
265
|
+
code: "CONFLICTING_EXPIRES",
|
|
266
|
+
message: "Use either --expires-in <duration> or --no-expires-in, not both",
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
if (options.clearExpires) {
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
if (options.expiresIn !== undefined) {
|
|
273
|
+
return new Date(Date.now() + parseDuration(options.expiresIn)).toISOString();
|
|
274
|
+
}
|
|
275
|
+
return undefined;
|
|
276
|
+
}
|
|
277
|
+
function parseUpdateName(options) {
|
|
278
|
+
if (options.name === undefined) {
|
|
279
|
+
return undefined;
|
|
280
|
+
}
|
|
281
|
+
const trimmed = options.name.trim();
|
|
282
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
283
|
+
}
|
|
284
|
+
function parseUpdatePrompt(options) {
|
|
285
|
+
if (options.prompt === undefined) {
|
|
286
|
+
return undefined;
|
|
287
|
+
}
|
|
288
|
+
const trimmed = options.prompt.trim();
|
|
289
|
+
if (!trimmed) {
|
|
290
|
+
throw {
|
|
291
|
+
code: "INVALID_PROMPT",
|
|
292
|
+
message: "--prompt cannot be empty",
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
return trimmed;
|
|
296
|
+
}
|
|
297
|
+
function buildNewAgentConfigPatch(options) {
|
|
298
|
+
const patch = {};
|
|
299
|
+
if (options.provider !== undefined || options.model !== undefined) {
|
|
300
|
+
const resolved = resolveProviderAndModel({
|
|
301
|
+
provider: options.provider,
|
|
302
|
+
model: options.model,
|
|
303
|
+
});
|
|
304
|
+
patch.provider = resolved.provider;
|
|
305
|
+
if (resolved.model !== undefined) {
|
|
306
|
+
patch.model = resolved.model;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
if (options.mode !== undefined) {
|
|
310
|
+
const trimmed = options.mode.trim();
|
|
311
|
+
patch.modeId = trimmed.length > 0 ? trimmed : null;
|
|
312
|
+
}
|
|
313
|
+
if (options.cwd !== undefined) {
|
|
314
|
+
const trimmed = options.cwd.trim();
|
|
315
|
+
if (!trimmed) {
|
|
316
|
+
throw {
|
|
317
|
+
code: "INVALID_CWD",
|
|
318
|
+
message: "--cwd cannot be empty",
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
patch.cwd = trimmed;
|
|
322
|
+
}
|
|
323
|
+
return Object.keys(patch).length > 0 ? patch : undefined;
|
|
324
|
+
}
|
|
325
|
+
function parsePositiveInt(value, flag) {
|
|
326
|
+
const parsed = Number.parseInt(value, 10);
|
|
327
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
328
|
+
throw {
|
|
329
|
+
code: "INVALID_INTEGER",
|
|
330
|
+
message: `${flag} must be a positive integer`,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
return parsed;
|
|
334
|
+
}
|
|
335
|
+
export function toScheduleRow(schedule) {
|
|
336
|
+
return {
|
|
337
|
+
id: schedule.id,
|
|
338
|
+
name: schedule.name,
|
|
339
|
+
cadence: formatCadence(schedule.cadence),
|
|
340
|
+
target: formatTarget(schedule.target),
|
|
341
|
+
status: schedule.status,
|
|
342
|
+
nextRunAt: schedule.nextRunAt,
|
|
343
|
+
lastRunAt: schedule.lastRunAt,
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
//# sourceMappingURL=shared.js.map
|