@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,11 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { ListResult } from "../../output/index.js";
|
|
3
|
+
import { type ChatCommandOptions } from "./shared.js";
|
|
4
|
+
import { type ChatMessageRow } from "./schema.js";
|
|
5
|
+
export interface ChatReadOptions extends ChatCommandOptions {
|
|
6
|
+
limit?: string;
|
|
7
|
+
since?: string;
|
|
8
|
+
agent?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function runReadCommand(room: string, options: ChatReadOptions, _command: Command): Promise<ListResult<ChatMessageRow>>;
|
|
11
|
+
//# sourceMappingURL=read.d.ts.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { attachAgentNamesToMessages, connectChatClient, parseSinceValue, toChatCommandError, } from "./shared.js";
|
|
2
|
+
import { chatMessageSchema, toChatMessageRow } from "./schema.js";
|
|
3
|
+
function parseLimit(value) {
|
|
4
|
+
if (!value) {
|
|
5
|
+
return undefined;
|
|
6
|
+
}
|
|
7
|
+
const parsed = Number.parseInt(value, 10);
|
|
8
|
+
if (!Number.isInteger(parsed) || parsed < 0) {
|
|
9
|
+
throw {
|
|
10
|
+
code: "INVALID_LIMIT",
|
|
11
|
+
message: "Invalid --limit value",
|
|
12
|
+
details: "Use a non-negative integer.",
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
return parsed;
|
|
16
|
+
}
|
|
17
|
+
export async function runReadCommand(room, options, _command) {
|
|
18
|
+
const { client } = await connectChatClient(options.host);
|
|
19
|
+
try {
|
|
20
|
+
const payload = await client.readChatMessages({
|
|
21
|
+
room,
|
|
22
|
+
limit: parseLimit(options.limit),
|
|
23
|
+
since: parseSinceValue(options.since),
|
|
24
|
+
authorAgentId: options.agent,
|
|
25
|
+
});
|
|
26
|
+
const messages = await attachAgentNamesToMessages(client, payload.messages.map(toChatMessageRow));
|
|
27
|
+
return {
|
|
28
|
+
type: "list",
|
|
29
|
+
data: messages,
|
|
30
|
+
schema: chatMessageSchema,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
throw toChatCommandError("CHAT_READ_FAILED", "read chat messages", err);
|
|
35
|
+
}
|
|
36
|
+
finally {
|
|
37
|
+
await client.close().catch(() => { });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=read.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { OutputSchema } from "../../output/index.js";
|
|
2
|
+
export interface ChatRoomRow {
|
|
3
|
+
name: string;
|
|
4
|
+
id: string;
|
|
5
|
+
purpose: string;
|
|
6
|
+
messages: number;
|
|
7
|
+
lastMessageAt: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ChatMessageRow {
|
|
10
|
+
id: string;
|
|
11
|
+
author: string;
|
|
12
|
+
authorName: string | null;
|
|
13
|
+
createdAt: string;
|
|
14
|
+
replyTo: string;
|
|
15
|
+
mentionAgentIds: string[];
|
|
16
|
+
mentionLabels: string[];
|
|
17
|
+
body: string;
|
|
18
|
+
}
|
|
19
|
+
export declare const chatRoomSchema: OutputSchema<ChatRoomRow>;
|
|
20
|
+
export declare const chatMessageSchema: OutputSchema<ChatMessageRow>;
|
|
21
|
+
export declare function toChatRoomRow(room: {
|
|
22
|
+
id: string;
|
|
23
|
+
name: string;
|
|
24
|
+
purpose: string | null;
|
|
25
|
+
messageCount: number;
|
|
26
|
+
lastMessageAt: string | null;
|
|
27
|
+
}): ChatRoomRow;
|
|
28
|
+
export declare function toChatMessageRow(message: {
|
|
29
|
+
id: string;
|
|
30
|
+
authorAgentId: string;
|
|
31
|
+
createdAt: string;
|
|
32
|
+
replyToMessageId: string | null;
|
|
33
|
+
mentionAgentIds: string[];
|
|
34
|
+
body: string;
|
|
35
|
+
}): ChatMessageRow;
|
|
36
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
export const chatRoomSchema = {
|
|
2
|
+
idField: "id",
|
|
3
|
+
columns: [
|
|
4
|
+
{ header: "NAME", field: "name", width: 22 },
|
|
5
|
+
{ header: "ID", field: "id", width: 36 },
|
|
6
|
+
{ header: "PURPOSE", field: "purpose", width: 30 },
|
|
7
|
+
{ header: "MESSAGES", field: "messages", width: 10, align: "right" },
|
|
8
|
+
{ header: "LAST MESSAGE", field: "lastMessageAt", width: 24 },
|
|
9
|
+
],
|
|
10
|
+
};
|
|
11
|
+
export const chatMessageSchema = {
|
|
12
|
+
idField: "id",
|
|
13
|
+
columns: [
|
|
14
|
+
{ header: "ID", field: "id", width: 36 },
|
|
15
|
+
{ header: "AUTHOR", field: "author", width: 16 },
|
|
16
|
+
{ header: "AUTHOR NAME", field: (row) => row.authorName ?? "-", width: 20 },
|
|
17
|
+
{ header: "CREATED", field: "createdAt", width: 24 },
|
|
18
|
+
{ header: "REPLY TO", field: "replyTo", width: 36 },
|
|
19
|
+
{ header: "MENTIONS", field: (row) => row.mentionLabels.join(", ") || "-", width: 24 },
|
|
20
|
+
{ header: "MESSAGE", field: "body", width: 60 },
|
|
21
|
+
],
|
|
22
|
+
renderHuman: renderChatTranscript,
|
|
23
|
+
};
|
|
24
|
+
function renderChatTranscript(result, _options) {
|
|
25
|
+
const data = result.type === "list" ? result.data : [result.data];
|
|
26
|
+
if (data.length === 0) {
|
|
27
|
+
return "";
|
|
28
|
+
}
|
|
29
|
+
return data.map(renderChatMessageBlock).join("\n\n");
|
|
30
|
+
}
|
|
31
|
+
function renderChatMessageBlock(message) {
|
|
32
|
+
const authorLabel = message.authorName
|
|
33
|
+
? `${message.authorName} (${message.author})`
|
|
34
|
+
: message.author;
|
|
35
|
+
const lines = [
|
|
36
|
+
`┌─ ${authorLabel} ── ${formatTimestamp(message.createdAt)} ── [msg ${message.id}]`,
|
|
37
|
+
];
|
|
38
|
+
if (message.replyTo !== "-") {
|
|
39
|
+
lines.push(`│ reply-to: msg ${message.replyTo}`);
|
|
40
|
+
}
|
|
41
|
+
if (message.mentionLabels.length > 0) {
|
|
42
|
+
lines.push(`│ mentions: ${message.mentionLabels.join(", ")}`);
|
|
43
|
+
}
|
|
44
|
+
lines.push("│");
|
|
45
|
+
const bodyLines = message.body.split(/\r?\n/);
|
|
46
|
+
for (const line of bodyLines) {
|
|
47
|
+
lines.push(`│ ${line}`);
|
|
48
|
+
}
|
|
49
|
+
lines.push("│");
|
|
50
|
+
lines.push("└─");
|
|
51
|
+
return lines.join("\n");
|
|
52
|
+
}
|
|
53
|
+
function formatTimestamp(input) {
|
|
54
|
+
const date = new Date(input);
|
|
55
|
+
if (Number.isNaN(date.getTime())) {
|
|
56
|
+
return input;
|
|
57
|
+
}
|
|
58
|
+
return date.toISOString().replace("T", " ").replace(".000Z", "Z");
|
|
59
|
+
}
|
|
60
|
+
export function toChatRoomRow(room) {
|
|
61
|
+
return {
|
|
62
|
+
id: room.id,
|
|
63
|
+
name: room.name,
|
|
64
|
+
purpose: room.purpose ?? "-",
|
|
65
|
+
messages: room.messageCount,
|
|
66
|
+
lastMessageAt: room.lastMessageAt ?? "-",
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export function toChatMessageRow(message) {
|
|
70
|
+
return {
|
|
71
|
+
id: message.id,
|
|
72
|
+
author: message.authorAgentId,
|
|
73
|
+
authorName: null,
|
|
74
|
+
createdAt: message.createdAt,
|
|
75
|
+
replyTo: message.replyToMessageId ?? "-",
|
|
76
|
+
mentionAgentIds: message.mentionAgentIds,
|
|
77
|
+
mentionLabels: message.mentionAgentIds,
|
|
78
|
+
body: message.body,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { connectToDaemon } from "../../utils/client.js";
|
|
2
|
+
import type { CommandError, CommandOptions } from "../../output/index.js";
|
|
3
|
+
import type { ChatMessageRow } from "./schema.js";
|
|
4
|
+
export interface ChatCommandOptions extends CommandOptions {
|
|
5
|
+
host?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function connectChatClient(host?: string): Promise<{
|
|
8
|
+
client: import("@otto-code/client/internal/daemon-client").DaemonClient;
|
|
9
|
+
daemonHost: string;
|
|
10
|
+
}>;
|
|
11
|
+
export declare function attachAgentNamesToMessages(client: Awaited<ReturnType<typeof connectToDaemon>>, messages: ChatMessageRow[], options?: {
|
|
12
|
+
timeout?: number;
|
|
13
|
+
bestEffort?: boolean;
|
|
14
|
+
}): Promise<ChatMessageRow[]>;
|
|
15
|
+
export declare function toChatCommandError(code: string, action: string, err: unknown): CommandError;
|
|
16
|
+
export declare function parseSinceValue(input?: string): string | undefined;
|
|
17
|
+
export declare function parseTimeoutMs(input?: string): number | undefined;
|
|
18
|
+
export declare function resolveChatAuthorAgentId(): string;
|
|
19
|
+
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { connectToDaemon, getDaemonHost } from "../../utils/client.js";
|
|
2
|
+
import { parseDuration } from "../../utils/duration.js";
|
|
3
|
+
export async function connectChatClient(host) {
|
|
4
|
+
const daemonHost = getDaemonHost({ host });
|
|
5
|
+
try {
|
|
6
|
+
const client = await connectToDaemon({ host });
|
|
7
|
+
return { client, daemonHost };
|
|
8
|
+
}
|
|
9
|
+
catch (err) {
|
|
10
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
11
|
+
const error = {
|
|
12
|
+
code: "DAEMON_NOT_RUNNING",
|
|
13
|
+
message: `Cannot connect to daemon at ${daemonHost}: ${message}`,
|
|
14
|
+
details: "Start the daemon with: otto daemon start",
|
|
15
|
+
};
|
|
16
|
+
throw error;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export async function attachAgentNamesToMessages(client, messages, options = {}) {
|
|
20
|
+
const agentIds = new Set();
|
|
21
|
+
for (const message of messages) {
|
|
22
|
+
agentIds.add(message.author);
|
|
23
|
+
for (const mentionId of message.mentionAgentIds) {
|
|
24
|
+
agentIds.add(mentionId);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (agentIds.size === 0) {
|
|
28
|
+
return messages;
|
|
29
|
+
}
|
|
30
|
+
let payload;
|
|
31
|
+
try {
|
|
32
|
+
payload = await client.fetchAgents({
|
|
33
|
+
filter: { includeArchived: true },
|
|
34
|
+
...(typeof options.timeout === "number" ? { timeout: options.timeout } : {}),
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
if (options.bestEffort) {
|
|
39
|
+
return messages;
|
|
40
|
+
}
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
const agentNames = new Map();
|
|
44
|
+
for (const entry of payload.entries) {
|
|
45
|
+
const title = entry.agent.title?.trim();
|
|
46
|
+
if (title) {
|
|
47
|
+
agentNames.set(entry.agent.id, title);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return messages.map((message) => ({
|
|
51
|
+
...message,
|
|
52
|
+
authorName: agentNames.get(message.author) ?? null,
|
|
53
|
+
mentionLabels: message.mentionAgentIds.map((agentId) => {
|
|
54
|
+
const name = agentNames.get(agentId);
|
|
55
|
+
return name ? `${name} (${agentId})` : agentId;
|
|
56
|
+
}),
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
export function toChatCommandError(code, action, err) {
|
|
60
|
+
if (err && typeof err === "object" && "code" in err && "message" in err) {
|
|
61
|
+
return err;
|
|
62
|
+
}
|
|
63
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
64
|
+
const rpcCode = typeof err === "object" && err !== null && "code" in err && typeof err.code === "string"
|
|
65
|
+
? err.code
|
|
66
|
+
: undefined;
|
|
67
|
+
return {
|
|
68
|
+
code: rpcCode ?? code,
|
|
69
|
+
message: `Failed to ${action}: ${message}`,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export function parseSinceValue(input) {
|
|
73
|
+
if (!input) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
const durationMs = parseDuration(input);
|
|
78
|
+
return new Date(Date.now() - durationMs).toISOString();
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
const timestamp = new Date(input);
|
|
82
|
+
if (Number.isNaN(timestamp.getTime())) {
|
|
83
|
+
const error = {
|
|
84
|
+
code: "INVALID_SINCE",
|
|
85
|
+
message: "Invalid --since value",
|
|
86
|
+
details: "Use a duration like 10m or an ISO timestamp.",
|
|
87
|
+
};
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
return timestamp.toISOString();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export function parseTimeoutMs(input) {
|
|
94
|
+
if (!input) {
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
const timeoutMs = parseDuration(input);
|
|
99
|
+
if (timeoutMs <= 0) {
|
|
100
|
+
throw new Error("Timeout must be positive");
|
|
101
|
+
}
|
|
102
|
+
return timeoutMs;
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
106
|
+
const error = {
|
|
107
|
+
code: "INVALID_TIMEOUT",
|
|
108
|
+
message: "Invalid timeout value",
|
|
109
|
+
details: message,
|
|
110
|
+
};
|
|
111
|
+
throw error;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
export function resolveChatAuthorAgentId() {
|
|
115
|
+
const agentId = process.env.OTTO_AGENT_ID?.trim();
|
|
116
|
+
return agentId && agentId.length > 0 ? agentId : "manual";
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { ListResult } from "../../output/index.js";
|
|
3
|
+
import { type ChatCommandOptions } from "./shared.js";
|
|
4
|
+
import { type ChatMessageRow } from "./schema.js";
|
|
5
|
+
export interface ChatWaitOptions extends ChatCommandOptions {
|
|
6
|
+
timeout?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function runWaitCommand(room: string, options: ChatWaitOptions, _command: Command): Promise<ListResult<ChatMessageRow>>;
|
|
9
|
+
//# sourceMappingURL=wait.d.ts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { attachAgentNamesToMessages, connectChatClient, parseTimeoutMs, toChatCommandError, } from "./shared.js";
|
|
2
|
+
import { chatMessageSchema, toChatMessageRow } from "./schema.js";
|
|
3
|
+
const CHAT_WAIT_PREFLIGHT_TIMEOUT_MS = 2000;
|
|
4
|
+
export async function runWaitCommand(room, options, _command) {
|
|
5
|
+
const timeoutMs = parseTimeoutMs(options.timeout);
|
|
6
|
+
const { client } = await connectChatClient(options.host);
|
|
7
|
+
const deadline = typeof timeoutMs === "number" ? Date.now() + timeoutMs : null;
|
|
8
|
+
const hasExplicitTimeout = deadline !== null;
|
|
9
|
+
const remainingTimeoutMs = () => deadline === null ? undefined : Math.max(1, deadline - Date.now());
|
|
10
|
+
try {
|
|
11
|
+
const latest = await client.readChatMessages({
|
|
12
|
+
room,
|
|
13
|
+
limit: 1,
|
|
14
|
+
...(hasExplicitTimeout
|
|
15
|
+
? {
|
|
16
|
+
timeout: Math.min(remainingTimeoutMs() ?? 1, CHAT_WAIT_PREFLIGHT_TIMEOUT_MS),
|
|
17
|
+
}
|
|
18
|
+
: {}),
|
|
19
|
+
});
|
|
20
|
+
const afterMessageId = latest.messages[0]?.id;
|
|
21
|
+
const payload = await client.waitForChatMessages({
|
|
22
|
+
room,
|
|
23
|
+
afterMessageId,
|
|
24
|
+
timeoutMs: remainingTimeoutMs() ?? timeoutMs,
|
|
25
|
+
});
|
|
26
|
+
const messages = await attachAgentNamesToMessages(client, payload.messages.map(toChatMessageRow), hasExplicitTimeout
|
|
27
|
+
? {
|
|
28
|
+
timeout: remainingTimeoutMs(),
|
|
29
|
+
bestEffort: true,
|
|
30
|
+
}
|
|
31
|
+
: {});
|
|
32
|
+
return {
|
|
33
|
+
type: "list",
|
|
34
|
+
data: messages,
|
|
35
|
+
schema: chatMessageSchema,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
throw toChatCommandError("CHAT_WAIT_FAILED", "wait for chat messages", err);
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
await client.close().catch(() => { });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=wait.js.map
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Command, Option } from "commander";
|
|
2
|
+
import { startCommand } from "./start.js";
|
|
3
|
+
import { runStatusCommand } from "./status.js";
|
|
4
|
+
import { runStopCommand } from "./stop.js";
|
|
5
|
+
import { runRestartCommand } from "./restart.js";
|
|
6
|
+
import { runSetPasswordCommand } from "./set-password.js";
|
|
7
|
+
import { pairCommand } from "./pair.js";
|
|
8
|
+
import { withOutput } from "../../output/index.js";
|
|
9
|
+
import { addJsonOption } from "../../utils/command-options.js";
|
|
10
|
+
function resolveHostnamesOption(hostnames, allowedHosts) {
|
|
11
|
+
if (typeof hostnames === "string")
|
|
12
|
+
return hostnames;
|
|
13
|
+
if (typeof allowedHosts === "string")
|
|
14
|
+
return allowedHosts;
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
export function createDaemonCommand() {
|
|
18
|
+
const daemon = new Command("daemon").description("Manage the Otto daemon");
|
|
19
|
+
daemon.addCommand(startCommand());
|
|
20
|
+
daemon.addCommand(pairCommand());
|
|
21
|
+
addJsonOption(daemon.command("status").description("Show local daemon status"))
|
|
22
|
+
.option("--home <path>", "Otto home directory (default: ~/.otto)")
|
|
23
|
+
.action(withOutput(runStatusCommand));
|
|
24
|
+
addJsonOption(daemon.command("stop").description("Stop the local daemon"))
|
|
25
|
+
.option("--home <path>", "Otto home directory (default: ~/.otto)")
|
|
26
|
+
.option("--timeout <seconds>", "Wait timeout before failing (default: 15)")
|
|
27
|
+
.option("--force", "Send SIGKILL if graceful stop times out")
|
|
28
|
+
.option("--kill-timeout <seconds>", "Wait after SIGKILL before failing (default: 3)")
|
|
29
|
+
.action(withOutput(runStopCommand));
|
|
30
|
+
addJsonOption(daemon.command("restart").description("Restart the local daemon"))
|
|
31
|
+
.option("--home <path>", "Otto home directory (default: ~/.otto)")
|
|
32
|
+
.option("--timeout <seconds>", "Wait timeout before force step (default: 15)")
|
|
33
|
+
.option("--force", "Send SIGKILL if graceful stop times out")
|
|
34
|
+
.option("--listen <listen>", "Listen target for restarted daemon (host:port, port, or unix socket)")
|
|
35
|
+
.option("--port <port>", "Port for restarted daemon listen target")
|
|
36
|
+
.option("--no-relay", "Disable relay on restarted daemon")
|
|
37
|
+
.option("--no-mcp", "Disable Agent MCP on restarted daemon")
|
|
38
|
+
.option("--no-inject-mcp", "Disable auto-injecting the Otto MCP into created agents")
|
|
39
|
+
.option("--web-ui", "Enable the bundled daemon web UI on restarted daemon")
|
|
40
|
+
.option("--no-web-ui", "Disable the bundled daemon web UI on restarted daemon")
|
|
41
|
+
.option("--hostnames <hosts>", 'Daemon hostnames (comma-separated, e.g. "myhost,.example.com" or "true" for any)')
|
|
42
|
+
.addOption(new Option("--allowed-hosts <hosts>").hideHelp())
|
|
43
|
+
.action(withOutput((...args) => {
|
|
44
|
+
const [options, command] = args.slice(-2);
|
|
45
|
+
return runRestartCommand({
|
|
46
|
+
...options,
|
|
47
|
+
hostnames: resolveHostnamesOption(options.hostnames, options.allowedHosts),
|
|
48
|
+
}, command);
|
|
49
|
+
}));
|
|
50
|
+
addJsonOption(daemon
|
|
51
|
+
.command("set-password")
|
|
52
|
+
.description("Prompt for and save a hashed daemon password to config.json"))
|
|
53
|
+
.option("--home <path>", "Otto home directory (default: ~/.otto)")
|
|
54
|
+
.action(withOutput(runSetPasswordCommand));
|
|
55
|
+
return daemon;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { spawnSync, type ChildProcess } from "node:child_process";
|
|
2
|
+
import { spawnProcess } from "@otto-code/server";
|
|
3
|
+
export interface DaemonStartOptions {
|
|
4
|
+
port?: string;
|
|
5
|
+
listen?: string;
|
|
6
|
+
home?: string;
|
|
7
|
+
foreground?: boolean;
|
|
8
|
+
relay?: boolean;
|
|
9
|
+
relayUseTls?: boolean;
|
|
10
|
+
mcp?: boolean;
|
|
11
|
+
injectMcp?: boolean;
|
|
12
|
+
webUi?: boolean;
|
|
13
|
+
hostnames?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface LocalDaemonPidInfo {
|
|
16
|
+
pid: number;
|
|
17
|
+
startedAt?: string;
|
|
18
|
+
hostname?: string;
|
|
19
|
+
uid?: number;
|
|
20
|
+
listen?: string;
|
|
21
|
+
desktopManaged?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface LocalDaemonState {
|
|
24
|
+
home: string;
|
|
25
|
+
listen: string;
|
|
26
|
+
relayEnabled: boolean;
|
|
27
|
+
relayEndpoint: string;
|
|
28
|
+
relayUseTls: boolean;
|
|
29
|
+
relayPublicUseTls: boolean;
|
|
30
|
+
logPath: string;
|
|
31
|
+
pidPath: string;
|
|
32
|
+
pidInfo: LocalDaemonPidInfo | null;
|
|
33
|
+
running: boolean;
|
|
34
|
+
stalePidFile: boolean;
|
|
35
|
+
}
|
|
36
|
+
export interface DetachedStartResult {
|
|
37
|
+
pid: number | null;
|
|
38
|
+
logPath: string;
|
|
39
|
+
}
|
|
40
|
+
export interface StopLocalDaemonOptions {
|
|
41
|
+
home?: string;
|
|
42
|
+
timeoutMs?: number;
|
|
43
|
+
killTimeoutMs?: number;
|
|
44
|
+
force?: boolean;
|
|
45
|
+
}
|
|
46
|
+
export interface StopLocalDaemonResult {
|
|
47
|
+
action: "stopped" | "not_running";
|
|
48
|
+
home: string;
|
|
49
|
+
pid: number | null;
|
|
50
|
+
forced: boolean;
|
|
51
|
+
usedLifecycleRpc: boolean;
|
|
52
|
+
reason: "not_running" | "lifecycle_shutdown_rpc" | "owner_pid_signal" | "owner_pid_sigkill";
|
|
53
|
+
message: string;
|
|
54
|
+
}
|
|
55
|
+
export interface DetachedDaemonProcess extends Pick<ChildProcess, "once" | "pid" | "unref"> {
|
|
56
|
+
}
|
|
57
|
+
export interface ForegroundDaemonProcessResult {
|
|
58
|
+
status: number | null;
|
|
59
|
+
error?: Error;
|
|
60
|
+
}
|
|
61
|
+
export interface DaemonLaunchRuntime {
|
|
62
|
+
resolveRunnerEntry(): string;
|
|
63
|
+
resolveHome(env: NodeJS.ProcessEnv): string;
|
|
64
|
+
spawnDetached(command: string, args: string[], options: Parameters<typeof spawnProcess>[2]): DetachedDaemonProcess;
|
|
65
|
+
spawnForeground(command: string, args: string[], options: Parameters<typeof spawnSync>[2]): ForegroundDaemonProcessResult;
|
|
66
|
+
}
|
|
67
|
+
export declare const DEFAULT_STOP_TIMEOUT_MS = 15000;
|
|
68
|
+
export declare const DEFAULT_KILL_TIMEOUT_MS = 3000;
|
|
69
|
+
export declare function resolveLocalOttoHome(home?: string): string;
|
|
70
|
+
export declare function resolveTcpHostFromListen(listen: string): string | null;
|
|
71
|
+
export declare function resolveLocalDaemonState(options?: {
|
|
72
|
+
home?: string;
|
|
73
|
+
}): LocalDaemonState;
|
|
74
|
+
export declare function tailDaemonLog(home?: string, lines?: number): string | null;
|
|
75
|
+
export declare function startLocalDaemonDetached(options: DaemonStartOptions, runtime?: DaemonLaunchRuntime): Promise<DetachedStartResult>;
|
|
76
|
+
export declare function startLocalDaemonForeground(options: DaemonStartOptions, runtime?: DaemonLaunchRuntime): number;
|
|
77
|
+
export declare function stopLocalDaemon(options?: StopLocalDaemonOptions): Promise<StopLocalDaemonResult>;
|
|
78
|
+
//# sourceMappingURL=local-daemon.d.ts.map
|