@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,105 @@
|
|
|
1
|
+
import { connectToDaemon, getDaemonHost } from "../../utils/client.js";
|
|
2
|
+
import { permitResponseSchema } from "./allow.js";
|
|
3
|
+
export async function runDenyCommand(agentIdOrPrefix, reqId, options, _command) {
|
|
4
|
+
const host = getDaemonHost({ host: options.host });
|
|
5
|
+
// Validate arguments
|
|
6
|
+
if (!options.all && !reqId) {
|
|
7
|
+
const error = {
|
|
8
|
+
code: "MISSING_ARGUMENT",
|
|
9
|
+
message: "Request ID is required unless --all is specified",
|
|
10
|
+
details: "Usage: otto permit deny <agent> <req_id> or otto permit deny <agent> --all",
|
|
11
|
+
};
|
|
12
|
+
throw error;
|
|
13
|
+
}
|
|
14
|
+
let client;
|
|
15
|
+
try {
|
|
16
|
+
client = await connectToDaemon({ host: options.host });
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
20
|
+
const error = {
|
|
21
|
+
code: "DAEMON_NOT_RUNNING",
|
|
22
|
+
message: `Cannot connect to daemon at ${host}: ${message}`,
|
|
23
|
+
details: "Start the daemon with: otto daemon start",
|
|
24
|
+
};
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
const fetchResult = await client.fetchAgent({ agentId: agentIdOrPrefix });
|
|
29
|
+
if (!fetchResult) {
|
|
30
|
+
await client.close();
|
|
31
|
+
const error = {
|
|
32
|
+
code: "AGENT_NOT_FOUND",
|
|
33
|
+
message: `Agent not found: ${agentIdOrPrefix}`,
|
|
34
|
+
details: 'Use "otto ls" to list available agents',
|
|
35
|
+
};
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
const agent = fetchResult.agent;
|
|
39
|
+
const resolvedAgentId = agent.id;
|
|
40
|
+
// Get pending permissions for this agent
|
|
41
|
+
const pendingPermissions = agent.pendingPermissions || [];
|
|
42
|
+
if (pendingPermissions.length === 0) {
|
|
43
|
+
await client.close();
|
|
44
|
+
const error = {
|
|
45
|
+
code: "NO_PENDING_PERMISSIONS",
|
|
46
|
+
message: `No pending permissions for agent ${agent.id.slice(0, 7)}`,
|
|
47
|
+
};
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
// Determine which permissions to deny
|
|
51
|
+
let permissionsToDeny;
|
|
52
|
+
if (options.all) {
|
|
53
|
+
permissionsToDeny = pendingPermissions;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// Find permission by ID prefix
|
|
57
|
+
const permission = pendingPermissions.find((p) => p.id === reqId || p.id.startsWith(reqId));
|
|
58
|
+
if (!permission) {
|
|
59
|
+
await client.close();
|
|
60
|
+
const error = {
|
|
61
|
+
code: "PERMISSION_NOT_FOUND",
|
|
62
|
+
message: `Permission request not found: ${reqId}`,
|
|
63
|
+
details: `Available requests: ${pendingPermissions.map((p) => p.id.slice(0, 8)).join(", ")}`,
|
|
64
|
+
};
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
permissionsToDeny = [permission];
|
|
68
|
+
}
|
|
69
|
+
// Deny permissions
|
|
70
|
+
const results = await Promise.all(permissionsToDeny.map(async (permission) => {
|
|
71
|
+
await client.respondToPermission(resolvedAgentId, permission.id, {
|
|
72
|
+
behavior: "deny",
|
|
73
|
+
...(options.message ? { message: options.message } : {}),
|
|
74
|
+
...(options.interrupt ? { interrupt: true } : {}),
|
|
75
|
+
});
|
|
76
|
+
return {
|
|
77
|
+
requestId: permission.id.slice(0, 8),
|
|
78
|
+
agentId: resolvedAgentId,
|
|
79
|
+
agentShortId: resolvedAgentId.slice(0, 7),
|
|
80
|
+
name: permission.name,
|
|
81
|
+
result: "denied",
|
|
82
|
+
};
|
|
83
|
+
}));
|
|
84
|
+
await client.close();
|
|
85
|
+
return {
|
|
86
|
+
type: "list",
|
|
87
|
+
data: results,
|
|
88
|
+
schema: permitResponseSchema,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
await client.close().catch(() => { });
|
|
93
|
+
// Re-throw CommandErrors
|
|
94
|
+
if (err && typeof err === "object" && "code" in err) {
|
|
95
|
+
throw err;
|
|
96
|
+
}
|
|
97
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
98
|
+
const error = {
|
|
99
|
+
code: "DENY_PERMISSION_FAILED",
|
|
100
|
+
message: `Failed to deny permission: ${message}`,
|
|
101
|
+
};
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=deny.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { runLsCommand } from "./ls.js";
|
|
3
|
+
import { runAllowCommand } from "./allow.js";
|
|
4
|
+
import { runDenyCommand } from "./deny.js";
|
|
5
|
+
import { withOutput } from "../../output/index.js";
|
|
6
|
+
import { addJsonAndDaemonHostOptions } from "../../utils/command-options.js";
|
|
7
|
+
export function createPermitCommand() {
|
|
8
|
+
const permit = new Command("permit").description("Manage permission requests");
|
|
9
|
+
addJsonAndDaemonHostOptions(permit.command("ls").description("List all pending permissions")).action(withOutput(runLsCommand));
|
|
10
|
+
addJsonAndDaemonHostOptions(permit
|
|
11
|
+
.command("allow")
|
|
12
|
+
.description("Allow a permission request")
|
|
13
|
+
.argument("<agent>", "Agent ID (or prefix)")
|
|
14
|
+
.argument("[req_id]", "Permission request ID (optional if --all)")
|
|
15
|
+
.option("--all", "Allow all pending permissions for this agent")
|
|
16
|
+
.option("--input <json>", "Modified input parameters (JSON)")).action(withOutput(runAllowCommand));
|
|
17
|
+
addJsonAndDaemonHostOptions(permit
|
|
18
|
+
.command("deny")
|
|
19
|
+
.description("Deny a permission request")
|
|
20
|
+
.argument("<agent>", "Agent ID (or prefix)")
|
|
21
|
+
.argument("[req_id]", "Permission request ID (optional if --all)")
|
|
22
|
+
.option("--all", "Deny all pending permissions for this agent")
|
|
23
|
+
.option("--message <msg>", "Denial reason message")
|
|
24
|
+
.option("--interrupt", "Stop agent after denial")).action(withOutput(runDenyCommand));
|
|
25
|
+
return permit;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { CommandOptions, ListResult, OutputSchema } from "../../output/index.js";
|
|
3
|
+
/** Permission list item for display */
|
|
4
|
+
export interface PermissionListItem {
|
|
5
|
+
id: string;
|
|
6
|
+
agentId: string;
|
|
7
|
+
agentShortId: string;
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
}
|
|
11
|
+
/** Schema for permit ls output */
|
|
12
|
+
export declare const permitLsSchema: OutputSchema<PermissionListItem>;
|
|
13
|
+
export type PermitLsResult = ListResult<PermissionListItem>;
|
|
14
|
+
export interface PermitLsOptions extends CommandOptions {
|
|
15
|
+
host?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function runLsCommand(options: PermitLsOptions, _command: Command): Promise<PermitLsResult>;
|
|
18
|
+
//# sourceMappingURL=ls.d.ts.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { connectToDaemon, getDaemonHost } from "../../utils/client.js";
|
|
2
|
+
/** Schema for permit ls output */
|
|
3
|
+
export const permitLsSchema = {
|
|
4
|
+
idField: "id",
|
|
5
|
+
columns: [
|
|
6
|
+
{ header: "AGENT", field: "agentShortId", width: 12 },
|
|
7
|
+
{ header: "REQ_ID", field: "id", width: 12 },
|
|
8
|
+
{ header: "TOOL", field: "name", width: 20 },
|
|
9
|
+
{ header: "DESCRIPTION", field: "description", width: 50 },
|
|
10
|
+
],
|
|
11
|
+
};
|
|
12
|
+
/** Transform agent snapshot + permission to list item */
|
|
13
|
+
function toListItem(agent, permission) {
|
|
14
|
+
return {
|
|
15
|
+
id: permission.id.slice(0, 8),
|
|
16
|
+
agentId: agent.id,
|
|
17
|
+
agentShortId: agent.id.slice(0, 7),
|
|
18
|
+
name: permission.name,
|
|
19
|
+
description: permission.description ?? "-",
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export async function runLsCommand(options, _command) {
|
|
23
|
+
const host = getDaemonHost({ host: options.host });
|
|
24
|
+
let client;
|
|
25
|
+
try {
|
|
26
|
+
client = await connectToDaemon({ host: options.host });
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
30
|
+
const error = {
|
|
31
|
+
code: "DAEMON_NOT_RUNNING",
|
|
32
|
+
message: `Cannot connect to daemon at ${host}: ${message}`,
|
|
33
|
+
details: "Start the daemon with: otto daemon start",
|
|
34
|
+
};
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const agentsPayload = await client.fetchAgents({ filter: { includeArchived: true } });
|
|
39
|
+
const agents = agentsPayload.entries.map((entry) => entry.agent);
|
|
40
|
+
await client.close();
|
|
41
|
+
// Collect all pending permissions from all agents
|
|
42
|
+
const items = [];
|
|
43
|
+
for (const agent of agents) {
|
|
44
|
+
if (agent.pendingPermissions && agent.pendingPermissions.length > 0) {
|
|
45
|
+
for (const permission of agent.pendingPermissions) {
|
|
46
|
+
items.push(toListItem(agent, permission));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
type: "list",
|
|
52
|
+
data: items,
|
|
53
|
+
schema: permitLsSchema,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
await client.close().catch(() => { });
|
|
58
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
59
|
+
const error = {
|
|
60
|
+
code: "LIST_PERMISSIONS_FAILED",
|
|
61
|
+
message: `Failed to list permissions: ${message}`,
|
|
62
|
+
};
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=ls.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { runLsCommand } from "./ls.js";
|
|
3
|
+
import { runModelsCommand } from "./models.js";
|
|
4
|
+
import { withOutput } from "../../output/index.js";
|
|
5
|
+
import { addJsonAndDaemonHostOptions } from "../../utils/command-options.js";
|
|
6
|
+
export function createProviderCommand() {
|
|
7
|
+
const provider = new Command("provider").description("Manage agent providers");
|
|
8
|
+
addJsonAndDaemonHostOptions(provider.command("ls").description("List available providers and status")).action(withOutput(runLsCommand));
|
|
9
|
+
addJsonAndDaemonHostOptions(provider
|
|
10
|
+
.command("models")
|
|
11
|
+
.description("List models for a provider")
|
|
12
|
+
.argument("<provider>", "Provider name (claude, codex, opencode)")
|
|
13
|
+
.option("--thinking", "Include thinking option IDs for each model")).action(withOutput(runModelsCommand));
|
|
14
|
+
return provider;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { CommandOptions, ListResult, OutputSchema } from "../../output/index.js";
|
|
3
|
+
import type { ProviderSnapshotEntry } from "@otto-code/protocol/agent-types";
|
|
4
|
+
export interface ProviderListItem {
|
|
5
|
+
provider: ProviderSnapshotEntry["provider"];
|
|
6
|
+
label: string;
|
|
7
|
+
status: string;
|
|
8
|
+
enabled: "Enabled" | "Disabled";
|
|
9
|
+
defaultMode: string;
|
|
10
|
+
modes: string;
|
|
11
|
+
}
|
|
12
|
+
/** Schema for provider ls output */
|
|
13
|
+
export declare const providerLsSchema: OutputSchema<ProviderListItem>;
|
|
14
|
+
export type ProviderLsResult = ListResult<ProviderListItem>;
|
|
15
|
+
export interface ProviderLsOptions extends CommandOptions {
|
|
16
|
+
host?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function runLsCommand(options: ProviderLsOptions, _command: Command): Promise<ProviderLsResult>;
|
|
19
|
+
//# sourceMappingURL=ls.d.ts.map
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { AGENT_PROVIDER_DEFINITIONS } from "@otto-code/protocol/provider-manifest";
|
|
2
|
+
import { tryConnectToDaemon } from "../../utils/client.js";
|
|
3
|
+
/** Derive provider list from the manifest — single source of truth */
|
|
4
|
+
const PROVIDERS = AGENT_PROVIDER_DEFINITIONS.map((def) => ({
|
|
5
|
+
provider: def.id,
|
|
6
|
+
label: def.label,
|
|
7
|
+
status: "available",
|
|
8
|
+
enabled: def.enabledByDefault === false ? "Disabled" : "Enabled",
|
|
9
|
+
defaultMode: def.defaultModeId ?? "-",
|
|
10
|
+
modes: def.modes.length > 0 ? def.modes.map((m) => m.label).join(", ") : "-",
|
|
11
|
+
}));
|
|
12
|
+
function getStaticProviders() {
|
|
13
|
+
return PROVIDERS;
|
|
14
|
+
}
|
|
15
|
+
/** Schema for provider ls output */
|
|
16
|
+
export const providerLsSchema = {
|
|
17
|
+
idField: "provider",
|
|
18
|
+
columns: [
|
|
19
|
+
{ header: "PROVIDER", field: "provider", width: 12 },
|
|
20
|
+
{ header: "LABEL", field: "label", width: 16 },
|
|
21
|
+
{
|
|
22
|
+
header: "STATUS",
|
|
23
|
+
field: "status",
|
|
24
|
+
width: 12,
|
|
25
|
+
color: (value) => {
|
|
26
|
+
if (value === "available")
|
|
27
|
+
return "green";
|
|
28
|
+
if (value === "unavailable")
|
|
29
|
+
return "red";
|
|
30
|
+
return undefined;
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
{ header: "ENABLED", field: "enabled", width: 10 },
|
|
34
|
+
{ header: "DEFAULT MODE", field: "defaultMode", width: 14 },
|
|
35
|
+
{ header: "MODES", field: "modes", width: 30 },
|
|
36
|
+
],
|
|
37
|
+
};
|
|
38
|
+
export async function runLsCommand(options, _command) {
|
|
39
|
+
const client = await tryConnectToDaemon({ host: options.host });
|
|
40
|
+
if (!client) {
|
|
41
|
+
return {
|
|
42
|
+
type: "list",
|
|
43
|
+
data: getStaticProviders(),
|
|
44
|
+
schema: providerLsSchema,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const snapshot = await client.getProvidersSnapshot();
|
|
49
|
+
return {
|
|
50
|
+
type: "list",
|
|
51
|
+
data: snapshot.entries.map((entry) => ({
|
|
52
|
+
provider: entry.provider,
|
|
53
|
+
label: entry.label ?? entry.provider,
|
|
54
|
+
status: entry.status === "ready" ? "available" : entry.status,
|
|
55
|
+
enabled: !entry.enabled ? "Disabled" : "Enabled",
|
|
56
|
+
defaultMode: entry.defaultModeId ?? "default",
|
|
57
|
+
modes: (entry.modes ?? []).map((mode) => mode.label).join(", "),
|
|
58
|
+
})),
|
|
59
|
+
schema: providerLsSchema,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return {
|
|
64
|
+
type: "list",
|
|
65
|
+
data: getStaticProviders(),
|
|
66
|
+
schema: providerLsSchema,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
await client.close().catch(() => { });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=ls.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { CommandOptions, ListResult, OutputSchema } from "../../output/index.js";
|
|
3
|
+
/** Model list item for display */
|
|
4
|
+
export interface ModelListItem {
|
|
5
|
+
model: string;
|
|
6
|
+
id: string;
|
|
7
|
+
description: string;
|
|
8
|
+
thinkingOptionIds: string[];
|
|
9
|
+
defaultThinkingOptionId: string | null;
|
|
10
|
+
thinkingOptions: string;
|
|
11
|
+
}
|
|
12
|
+
/** Schema for provider models output */
|
|
13
|
+
export declare const providerModelsSchema: OutputSchema<ModelListItem>;
|
|
14
|
+
export type ProviderModelsResult = ListResult<ModelListItem>;
|
|
15
|
+
export interface ProviderModelsOptions extends CommandOptions {
|
|
16
|
+
host?: string;
|
|
17
|
+
thinking?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare function runModelsCommand(provider: string, options: ProviderModelsOptions, _command: Command): Promise<ProviderModelsResult>;
|
|
20
|
+
//# sourceMappingURL=models.d.ts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { connectToDaemon } from "../../utils/client.js";
|
|
2
|
+
/** Schema for provider models output */
|
|
3
|
+
export const providerModelsSchema = {
|
|
4
|
+
idField: "id",
|
|
5
|
+
columns: [
|
|
6
|
+
{ header: "ID", field: "id", width: 30 },
|
|
7
|
+
{ header: "MODEL", field: "model", width: 30 },
|
|
8
|
+
{ header: "DESCRIPTION", field: "description", width: 40 },
|
|
9
|
+
],
|
|
10
|
+
};
|
|
11
|
+
const providerModelsWithThinkingSchema = {
|
|
12
|
+
idField: "id",
|
|
13
|
+
columns: [
|
|
14
|
+
{ header: "ID", field: "id", width: 30 },
|
|
15
|
+
{ header: "MODEL", field: "model", width: 30 },
|
|
16
|
+
{ header: "THINKING IDS", field: "thinkingOptions", width: 40 },
|
|
17
|
+
{
|
|
18
|
+
header: "DEFAULT THINKING",
|
|
19
|
+
field: (item) => item.defaultThinkingOptionId ?? "auto",
|
|
20
|
+
width: 18,
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
export async function runModelsCommand(provider, options, _command) {
|
|
25
|
+
const normalizedProvider = provider.toLowerCase();
|
|
26
|
+
const client = await connectToDaemon({ host: options.host });
|
|
27
|
+
try {
|
|
28
|
+
const result = await client.listProviderModels(normalizedProvider);
|
|
29
|
+
if (result.error) {
|
|
30
|
+
throw {
|
|
31
|
+
code: "PROVIDER_ERROR",
|
|
32
|
+
message: `Failed to fetch models for ${provider}: ${result.error}`,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
const models = (result.models ?? []).map((m) => ({
|
|
36
|
+
model: m.label,
|
|
37
|
+
id: m.id,
|
|
38
|
+
description: m.description ?? "",
|
|
39
|
+
thinkingOptionIds: (m.thinkingOptions ?? []).map((option) => option.id),
|
|
40
|
+
defaultThinkingOptionId: m.defaultThinkingOptionId ?? null,
|
|
41
|
+
thinkingOptions: (m.thinkingOptions ?? []).map((option) => option.id).join(", ") || "none",
|
|
42
|
+
}));
|
|
43
|
+
return {
|
|
44
|
+
type: "list",
|
|
45
|
+
data: models,
|
|
46
|
+
schema: options.thinking ? providerModelsWithThinkingSchema : providerModelsSchema,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
await client.close();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=models.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
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 interface ScheduleCreateOptions extends ScheduleCommandOptions {
|
|
5
|
+
every?: string;
|
|
6
|
+
cron?: string;
|
|
7
|
+
timezone?: string;
|
|
8
|
+
name?: string;
|
|
9
|
+
target?: string;
|
|
10
|
+
provider?: string;
|
|
11
|
+
mode?: string;
|
|
12
|
+
cwd?: string;
|
|
13
|
+
maxRuns?: string;
|
|
14
|
+
expiresIn?: string;
|
|
15
|
+
runNow?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare function runCreateCommand(prompt: string, options: ScheduleCreateOptions, command: Command): Promise<SingleResult<ScheduleRow>>;
|
|
18
|
+
//# sourceMappingURL=create.d.ts.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { scheduleSchema } from "./schema.js";
|
|
2
|
+
import { connectScheduleClient, parseScheduleCreateInput, toScheduleCommandError, toScheduleRow, } from "./shared.js";
|
|
3
|
+
export async function runCreateCommand(prompt, options, command) {
|
|
4
|
+
const runNowSource = command.getOptionValueSource("runNow");
|
|
5
|
+
const runNow = runNowSource === "cli" ? Boolean(options.runNow) : undefined;
|
|
6
|
+
const input = parseScheduleCreateInput({
|
|
7
|
+
prompt,
|
|
8
|
+
every: options.every,
|
|
9
|
+
cron: options.cron,
|
|
10
|
+
timezone: options.timezone,
|
|
11
|
+
name: options.name,
|
|
12
|
+
target: options.target,
|
|
13
|
+
provider: options.provider,
|
|
14
|
+
mode: options.mode,
|
|
15
|
+
cwd: options.cwd,
|
|
16
|
+
host: options.host,
|
|
17
|
+
maxRuns: options.maxRuns,
|
|
18
|
+
expiresIn: options.expiresIn,
|
|
19
|
+
runNow,
|
|
20
|
+
});
|
|
21
|
+
const { client } = await connectScheduleClient(options.host);
|
|
22
|
+
try {
|
|
23
|
+
const payload = await client.scheduleCreate(input);
|
|
24
|
+
if (payload.error || !payload.schedule) {
|
|
25
|
+
throw new Error(payload.error ?? "Schedule creation failed");
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
type: "single",
|
|
29
|
+
data: toScheduleRow(payload.schedule),
|
|
30
|
+
schema: scheduleSchema,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
throw toScheduleCommandError("SCHEDULE_CREATE_FAILED", "create schedule", error);
|
|
35
|
+
}
|
|
36
|
+
finally {
|
|
37
|
+
await client.close().catch(() => { });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=create.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { SingleResult } from "../../output/index.js";
|
|
3
|
+
import { type ScheduleCommandOptions } from "./shared.js";
|
|
4
|
+
interface ScheduleDeleteRow {
|
|
5
|
+
id: string;
|
|
6
|
+
status: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function runDeleteCommand(id: string, options: ScheduleCommandOptions, _command: Command): Promise<SingleResult<ScheduleDeleteRow>>;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=delete.d.ts.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { connectScheduleClient, toScheduleCommandError, } from "./shared.js";
|
|
2
|
+
const scheduleDeleteSchema = {
|
|
3
|
+
idField: "id",
|
|
4
|
+
columns: [
|
|
5
|
+
{ header: "ID", field: "id", width: 10 },
|
|
6
|
+
{ header: "STATUS", field: "status", width: 12 },
|
|
7
|
+
],
|
|
8
|
+
};
|
|
9
|
+
export async function runDeleteCommand(id, options, _command) {
|
|
10
|
+
const { client } = await connectScheduleClient(options.host);
|
|
11
|
+
try {
|
|
12
|
+
const payload = await client.scheduleDelete({ id });
|
|
13
|
+
if (payload.error) {
|
|
14
|
+
throw new Error(payload.error);
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
type: "single",
|
|
18
|
+
data: {
|
|
19
|
+
id: payload.scheduleId,
|
|
20
|
+
status: "deleted",
|
|
21
|
+
},
|
|
22
|
+
schema: scheduleDeleteSchema,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
throw toScheduleCommandError("SCHEDULE_DELETE_FAILED", "delete schedule", error);
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
await client.close().catch(() => { });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=delete.js.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { withOutput } from "../../output/index.js";
|
|
3
|
+
import { addJsonAndDaemonHostOptions } from "../../utils/command-options.js";
|
|
4
|
+
import { runCreateCommand } from "./create.js";
|
|
5
|
+
import { runLsCommand } from "./ls.js";
|
|
6
|
+
import { runInspectCommand } from "./inspect.js";
|
|
7
|
+
import { runLogsCommand } from "./logs.js";
|
|
8
|
+
import { runPauseCommand } from "./pause.js";
|
|
9
|
+
import { runResumeCommand } from "./resume.js";
|
|
10
|
+
import { runDeleteCommand } from "./delete.js";
|
|
11
|
+
import { runRunOnceCommand } from "./run-once.js";
|
|
12
|
+
import { runUpdateCommand } from "./update.js";
|
|
13
|
+
export function createScheduleCommand() {
|
|
14
|
+
const schedule = new Command("schedule").description("Manage recurring schedules");
|
|
15
|
+
addJsonAndDaemonHostOptions(schedule
|
|
16
|
+
.command("create")
|
|
17
|
+
.description("Create a schedule")
|
|
18
|
+
.argument("<prompt>", "Prompt to run on the schedule")
|
|
19
|
+
.option("--every <duration>", "Fixed interval cadence (for example: 5m, 1h)")
|
|
20
|
+
.option("--cron <expr>", "Cron cadence expression")
|
|
21
|
+
.option("--timezone <iana>", "IANA time zone for cron cadence (default: UTC)")
|
|
22
|
+
.option("--name <name>", "Optional schedule name")
|
|
23
|
+
.option("--target <self|new-agent|agent-id>", "Run target")
|
|
24
|
+
.option("--provider <provider>", "Agent provider, or provider/model (e.g. codex or codex/gpt-5.4)")
|
|
25
|
+
.option("--mode <mode>", "Provider-specific mode (e.g. claude bypassPermissions, opencode build)")
|
|
26
|
+
.option("--cwd <path>", "Working directory (default: current; required with --host)")
|
|
27
|
+
.option("--run-now", "Fire one immediate run on creation (only with --cron)")
|
|
28
|
+
.option("--no-run-now", "Wait the full interval before the first run (only with --every)")
|
|
29
|
+
.option("--max-runs <n>", "Maximum number of runs")
|
|
30
|
+
.option("--expires-in <duration>", "Time to live for the schedule")).action(withOutput(runCreateCommand));
|
|
31
|
+
addJsonAndDaemonHostOptions(schedule.command("ls").description("List schedules")).action(withOutput(runLsCommand));
|
|
32
|
+
addJsonAndDaemonHostOptions(schedule.command("inspect").description("Inspect a schedule").argument("<id>", "Schedule ID")).action(withOutput(runInspectCommand));
|
|
33
|
+
addJsonAndDaemonHostOptions(schedule
|
|
34
|
+
.command("logs")
|
|
35
|
+
.description("Show recent schedule run logs")
|
|
36
|
+
.argument("<id>", "Schedule ID")).action(withOutput(runLogsCommand));
|
|
37
|
+
addJsonAndDaemonHostOptions(schedule.command("pause").description("Pause a schedule").argument("<id>", "Schedule ID")).action(withOutput(runPauseCommand));
|
|
38
|
+
addJsonAndDaemonHostOptions(schedule
|
|
39
|
+
.command("resume")
|
|
40
|
+
.description("Resume a paused schedule")
|
|
41
|
+
.argument("<id>", "Schedule ID")).action(withOutput(runResumeCommand));
|
|
42
|
+
addJsonAndDaemonHostOptions(schedule.command("delete").description("Delete a schedule").argument("<id>", "Schedule ID")).action(withOutput(runDeleteCommand));
|
|
43
|
+
addJsonAndDaemonHostOptions(schedule
|
|
44
|
+
.command("run-once")
|
|
45
|
+
.description("Manually trigger a single run of a schedule without affecting cadence")
|
|
46
|
+
.argument("<id>", "Schedule ID")).action(withOutput(runRunOnceCommand));
|
|
47
|
+
addJsonAndDaemonHostOptions(schedule
|
|
48
|
+
.command("update")
|
|
49
|
+
.description("Update an existing schedule in place")
|
|
50
|
+
.argument("<id>", "Schedule ID")
|
|
51
|
+
.option("--every <duration>", "Switch to fixed interval cadence (for example: 5m, 1h)")
|
|
52
|
+
.option("--cron <expr>", "Switch to cron cadence expression")
|
|
53
|
+
.option("--timezone <iana>", "IANA time zone for cron cadence (requires --cron)")
|
|
54
|
+
.option("--name <name>", "Rename the schedule (empty string clears the name)")
|
|
55
|
+
.option("--prompt <text>", "Replace the schedule prompt")
|
|
56
|
+
.option("--provider <provider>", "New agent provider, or provider/model (only for new-agent target)")
|
|
57
|
+
.option("--model <model>", "New agent model (only for new-agent target)")
|
|
58
|
+
.option("--mode <mode>", "New agent provider mode (only for new-agent target)")
|
|
59
|
+
.option("--cwd <path>", "New working directory (only for new-agent target)")
|
|
60
|
+
.option("--max-runs <n>", "Set or change maximum number of runs")
|
|
61
|
+
.option("--no-max-runs", "Clear the max-runs limit")
|
|
62
|
+
.option("--expires-in <duration>", "Set or change time to live for the schedule")
|
|
63
|
+
.option("--no-expires-in", "Clear the expiration")).action(withOutput(runUpdateCommand));
|
|
64
|
+
return schedule;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { ListResult } from "../../output/index.js";
|
|
3
|
+
import { type ScheduleInspectRow } from "./schema.js";
|
|
4
|
+
import { type ScheduleCommandOptions } from "./shared.js";
|
|
5
|
+
export declare function runInspectCommand(id: string, options: ScheduleCommandOptions, _command: Command): Promise<ListResult<ScheduleInspectRow>>;
|
|
6
|
+
//# sourceMappingURL=inspect.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createScheduleInspectRows, createScheduleInspectSchema, } from "./schema.js";
|
|
2
|
+
import { connectScheduleClient, toScheduleCommandError, } from "./shared.js";
|
|
3
|
+
export async function runInspectCommand(id, options, _command) {
|
|
4
|
+
const { client } = await connectScheduleClient(options.host);
|
|
5
|
+
try {
|
|
6
|
+
const payload = await client.scheduleInspect({ id });
|
|
7
|
+
if (payload.error || !payload.schedule) {
|
|
8
|
+
throw new Error(payload.error ?? `Schedule not found: ${id}`);
|
|
9
|
+
}
|
|
10
|
+
const rows = createScheduleInspectRows(payload.schedule);
|
|
11
|
+
return {
|
|
12
|
+
type: "list",
|
|
13
|
+
data: rows,
|
|
14
|
+
schema: createScheduleInspectSchema(payload.schedule),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
throw toScheduleCommandError("SCHEDULE_INSPECT_FAILED", "inspect schedule", error);
|
|
19
|
+
}
|
|
20
|
+
finally {
|
|
21
|
+
await client.close().catch(() => { });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=inspect.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { ListResult } from "../../output/index.js";
|
|
3
|
+
import { type ScheduleLogRow } from "./schema.js";
|
|
4
|
+
import { type ScheduleCommandOptions } from "./shared.js";
|
|
5
|
+
export declare function runLogsCommand(id: string, options: ScheduleCommandOptions, _command: Command): Promise<ListResult<ScheduleLogRow>>;
|
|
6
|
+
//# sourceMappingURL=logs.d.ts.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { scheduleLogSchema, toScheduleLogRow } from "./schema.js";
|
|
2
|
+
import { connectScheduleClient, toScheduleCommandError, } from "./shared.js";
|
|
3
|
+
export async function runLogsCommand(id, options, _command) {
|
|
4
|
+
const { client } = await connectScheduleClient(options.host);
|
|
5
|
+
try {
|
|
6
|
+
const payload = await client.scheduleLogs({ id });
|
|
7
|
+
if (payload.error) {
|
|
8
|
+
throw new Error(payload.error);
|
|
9
|
+
}
|
|
10
|
+
return {
|
|
11
|
+
type: "list",
|
|
12
|
+
data: payload.runs.map(toScheduleLogRow),
|
|
13
|
+
schema: scheduleLogSchema,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
throw toScheduleCommandError("SCHEDULE_LOGS_FAILED", "read schedule logs", error);
|
|
18
|
+
}
|
|
19
|
+
finally {
|
|
20
|
+
await client.close().catch(() => { });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=logs.js.map
|