agent-office 0.5.0 → 0.6.1

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.
Files changed (189) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +259 -228
  3. package/dist/commands/cron-requests.d.ts +7 -0
  4. package/dist/commands/cron-requests.d.ts.map +1 -0
  5. package/dist/commands/cron-requests.js +31 -0
  6. package/dist/commands/cron-requests.js.map +1 -0
  7. package/dist/commands/crons.d.ts +10 -0
  8. package/dist/commands/crons.d.ts.map +1 -0
  9. package/dist/commands/crons.js +45 -0
  10. package/dist/commands/crons.js.map +1 -0
  11. package/dist/commands/hello.d.ts +5 -0
  12. package/dist/commands/hello.d.ts.map +1 -0
  13. package/dist/commands/hello.js +4 -0
  14. package/dist/commands/hello.js.map +1 -0
  15. package/dist/commands/messages.d.ts +5 -0
  16. package/dist/commands/messages.d.ts.map +1 -0
  17. package/dist/commands/messages.js +18 -0
  18. package/dist/commands/messages.js.map +1 -0
  19. package/dist/commands/sessions.d.ts +13 -0
  20. package/dist/commands/sessions.d.ts.map +1 -0
  21. package/dist/commands/sessions.js +58 -0
  22. package/dist/commands/sessions.js.map +1 -0
  23. package/dist/commands/task-columns.d.ts +2 -0
  24. package/dist/commands/task-columns.d.ts.map +1 -0
  25. package/dist/commands/task-columns.js +13 -0
  26. package/dist/commands/task-columns.js.map +1 -0
  27. package/dist/commands/tasks.d.ts +11 -0
  28. package/dist/commands/tasks.d.ts.map +1 -0
  29. package/dist/commands/tasks.js +75 -0
  30. package/dist/commands/tasks.js.map +1 -0
  31. package/dist/config.test.d.ts +2 -0
  32. package/dist/config.test.d.ts.map +1 -0
  33. package/dist/config.test.js +50 -0
  34. package/dist/config.test.js.map +1 -0
  35. package/dist/db/index.d.ts +6 -70
  36. package/dist/db/index.d.ts.map +1 -0
  37. package/dist/db/index.js +4 -11
  38. package/dist/db/index.js.map +1 -0
  39. package/dist/db/mock-storage.d.ts +79 -0
  40. package/dist/db/mock-storage.d.ts.map +1 -0
  41. package/dist/db/mock-storage.js +381 -0
  42. package/dist/db/mock-storage.js.map +1 -0
  43. package/dist/db/mock-storage.test.d.ts +2 -0
  44. package/dist/db/mock-storage.test.d.ts.map +1 -0
  45. package/dist/db/mock-storage.test.js +234 -0
  46. package/dist/db/mock-storage.test.js.map +1 -0
  47. package/dist/db/postgresql-storage.d.ts +10 -8
  48. package/dist/db/postgresql-storage.d.ts.map +1 -0
  49. package/dist/db/postgresql-storage.js +76 -42
  50. package/dist/db/postgresql-storage.js.map +1 -0
  51. package/dist/db/sqlite-storage.d.ts +9 -8
  52. package/dist/db/sqlite-storage.d.ts.map +1 -0
  53. package/dist/db/sqlite-storage.js +75 -41
  54. package/dist/db/sqlite-storage.js.map +1 -0
  55. package/dist/db/storage-base.d.ts +7 -8
  56. package/dist/db/storage-base.d.ts.map +1 -0
  57. package/dist/db/storage-base.js +3 -2
  58. package/dist/db/storage-base.js.map +1 -0
  59. package/dist/db/storage.d.ts +12 -12
  60. package/dist/db/storage.d.ts.map +1 -0
  61. package/dist/db/storage.js +1 -0
  62. package/dist/db/storage.js.map +1 -0
  63. package/dist/db/types.d.ts +67 -0
  64. package/dist/db/types.d.ts.map +1 -0
  65. package/dist/db/types.js +2 -0
  66. package/dist/db/types.js.map +1 -0
  67. package/dist/index.d.ts +2 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +397 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/index.test.d.ts +2 -0
  72. package/dist/index.test.d.ts.map +1 -0
  73. package/dist/index.test.js +49 -0
  74. package/dist/index.test.js.map +1 -0
  75. package/dist/lib/output.d.ts +2 -0
  76. package/dist/lib/output.d.ts.map +1 -0
  77. package/dist/lib/output.js +8 -0
  78. package/dist/lib/output.js.map +1 -0
  79. package/dist/services/cron-service.constraints.test.d.ts +2 -0
  80. package/dist/services/cron-service.constraints.test.d.ts.map +1 -0
  81. package/dist/services/cron-service.constraints.test.js +90 -0
  82. package/dist/services/cron-service.constraints.test.js.map +1 -0
  83. package/dist/services/cron-service.d.ts +45 -0
  84. package/dist/services/cron-service.d.ts.map +1 -0
  85. package/dist/services/cron-service.js +157 -0
  86. package/dist/services/cron-service.js.map +1 -0
  87. package/dist/services/cron-service.test.d.ts +2 -0
  88. package/dist/services/cron-service.test.d.ts.map +1 -0
  89. package/dist/services/cron-service.test.js +280 -0
  90. package/dist/services/cron-service.test.js.map +1 -0
  91. package/dist/services/index.d.ts +5 -0
  92. package/dist/services/index.d.ts.map +1 -0
  93. package/dist/services/index.js +5 -0
  94. package/dist/services/index.js.map +1 -0
  95. package/dist/services/message-service.d.ts +16 -0
  96. package/dist/services/message-service.d.ts.map +1 -0
  97. package/dist/services/message-service.js +39 -0
  98. package/dist/services/message-service.js.map +1 -0
  99. package/dist/services/message-service.test.d.ts +2 -0
  100. package/dist/services/message-service.test.d.ts.map +1 -0
  101. package/dist/services/message-service.test.js +145 -0
  102. package/dist/services/message-service.test.js.map +1 -0
  103. package/dist/services/session-service.constraints.test.d.ts +2 -0
  104. package/dist/services/session-service.constraints.test.d.ts.map +1 -0
  105. package/dist/services/session-service.constraints.test.js +34 -0
  106. package/dist/services/session-service.constraints.test.js.map +1 -0
  107. package/dist/services/session-service.d.ts +27 -0
  108. package/dist/services/session-service.d.ts.map +1 -0
  109. package/dist/services/session-service.js +55 -0
  110. package/dist/services/session-service.js.map +1 -0
  111. package/dist/services/session-service.test.d.ts +2 -0
  112. package/dist/services/session-service.test.d.ts.map +1 -0
  113. package/dist/services/session-service.test.js +87 -0
  114. package/dist/services/session-service.test.js.map +1 -0
  115. package/dist/services/task-service.d.ts +25 -0
  116. package/dist/services/task-service.d.ts.map +1 -0
  117. package/dist/services/task-service.js +87 -0
  118. package/dist/services/task-service.js.map +1 -0
  119. package/dist/services/task-service.test.d.ts +2 -0
  120. package/dist/services/task-service.test.d.ts.map +1 -0
  121. package/dist/services/task-service.test.js +180 -0
  122. package/dist/services/task-service.test.js.map +1 -0
  123. package/package.json +41 -42
  124. package/dist/cli.d.ts +0 -2
  125. package/dist/cli.js +0 -317
  126. package/dist/commands/communicator.d.ts +0 -9
  127. package/dist/commands/communicator.js +0 -2232
  128. package/dist/commands/manage.d.ts +0 -5
  129. package/dist/commands/manage.js +0 -20
  130. package/dist/commands/notifier.d.ts +0 -11
  131. package/dist/commands/notifier.js +0 -100
  132. package/dist/commands/screensaver.d.ts +0 -8
  133. package/dist/commands/screensaver.js +0 -1280
  134. package/dist/commands/serve.d.ts +0 -13
  135. package/dist/commands/serve.js +0 -95
  136. package/dist/commands/task-board.d.ts +0 -29
  137. package/dist/commands/task-board.js +0 -251
  138. package/dist/commands/worker.d.ts +0 -16
  139. package/dist/commands/worker.js +0 -145
  140. package/dist/db/migrate.d.ts +0 -2
  141. package/dist/db/migrate.js +0 -3
  142. package/dist/lib/agentic-coding-server.d.ts +0 -66
  143. package/dist/lib/agentic-coding-server.js +0 -7
  144. package/dist/lib/notifier.d.ts +0 -18
  145. package/dist/lib/notifier.js +0 -15
  146. package/dist/lib/opencode-coding-server.d.ts +0 -11
  147. package/dist/lib/opencode-coding-server.js +0 -66
  148. package/dist/lib/pi-coding-server.d.ts +0 -20
  149. package/dist/lib/pi-coding-server.js +0 -162
  150. package/dist/manage/app.d.ts +0 -6
  151. package/dist/manage/app.js +0 -128
  152. package/dist/manage/components/AgentCode.d.ts +0 -8
  153. package/dist/manage/components/AgentCode.js +0 -73
  154. package/dist/manage/components/CreateSession.d.ts +0 -8
  155. package/dist/manage/components/CreateSession.js +0 -37
  156. package/dist/manage/components/CronList.d.ts +0 -9
  157. package/dist/manage/components/CronList.js +0 -321
  158. package/dist/manage/components/CronRequests.d.ts +0 -8
  159. package/dist/manage/components/CronRequests.js +0 -181
  160. package/dist/manage/components/DeleteSession.d.ts +0 -7
  161. package/dist/manage/components/DeleteSession.js +0 -55
  162. package/dist/manage/components/InjectText.d.ts +0 -8
  163. package/dist/manage/components/InjectText.js +0 -51
  164. package/dist/manage/components/ItemSelector.d.ts +0 -7
  165. package/dist/manage/components/ItemSelector.js +0 -20
  166. package/dist/manage/components/MenuSelect.d.ts +0 -13
  167. package/dist/manage/components/MenuSelect.js +0 -22
  168. package/dist/manage/components/MyMail.d.ts +0 -9
  169. package/dist/manage/components/MyMail.js +0 -143
  170. package/dist/manage/components/Profile.d.ts +0 -8
  171. package/dist/manage/components/Profile.js +0 -60
  172. package/dist/manage/components/ReadMail.d.ts +0 -8
  173. package/dist/manage/components/ReadMail.js +0 -110
  174. package/dist/manage/components/SendMessage.d.ts +0 -9
  175. package/dist/manage/components/SendMessage.js +0 -79
  176. package/dist/manage/components/SessionList.d.ts +0 -9
  177. package/dist/manage/components/SessionList.js +0 -608
  178. package/dist/manage/components/SessionSidebar.d.ts +0 -6
  179. package/dist/manage/components/SessionSidebar.js +0 -24
  180. package/dist/manage/components/TailMessages.d.ts +0 -8
  181. package/dist/manage/components/TailMessages.js +0 -126
  182. package/dist/manage/hooks/useApi.d.ts +0 -147
  183. package/dist/manage/hooks/useApi.js +0 -181
  184. package/dist/server/cron.d.ts +0 -25
  185. package/dist/server/cron.js +0 -107
  186. package/dist/server/index.d.ts +0 -4
  187. package/dist/server/index.js +0 -22
  188. package/dist/server/routes.d.ts +0 -13
  189. package/dist/server/routes.js +0 -1396
@@ -1,126 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useState } from "react";
3
- import { Box, Text, useInput } from "ink";
4
- import { Select, Spinner } from "@inkjs/ui";
5
- import { useApi, useAsyncState } from "../hooks/useApi.js";
6
- export function TailMessages({ serverUrl, password, onBack, contentHeight }) {
7
- const { listSessions, getMessages } = useApi(serverUrl, password);
8
- const { run: runList } = useAsyncState();
9
- const [sessions, setSessions] = useState([]);
10
- const [sessionsLoading, setSessionsLoading] = useState(true);
11
- const [stage, setStage] = useState("select");
12
- const [selectedName, setSelectedName] = useState(null);
13
- const [messages, setMessages] = useState([]);
14
- const [error, setError] = useState(null);
15
- const [scrollOffset, setScrollOffset] = useState(0);
16
- useEffect(() => {
17
- runList(listSessions).then((rows) => {
18
- setSessions(rows ?? []);
19
- setSessionsLoading(false);
20
- });
21
- }, []);
22
- // Scroll through messages with arrow keys when viewing
23
- useInput((input, key) => {
24
- if (stage !== "viewing")
25
- return;
26
- if (key.upArrow)
27
- setScrollOffset((o) => Math.max(0, o - 1));
28
- if (key.downArrow)
29
- setScrollOffset((o) => o + 1);
30
- });
31
- const handleSelect = async (name) => {
32
- setSelectedName(name);
33
- setStage("loading");
34
- try {
35
- const msgs = await getMessages(name, 50);
36
- setMessages(msgs);
37
- setScrollOffset(Infinity);
38
- setStage("viewing");
39
- }
40
- catch (err) {
41
- setError(err instanceof Error ? err.message : String(err));
42
- setStage("error");
43
- }
44
- };
45
- if (sessionsLoading) {
46
- return (_jsx(Box, { height: contentHeight, alignItems: "center", justifyContent: "center", children: _jsx(Spinner, { label: "Loading sessions..." }) }));
47
- }
48
- if (stage === "select") {
49
- if (sessions.length === 0) {
50
- return (_jsx(Box, { height: contentHeight, alignItems: "center", justifyContent: "center", children: _jsx(Text, { dimColor: true, children: "No sessions yet. Create one first." }) }));
51
- }
52
- return (_jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsx(Text, { bold: true, children: "Tail Messages" }), _jsx(Text, { dimColor: true, children: "Select a session:" }), _jsx(Select, { options: sessions.map((s) => ({ label: s.name, value: s.name })), onChange: handleSelect })] }));
53
- }
54
- if (stage === "loading") {
55
- return (_jsx(Box, { height: contentHeight, alignItems: "center", justifyContent: "center", children: _jsx(Spinner, { label: `Fetching messages for "${selectedName}"...` }) }));
56
- }
57
- if (stage === "error") {
58
- return (_jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsx(Text, { bold: true, children: "Tail Messages" }), _jsxs(Text, { color: "red", children: ["Error: ", error] })] }));
59
- }
60
- // viewing — render messages with scroll
61
- const messageLines = [];
62
- for (const msg of messages) {
63
- for (const part of msg.parts) {
64
- if (part.type === "text" && part.text) {
65
- // Split multiline text into individual lines for rendering
66
- const lines = part.text.split("\n");
67
- for (let i = 0; i < lines.length; i++) {
68
- messageLines.push({ role: msg.role, text: i === 0 ? lines[i] : ` ${lines[i]}` });
69
- }
70
- messageLines.push({ role: msg.role, text: "" }); // blank line between parts
71
- }
72
- else if (part.type === "tool") {
73
- // Tool part has: tool (string), input, output
74
- const toolName = typeof part.tool === "string" ? part.tool : String(part.tool ?? "unknown");
75
- messageLines.push({ role: msg.role, text: "" }); // Blank line before tool
76
- messageLines.push({ role: msg.role, text: `▶ Tool: ${toolName}` });
77
- if (part.input !== undefined) {
78
- // Try to pretty-print input if it's an object
79
- let inputStr;
80
- if (typeof part.input === "object" && part.input !== null) {
81
- inputStr = JSON.stringify(part.input, null, 2);
82
- }
83
- else {
84
- inputStr = String(part.input);
85
- }
86
- const lines = inputStr.split("\n");
87
- for (let i = 0; i < Math.min(lines.length, 15); i++) {
88
- messageLines.push({ role: msg.role, text: ` ${lines[i]}` });
89
- }
90
- if (lines.length > 15) {
91
- messageLines.push({ role: msg.role, text: ` [...] (${lines.length - 15} more lines)` });
92
- }
93
- }
94
- if (part.output !== undefined) {
95
- // Show output type and preview
96
- let outputPreview;
97
- if (typeof part.output === "object" && part.output !== null) {
98
- outputPreview = JSON.stringify(part.output, null, 2).slice(0, 200);
99
- }
100
- else if (typeof part.output === "string") {
101
- outputPreview = part.output.slice(0, 200);
102
- }
103
- else {
104
- outputPreview = String(part.output).slice(0, 200);
105
- }
106
- const outputType = typeof part.output === "object" ? "object" : typeof part.output;
107
- messageLines.push({ role: msg.role, text: ` ${"—".repeat(40)}` });
108
- messageLines.push({ role: msg.role, text: ` Result (${outputType}):` });
109
- const lines = outputPreview.split("\n");
110
- for (let i = 0; i < Math.min(lines.length, 5); i++) {
111
- messageLines.push({ role: msg.role, text: ` ${lines[i]}` });
112
- }
113
- if (lines.length > 5 || outputPreview.length >= 200) {
114
- messageLines.push({ role: msg.role, text: " [...]" });
115
- }
116
- }
117
- messageLines.push({ role: msg.role, text: "" }); // Blank line after tool
118
- }
119
- }
120
- }
121
- const viewHeight = contentHeight - 3; // header + separator
122
- const maxOffset = Math.max(0, messageLines.length - viewHeight);
123
- const clampedOffset = Math.min(scrollOffset, maxOffset);
124
- const visible = messageLines.slice(clampedOffset, clampedOffset + viewHeight);
125
- return (_jsxs(Box, { flexDirection: "column", gap: 0, children: [_jsxs(Box, { gap: 2, marginBottom: 1, children: [_jsx(Text, { bold: true, children: "Messages" }), _jsx(Text, { color: "cyan", children: selectedName }), _jsxs(Text, { dimColor: true, children: ["(", messages.length, " messages)"] })] }), _jsx(Box, { flexDirection: "column", height: viewHeight, overflow: "hidden", children: visible.length === 0 ? (_jsx(Text, { dimColor: true, children: "No messages in this session yet." })) : (visible.map((line, i) => (_jsx(Box, { children: line.role === "user" ? (_jsx(Text, { color: "green", children: line.text })) : (_jsx(Text, { children: line.text })) }, i)))) }), messageLines.length > viewHeight && (_jsxs(Text, { dimColor: true, children: ["[", clampedOffset + 1, "-", Math.min(clampedOffset + viewHeight, messageLines.length), "/", messageLines.length, " lines] \u2191\u2193 scroll"] }))] }));
126
- }
@@ -1,147 +0,0 @@
1
- export interface Session {
2
- id: number;
3
- name: string;
4
- session_id: string;
5
- agent_code: string;
6
- agent: string | null;
7
- status: string | null;
8
- created_at: string;
9
- }
10
- export interface AppMode {
11
- name: string;
12
- description: string;
13
- model: string;
14
- }
15
- export interface MessagePart {
16
- type: "text" | "tool" | "tool-output";
17
- text?: string;
18
- tool?: string;
19
- input?: unknown;
20
- output?: unknown;
21
- data?: unknown;
22
- }
23
- export interface SessionMessage {
24
- role: "user" | "assistant";
25
- parts: MessagePart[];
26
- }
27
- export interface MailMessage {
28
- id: number;
29
- from_name: string;
30
- to_name: string;
31
- body: string;
32
- read: boolean;
33
- injected: boolean;
34
- created_at: string;
35
- }
36
- export interface Config {
37
- [key: string]: string;
38
- }
39
- export interface CronJob {
40
- id: number;
41
- name: string;
42
- session_name: string;
43
- schedule: string;
44
- timezone: string | null;
45
- message: string;
46
- enabled: boolean;
47
- created_at: string;
48
- last_run: string | null;
49
- next_run: string | null;
50
- }
51
- export interface CronHistoryEntry {
52
- id: number;
53
- cron_job_id: number;
54
- executed_at: string;
55
- success: boolean;
56
- error_message: string | null;
57
- }
58
- export interface CronRequest {
59
- id: number;
60
- name: string;
61
- session_name: string;
62
- schedule: string;
63
- timezone: string | null;
64
- message: string;
65
- status: "pending" | "approved" | "rejected";
66
- requested_at: string;
67
- reviewed_at: string | null;
68
- reviewed_by: string | null;
69
- reviewer_notes: string | null;
70
- }
71
- export declare function useApi(serverUrl: string, password: string): {
72
- listSessions: () => Promise<Session[]>;
73
- createSession: (name: string, agent: string) => Promise<Session>;
74
- deleteSession: (name: string) => Promise<void>;
75
- updateSessionAgent: (name: string, agent: string) => Promise<Session>;
76
- checkHealth: () => Promise<boolean>;
77
- getMessages: (name: string, limit?: number) => Promise<SessionMessage[]>;
78
- injectText: (name: string, text: string) => Promise<{
79
- ok: boolean;
80
- messageID: string;
81
- }>;
82
- revertToStart: (name: string) => Promise<{
83
- ok: boolean;
84
- messageID: string;
85
- }>;
86
- revertAll: () => Promise<{
87
- ok: boolean;
88
- total: number;
89
- results: Array<{
90
- name: string;
91
- ok: boolean;
92
- error?: string;
93
- }>;
94
- }>;
95
- regenerateCode: (name: string) => Promise<Session>;
96
- getConfig: () => Promise<Config>;
97
- setConfig: (key: string, value: string) => Promise<{
98
- ok: boolean;
99
- key: string;
100
- value: string;
101
- }>;
102
- getMailMessages: (name: string, options?: {
103
- sent?: boolean;
104
- unreadOnly?: boolean;
105
- }) => Promise<MailMessage[]>;
106
- sendMailMessage: (from: string, to: string[], body: string) => Promise<{
107
- ok: boolean;
108
- results: Array<{
109
- to: string;
110
- messageId: number;
111
- injected: boolean;
112
- }>;
113
- }>;
114
- markMessageRead: (id: number) => Promise<MailMessage>;
115
- getModes: () => Promise<AppMode[]>;
116
- listCrons: (sessionName?: string) => Promise<CronJob[]>;
117
- createCron: (data: {
118
- name: string;
119
- session_name: string;
120
- schedule: string;
121
- message: string;
122
- timezone?: string;
123
- }) => Promise<CronJob>;
124
- deleteCron: (id: number) => Promise<{
125
- deleted: boolean;
126
- id: number;
127
- name: string;
128
- }>;
129
- enableCron: (id: number) => Promise<CronJob>;
130
- disableCron: (id: number) => Promise<CronJob>;
131
- getCronHistory: (id: number, limit?: number) => Promise<CronHistoryEntry[]>;
132
- listCronRequests: (filters?: {
133
- status?: string;
134
- sessionName?: string;
135
- }) => Promise<CronRequest[]>;
136
- approveCronRequest: (id: number, notes?: string) => Promise<{
137
- request: CronRequest;
138
- cron_job: CronJob;
139
- }>;
140
- rejectCronRequest: (id: number, notes?: string) => Promise<CronRequest>;
141
- };
142
- export declare function useAsyncState<T>(): {
143
- run: (fn: () => Promise<T>) => Promise<T | null>;
144
- data: T | null;
145
- loading: boolean;
146
- error: string | null;
147
- };
@@ -1,181 +0,0 @@
1
- import { useState, useCallback } from "react";
2
- function makeHeaders(password) {
3
- return {
4
- "Content-Type": "application/json",
5
- Authorization: `Bearer ${password}`,
6
- };
7
- }
8
- async function apiFetch(url, password, init) {
9
- const res = await fetch(url, {
10
- ...init,
11
- headers: {
12
- ...makeHeaders(password),
13
- ...init?.headers,
14
- },
15
- });
16
- if (res.status === 401) {
17
- throw new Error("Unauthorized: check your --password");
18
- }
19
- const body = await res.json();
20
- if (!res.ok) {
21
- const msg = body.error ?? `HTTP ${res.status}`;
22
- throw new Error(msg);
23
- }
24
- return body;
25
- }
26
- export function useApi(serverUrl, password) {
27
- const base = serverUrl.replace(/\/$/, "");
28
- const listSessions = useCallback(async () => {
29
- return apiFetch(`${base}/sessions`, password);
30
- }, [base, password]);
31
- const createSession = useCallback(async (name, agent) => {
32
- return apiFetch(`${base}/sessions`, password, {
33
- method: "POST",
34
- body: JSON.stringify({ name, agent }),
35
- });
36
- }, [base, password]);
37
- const getModes = useCallback(async () => {
38
- return apiFetch(`${base}/modes`, password);
39
- }, [base, password]);
40
- const deleteSession = useCallback(async (name) => {
41
- await apiFetch(`${base}/sessions/${encodeURIComponent(name)}`, password, {
42
- method: "DELETE",
43
- });
44
- }, [base, password]);
45
- const updateSessionAgent = useCallback(async (name, agent) => {
46
- return apiFetch(`${base}/sessions/${encodeURIComponent(name)}/agent`, password, {
47
- method: "PATCH",
48
- body: JSON.stringify({ agent }),
49
- });
50
- }, [base, password]);
51
- const checkHealth = useCallback(async () => {
52
- try {
53
- await apiFetch(`${base}/health`, password);
54
- return true;
55
- }
56
- catch {
57
- return false;
58
- }
59
- }, [base, password]);
60
- const getMessages = useCallback(async (name, limit = 20) => {
61
- return apiFetch(`${base}/sessions/${encodeURIComponent(name)}/messages?limit=${limit}`, password);
62
- }, [base, password]);
63
- const injectText = useCallback(async (name, text) => {
64
- return apiFetch(`${base}/sessions/${encodeURIComponent(name)}/inject`, password, { method: "POST", body: JSON.stringify({ text }) });
65
- }, [base, password]);
66
- const revertToStart = useCallback(async (name) => {
67
- return apiFetch(`${base}/sessions/${encodeURIComponent(name)}/revert-to-start`, password, { method: "POST" });
68
- }, [base, password]);
69
- const revertAll = useCallback(async () => {
70
- return apiFetch(`${base}/sessions/revert-all`, password, { method: "POST" });
71
- }, [base, password]);
72
- const regenerateCode = useCallback(async (name) => {
73
- return apiFetch(`${base}/sessions/${encodeURIComponent(name)}/regenerate-code`, password, { method: "POST" });
74
- }, [base, password]);
75
- const getConfig = useCallback(async () => {
76
- return apiFetch(`${base}/config`, password);
77
- }, [base, password]);
78
- const setConfig = useCallback(async (key, value) => {
79
- return apiFetch(`${base}/config`, password, { method: "PUT", body: JSON.stringify({ key, value }) });
80
- }, [base, password]);
81
- const getMailMessages = useCallback(async (name, options) => {
82
- const params = new URLSearchParams();
83
- if (options?.sent)
84
- params.set("sent", "true");
85
- if (options?.unreadOnly)
86
- params.set("unread_only", "true");
87
- const query = params.toString() ? `?${params.toString()}` : "";
88
- return apiFetch(`${base}/messages/${encodeURIComponent(name)}${query}`, password);
89
- }, [base, password]);
90
- const sendMailMessage = useCallback(async (from, to, body) => {
91
- return apiFetch(`${base}/messages`, password, { method: "POST", body: JSON.stringify({ from, to, body }) });
92
- }, [base, password]);
93
- const markMessageRead = useCallback(async (id) => {
94
- return apiFetch(`${base}/messages/${id}/read`, password, { method: "POST" });
95
- }, [base, password]);
96
- const listCrons = useCallback(async (sessionName) => {
97
- const params = sessionName ? `?session_name=${encodeURIComponent(sessionName)}` : "";
98
- return apiFetch(`${base}/crons${params}`, password);
99
- }, [base, password]);
100
- const createCron = useCallback(async (data) => {
101
- return apiFetch(`${base}/crons`, password, {
102
- method: "POST",
103
- body: JSON.stringify(data),
104
- });
105
- }, [base, password]);
106
- const deleteCron = useCallback(async (id) => {
107
- return apiFetch(`${base}/crons/${id}`, password, { method: "DELETE" });
108
- }, [base, password]);
109
- const enableCron = useCallback(async (id) => {
110
- return apiFetch(`${base}/crons/${id}/enable`, password, { method: "POST" });
111
- }, [base, password]);
112
- const disableCron = useCallback(async (id) => {
113
- return apiFetch(`${base}/crons/${id}/disable`, password, { method: "POST" });
114
- }, [base, password]);
115
- const getCronHistory = useCallback(async (id, limit = 10) => {
116
- return apiFetch(`${base}/crons/${id}/history?limit=${limit}`, password);
117
- }, [base, password]);
118
- const listCronRequests = useCallback(async (filters) => {
119
- const params = new URLSearchParams();
120
- if (filters?.status)
121
- params.set("status", filters.status);
122
- if (filters?.sessionName)
123
- params.set("session_name", filters.sessionName);
124
- const query = params.toString() ? `?${params.toString()}` : "";
125
- return apiFetch(`${base}/cron-requests${query}`, password);
126
- }, [base, password]);
127
- const approveCronRequest = useCallback(async (id, notes) => {
128
- return apiFetch(`${base}/cron-requests/${id}/approve`, password, { method: "POST", body: JSON.stringify({ notes }) });
129
- }, [base, password]);
130
- const rejectCronRequest = useCallback(async (id, notes) => {
131
- return apiFetch(`${base}/cron-requests/${id}/reject`, password, { method: "POST", body: JSON.stringify({ notes }) });
132
- }, [base, password]);
133
- return {
134
- listSessions,
135
- createSession,
136
- deleteSession,
137
- updateSessionAgent,
138
- checkHealth,
139
- getMessages,
140
- injectText,
141
- revertToStart,
142
- revertAll,
143
- regenerateCode,
144
- getConfig,
145
- setConfig,
146
- getMailMessages,
147
- sendMailMessage,
148
- markMessageRead,
149
- getModes,
150
- listCrons,
151
- createCron,
152
- deleteCron,
153
- enableCron,
154
- disableCron,
155
- getCronHistory,
156
- listCronRequests,
157
- approveCronRequest,
158
- rejectCronRequest,
159
- };
160
- }
161
- export function useAsyncState() {
162
- const [state, setState] = useState({
163
- data: null,
164
- loading: false,
165
- error: null,
166
- });
167
- const run = useCallback(async (fn) => {
168
- setState({ data: null, loading: true, error: null });
169
- try {
170
- const data = await fn();
171
- setState({ data, loading: false, error: null });
172
- return data;
173
- }
174
- catch (err) {
175
- const error = err instanceof Error ? err.message : String(err);
176
- setState({ data: null, loading: false, error });
177
- return null;
178
- }
179
- }, []);
180
- return { ...state, run };
181
- }
@@ -1,25 +0,0 @@
1
- import type { AgentOfficeStorage } from "../db/storage.js";
2
- import type { AgenticCodingServer } from "../lib/agentic-coding-server.js";
3
- import type { CronJobRow } from "../db/index.js";
4
- interface CronSchedulerOptions {
5
- onJobExecuted?: (jobId: number, success: boolean, error?: string) => void;
6
- }
7
- export declare class CronScheduler {
8
- private options;
9
- private activeJobs;
10
- private storage;
11
- private agenticCodingServer;
12
- private serverUrl;
13
- private started;
14
- constructor(options?: CronSchedulerOptions);
15
- start(storage: AgentOfficeStorage, agenticCodingServer: AgenticCodingServer, serverUrl: string): Promise<void>;
16
- stop(): void;
17
- private addJob;
18
- private executeJob;
19
- addCronJob(job: CronJobRow): void;
20
- removeCronJob(jobId: number): void;
21
- enableCronJob(job: CronJobRow): void;
22
- disableCronJob(jobId: number): void;
23
- isTracking(jobId: number): boolean;
24
- }
25
- export {};
@@ -1,107 +0,0 @@
1
- import { Cron } from "croner";
2
- import { generateSystemPrompt } from "./routes.js";
3
- const CRON_INJECTION_BLURB = [
4
- ``,
5
- `---`,
6
- `You have a scheduled cron job trigger. Please review the injected message above`,
7
- `and take appropriate action.`,
8
- ].join("\n");
9
- export class CronScheduler {
10
- options;
11
- activeJobs = new Map();
12
- storage = null;
13
- agenticCodingServer = null;
14
- serverUrl = "";
15
- started = false;
16
- constructor(options = {}) {
17
- this.options = options;
18
- }
19
- async start(storage, agenticCodingServer, serverUrl) {
20
- if (this.started)
21
- return;
22
- this.storage = storage;
23
- this.agenticCodingServer = agenticCodingServer;
24
- this.serverUrl = serverUrl;
25
- const rows = await storage.listCronJobs();
26
- for (const job of rows) {
27
- if (job.enabled) {
28
- this.addJob(job);
29
- }
30
- }
31
- this.started = true;
32
- console.log(`Cron scheduler started: tracking ${rows.length} active jobs`);
33
- }
34
- stop() {
35
- for (const cronInst of this.activeJobs.values()) {
36
- cronInst.cron.stop();
37
- }
38
- this.activeJobs.clear();
39
- this.started = false;
40
- console.log("Cron scheduler stopped");
41
- }
42
- addJob(job) {
43
- if (!this.agenticCodingServer || !this.storage)
44
- return;
45
- const options = {
46
- protect: true,
47
- name: job.name,
48
- };
49
- if (job.timezone) {
50
- options.timezone = job.timezone;
51
- }
52
- const cron = new Cron(job.schedule, options, async () => {
53
- await this.executeJob(job);
54
- });
55
- this.activeJobs.set(job.id, { cron, job });
56
- }
57
- async executeJob(job) {
58
- if (!this.storage || !this.agenticCodingServer)
59
- return;
60
- const executedAt = new Date();
61
- try {
62
- const session = await this.storage.getSessionByName(job.session_name);
63
- if (!session) {
64
- throw new Error(`Session "${job.session_name}" not found`);
65
- }
66
- const humanName = (await this.storage.getConfig('human_name')) ?? 'your human manager';
67
- const humanDescription = (await this.storage.getConfig('human_description')) ?? '';
68
- const injectText = `[Cron Job "${job.name}" — ${executedAt.toISOString()}]\n${job.message}${CRON_INJECTION_BLURB}`;
69
- const token = `${session.agent_code}@${this.serverUrl}`;
70
- const system = generateSystemPrompt(job.session_name, session.status, humanName, humanDescription, token);
71
- await this.agenticCodingServer.sendMessage(session.session_id, injectText, session.agent, system);
72
- await this.storage.updateCronJobLastRun(job.id, executedAt);
73
- await this.storage.createCronHistory(job.id, executedAt, true);
74
- this.options.onJobExecuted?.(job.id, true);
75
- console.log(`Cron job "${job.name}" executed successfully`);
76
- }
77
- catch (err) {
78
- const errorMessage = err instanceof Error ? err.message : String(err);
79
- await this.storage.createCronHistory(job.id, executedAt, false, errorMessage);
80
- this.options.onJobExecuted?.(job.id, false, errorMessage);
81
- console.error(`Cron job "${job.name}" failed:`, errorMessage);
82
- }
83
- }
84
- addCronJob(job) {
85
- if (job.enabled) {
86
- this.addJob(job);
87
- }
88
- }
89
- removeCronJob(jobId) {
90
- const cronInst = this.activeJobs.get(jobId);
91
- if (cronInst) {
92
- cronInst.cron.stop();
93
- this.activeJobs.delete(jobId);
94
- }
95
- }
96
- enableCronJob(job) {
97
- if (!this.activeJobs.has(job.id) && job.enabled) {
98
- this.addJob(job);
99
- }
100
- }
101
- disableCronJob(jobId) {
102
- this.removeCronJob(jobId);
103
- }
104
- isTracking(jobId) {
105
- return this.activeJobs.has(jobId);
106
- }
107
- }
@@ -1,4 +0,0 @@
1
- import type { AgentOfficeStorage } from "../db/index.js";
2
- import type { AgenticCodingServer } from "../lib/agentic-coding-server.js";
3
- import { CronScheduler } from "./cron.js";
4
- export declare function createApp(storage: AgentOfficeStorage, agenticCodingServer: AgenticCodingServer, password: string, serverUrl: string, cronScheduler: CronScheduler): import("express-serve-static-core").Express;
@@ -1,22 +0,0 @@
1
- import express from "express";
2
- import { createRouter, createWorkerRouter } from "./routes.js";
3
- function authMiddleware(password) {
4
- return (req, res, next) => {
5
- const header = req.headers.authorization;
6
- if (!header || header !== `Bearer ${password}`) {
7
- res.status(401).json({ error: "Unauthorized" });
8
- return;
9
- }
10
- next();
11
- };
12
- }
13
- export function createApp(storage, agenticCodingServer, password, serverUrl, cronScheduler) {
14
- const app = express();
15
- app.use(express.json());
16
- // Worker routes are unauthenticated — mounted before auth middleware
17
- app.use("/", createWorkerRouter(storage, agenticCodingServer, serverUrl));
18
- // Everything else requires Bearer auth
19
- app.use(authMiddleware(password));
20
- app.use("/", createRouter(storage, agenticCodingServer, serverUrl, cronScheduler));
21
- return app;
22
- }
@@ -1,13 +0,0 @@
1
- import { Router } from "express";
2
- import type { AgentOfficeStorage } from "../db/index.js";
3
- import type { AgenticCodingServer } from "../lib/agentic-coding-server.js";
4
- import { CronScheduler } from "./cron.js";
5
- /**
6
- * Build the persistent system-prompt briefing for a worker session.
7
- * This is injected as the `system` field on every `promptAsync` call so the
8
- * agent always has its identity, token, and command reference in context —
9
- * without consuming a user-message turn.
10
- */
11
- export declare function generateSystemPrompt(name: string, status: string | null, humanName: string, humanDescription: string, token: string): string;
12
- export declare function createRouter(storage: AgentOfficeStorage, agenticCodingServer: AgenticCodingServer, serverUrl: string, scheduler: CronScheduler): Router;
13
- export declare function createWorkerRouter(storage: AgentOfficeStorage, agenticCodingServer: AgenticCodingServer, serverUrl: string): Router;