agent-office 0.3.1 → 0.4.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.
@@ -215,267 +215,6 @@ function CoworkerMailView({ serverUrl, password, sessionName, contentHeight, onC
215
215
  ? _jsx(Text, { bold: true, color: "yellow", children: "[Sent]" })
216
216
  : _jsx(Text, { dimColor: true, children: "Sent (s)" })] }), renderMessages()] }));
217
217
  }
218
- function MemoryView({ serverUrl, password, sessionName, contentHeight, onClose }) {
219
- const { listMemories, searchMemories, deleteMemory, updateMemory, addMemory } = useApi(serverUrl, password);
220
- const [memoryMode, setMemoryMode] = useState("browse");
221
- const [memories, setMemories] = useState([]);
222
- const [searchResults, setSearchResults] = useState([]);
223
- const [total, setTotal] = useState(0);
224
- const [loading, setLoading] = useState(true);
225
- const [error, setError] = useState(null);
226
- const [cursor, setCursor] = useState(0);
227
- const [scrollOffset, setScrollOffset] = useState(0);
228
- const [selectedMemory, setSelectedMemory] = useState(null);
229
- const [actionMsg, setActionMsg] = useState(null);
230
- const [searchInput, setSearchInput] = useState(false);
231
- const loadMemories = useCallback(async () => {
232
- setLoading(true);
233
- setError(null);
234
- try {
235
- const result = await listMemories(sessionName, 100);
236
- setMemories(result.memories);
237
- setTotal(result.total);
238
- }
239
- catch (err) {
240
- setError(err instanceof Error ? err.message : String(err));
241
- }
242
- finally {
243
- setLoading(false);
244
- }
245
- }, [sessionName]);
246
- useEffect(() => { void loadMemories(); }, [loadMemories]);
247
- useInput((input, key) => {
248
- if (memoryMode === "browse") {
249
- if (key.escape) {
250
- onClose();
251
- return;
252
- }
253
- if (!loading) {
254
- if (input === "a") {
255
- setMemoryMode("adding");
256
- }
257
- if (input === "s") {
258
- setSearchInput(true);
259
- setMemoryMode("search");
260
- }
261
- }
262
- if (!loading && memories.length > 0) {
263
- if (key.upArrow)
264
- setCursor((c) => Math.max(0, c - 1));
265
- if (key.downArrow)
266
- setCursor((c) => Math.min(memories.length - 1, c + 1));
267
- if (key.return) {
268
- setSelectedMemory(memories[cursor] ?? null);
269
- setMemoryMode("view-detail");
270
- setScrollOffset(0);
271
- }
272
- if (input === "d") {
273
- setSelectedMemory(memories[cursor] ?? null);
274
- setMemoryMode("confirm-delete");
275
- }
276
- }
277
- }
278
- if (memoryMode === "view-detail") {
279
- if (key.escape) {
280
- setMemoryMode("browse");
281
- setSelectedMemory(null);
282
- return;
283
- }
284
- if (key.upArrow)
285
- setScrollOffset((o) => Math.max(0, o - 1));
286
- if (key.downArrow)
287
- setScrollOffset((o) => o + 1);
288
- if (input === "e") {
289
- setMemoryMode("editing");
290
- }
291
- if (input === "d") {
292
- setMemoryMode("confirm-delete");
293
- }
294
- }
295
- if (memoryMode === "search-results") {
296
- if (key.escape) {
297
- setMemoryMode("browse");
298
- setSearchResults([]);
299
- setCursor(0);
300
- return;
301
- }
302
- if (searchResults.length > 0) {
303
- if (key.upArrow)
304
- setCursor((c) => Math.max(0, c - 1));
305
- if (key.downArrow)
306
- setCursor((c) => Math.min(searchResults.length - 1, c + 1));
307
- if (key.return) {
308
- setSelectedMemory(searchResults[cursor] ?? null);
309
- setMemoryMode("view-detail");
310
- setScrollOffset(0);
311
- }
312
- }
313
- }
314
- if (memoryMode === "confirm-delete") {
315
- if (key.escape) {
316
- setMemoryMode(selectedMemory ? "view-detail" : "browse");
317
- return;
318
- }
319
- if (input === "y" || input === "Y") {
320
- void handleDelete();
321
- }
322
- if (input === "n" || input === "N") {
323
- setMemoryMode(selectedMemory ? "view-detail" : "browse");
324
- }
325
- }
326
- if (memoryMode === "adding" && key.escape) {
327
- setMemoryMode("browse");
328
- }
329
- if (memoryMode === "search" && key.escape) {
330
- setSearchInput(false);
331
- setMemoryMode("browse");
332
- }
333
- if (memoryMode === "editing" && key.escape) {
334
- setMemoryMode("view-detail");
335
- }
336
- });
337
- const handleDelete = async () => {
338
- if (!selectedMemory)
339
- return;
340
- setMemoryMode("deleting");
341
- try {
342
- await deleteMemory(sessionName, selectedMemory.id);
343
- setActionMsg(`Memory deleted.`);
344
- setSelectedMemory(null);
345
- setMemoryMode("browse");
346
- setCursor(0);
347
- await loadMemories();
348
- }
349
- catch (err) {
350
- setError(err instanceof Error ? err.message : String(err));
351
- setMemoryMode("browse");
352
- }
353
- };
354
- const handleAdd = async (content) => {
355
- const trimmed = content.trim();
356
- if (!trimmed)
357
- return;
358
- setLoading(true);
359
- try {
360
- await addMemory(sessionName, trimmed);
361
- setActionMsg("Memory added.");
362
- setMemoryMode("browse");
363
- await loadMemories();
364
- }
365
- catch (err) {
366
- setError(err instanceof Error ? err.message : String(err));
367
- setMemoryMode("browse");
368
- }
369
- finally {
370
- setLoading(false);
371
- }
372
- };
373
- const handleSearch = async (query) => {
374
- const trimmed = query.trim();
375
- if (!trimmed)
376
- return;
377
- setSearchInput(false);
378
- setLoading(true);
379
- try {
380
- const results = await searchMemories(sessionName, trimmed, 20);
381
- setSearchResults(results);
382
- setCursor(0);
383
- setMemoryMode("search-results");
384
- }
385
- catch (err) {
386
- setError(err instanceof Error ? err.message : String(err));
387
- setMemoryMode("browse");
388
- }
389
- finally {
390
- setLoading(false);
391
- }
392
- };
393
- const handleEdit = async (newContent) => {
394
- const trimmed = newContent.trim();
395
- if (!trimmed || !selectedMemory)
396
- return;
397
- setLoading(true);
398
- try {
399
- await updateMemory(sessionName, selectedMemory.id, trimmed);
400
- setActionMsg("Memory updated.");
401
- setSelectedMemory(null);
402
- setMemoryMode("browse");
403
- await loadMemories();
404
- }
405
- catch (err) {
406
- setError(err instanceof Error ? err.message : String(err));
407
- setMemoryMode("view-detail");
408
- }
409
- finally {
410
- setLoading(false);
411
- }
412
- };
413
- // Clear action messages after a delay
414
- useEffect(() => {
415
- if (actionMsg) {
416
- const t = setTimeout(() => setActionMsg(null), 2000);
417
- return () => clearTimeout(t);
418
- }
419
- }, [actionMsg]);
420
- if (loading && memories.length === 0 && memoryMode === "browse") {
421
- return (_jsx(Box, { height: contentHeight, alignItems: "center", justifyContent: "center", children: _jsx(Spinner, { label: `Loading memories for "${sessionName}"...` }) }));
422
- }
423
- if (memoryMode === "adding") {
424
- return (_jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsxs(Box, { gap: 2, children: [_jsx(Text, { bold: true, children: "Add Memory" }), _jsx(Text, { color: "cyan", children: sessionName })] }), _jsxs(Box, { gap: 1, children: [_jsx(Text, { children: "Content: " }), _jsx(TextInput, { placeholder: "Type memory content...", onSubmit: (v) => void handleAdd(v) })] }), _jsx(Text, { dimColor: true, children: "Enter to save \u00B7 Esc cancel" })] }));
425
- }
426
- if (memoryMode === "search") {
427
- return (_jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsxs(Box, { gap: 2, children: [_jsx(Text, { bold: true, children: "Search Memories" }), _jsx(Text, { color: "cyan", children: sessionName })] }), _jsxs(Box, { gap: 1, children: [_jsx(Text, { children: "Query: " }), searchInput && (_jsx(TextInput, { placeholder: "semantic or keyword search...", onSubmit: (v) => void handleSearch(v) }))] }), _jsx(Text, { dimColor: true, children: "Enter to search \u00B7 Esc cancel" })] }));
428
- }
429
- if (memoryMode === "search-results") {
430
- const viewHeight = contentHeight - 5;
431
- return (_jsxs(Box, { flexDirection: "column", gap: 0, children: [_jsxs(Box, { gap: 2, marginBottom: 1, children: [_jsx(Text, { bold: true, children: "Search Results" }), _jsx(Text, { color: "cyan", children: sessionName }), _jsxs(Text, { dimColor: true, children: ["(", searchResults.length, " results)"] })] }), loading && _jsx(Spinner, { label: "Searching..." }), searchResults.length === 0 && !loading ? (_jsx(Text, { dimColor: true, children: "No results found." })) : (_jsx(Box, { flexDirection: "column", height: viewHeight, overflow: "hidden", children: searchResults.map((mem, i) => {
432
- const sel = i === cursor;
433
- const preview = mem.content.length > 80 ? mem.content.slice(0, 80) + "..." : mem.content;
434
- return (_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: sel ? "cyan" : undefined, bold: sel, children: sel ? "▶" : " " }), _jsx(Text, { dimColor: true, children: (mem.score?.toFixed(4) ?? "").padEnd(8) }), _jsx(Text, { color: sel ? "cyan" : undefined, children: preview })] }, mem.id));
435
- }) })), _jsx(Text, { dimColor: true, children: "\u2191\u2193 navigate \u00B7 Enter view \u00B7 Esc back to list" })] }));
436
- }
437
- if (memoryMode === "view-detail" && selectedMemory) {
438
- const lines = selectedMemory.content.split("\n");
439
- const metaStr = Object.keys(selectedMemory.metadata).length > 0
440
- ? JSON.stringify(selectedMemory.metadata, null, 2)
441
- : "(none)";
442
- const allLines = [
443
- `ID: ${selectedMemory.id}`,
444
- `Created: ${selectedMemory.createdAt}`,
445
- ...(selectedMemory.score != null ? [`Score: ${selectedMemory.score.toFixed(4)}`] : []),
446
- `Metadata: ${metaStr}`,
447
- ``,
448
- `Content:`,
449
- ...lines,
450
- ];
451
- const viewHeight = contentHeight - 5;
452
- const maxOff = Math.max(0, allLines.length - viewHeight);
453
- const clamped = Math.min(scrollOffset, maxOff);
454
- const visible = allLines.slice(clamped, clamped + viewHeight);
455
- return (_jsxs(Box, { flexDirection: "column", gap: 0, children: [_jsxs(Box, { gap: 2, marginBottom: 1, children: [_jsx(Text, { bold: true, children: "Memory Detail" }), _jsx(Text, { color: "cyan", children: sessionName })] }), _jsx(Box, { flexDirection: "column", height: viewHeight, overflow: "hidden", children: visible.map((line, i) => (_jsx(Text, { children: line }, i))) }), _jsx(Text, { dimColor: true, children: "\u2191\u2193 scroll \u00B7 e edit \u00B7 d delete \u00B7 Esc back" })] }));
456
- }
457
- if (memoryMode === "confirm-delete") {
458
- const target = selectedMemory ?? memories[cursor];
459
- return (_jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsxs(Box, { gap: 2, children: [_jsx(Text, { bold: true, color: "red", children: "Delete Memory" }), _jsx(Text, { color: "cyan", children: sessionName })] }), target && (_jsxs(Text, { children: ["Delete memory: ", _jsxs(Text, { color: "yellow", children: ["\"", target.content.slice(0, 60), "...\""] }), "?"] })), _jsx(Text, { children: "y/n" })] }));
460
- }
461
- if (memoryMode === "deleting") {
462
- return (_jsx(Box, { height: contentHeight, alignItems: "center", justifyContent: "center", children: _jsx(Spinner, { label: "Deleting memory..." }) }));
463
- }
464
- if (memoryMode === "editing" && selectedMemory) {
465
- return (_jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsxs(Box, { gap: 2, children: [_jsx(Text, { bold: true, children: "Edit Memory" }), _jsx(Text, { color: "cyan", children: sessionName })] }), _jsxs(Text, { dimColor: true, children: ["Current: ", selectedMemory.content.slice(0, 80), "..."] }), _jsxs(Box, { gap: 1, children: [_jsx(Text, { children: "New content: " }), _jsx(TextInput, { placeholder: "Enter new content...", defaultValue: selectedMemory.content, onSubmit: (v) => void handleEdit(v) })] }), _jsx(Text, { dimColor: true, children: "Enter to save \u00B7 Esc cancel" })] }));
466
- }
467
- // ── Browse mode ───────────────────────────────────────────────────────────
468
- const viewHeight = contentHeight - 5;
469
- const visibleStart = Math.max(0, cursor - viewHeight + 1);
470
- const visibleMemories = memories.slice(visibleStart, visibleStart + viewHeight);
471
- return (_jsxs(Box, { flexDirection: "column", gap: 0, children: [_jsxs(Box, { gap: 2, marginBottom: 1, children: [_jsx(Text, { bold: true, children: "Memories" }), _jsx(Text, { color: "cyan", children: sessionName }), _jsxs(Text, { dimColor: true, children: ["(", total, " total)"] }), loading && _jsx(Spinner, {})] }), actionMsg && _jsx(Text, { color: "green", children: actionMsg }), error && _jsxs(Text, { color: "red", children: ["Error: ", error] }), memories.length === 0 ? (_jsx(Text, { dimColor: true, children: "No memories stored yet." })) : (_jsx(Box, { flexDirection: "column", height: viewHeight, overflow: "hidden", children: visibleMemories.map((mem, i) => {
472
- const actualIdx = visibleStart + i;
473
- const sel = actualIdx === cursor;
474
- const preview = mem.content.length > 90 ? mem.content.slice(0, 90) + "..." : mem.content;
475
- const date = new Date(mem.createdAt).toLocaleDateString();
476
- return (_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: sel ? "cyan" : undefined, bold: sel, children: sel ? "▶" : " " }), _jsx(Text, { dimColor: true, children: date.padEnd(12) }), _jsx(Text, { color: sel ? "cyan" : undefined, children: preview })] }, mem.id));
477
- }) })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "\u2191\u2193 navigate \u00B7 Enter view \u00B7 a add \u00B7 d delete \u00B7 s search \u00B7 Esc back" }) })] }));
478
- }
479
218
  // ─── Main component ──────────────────────────────────────────────────────────
480
219
  export function SessionList({ serverUrl, password, contentHeight, onSubViewChange }) {
481
220
  const { listSessions, createSession, deleteSession, updateSessionAgent, regenerateCode, getModes, revertToStart, revertAll } = useApi(serverUrl, password);
@@ -585,8 +324,6 @@ export function SessionList({ serverUrl, password, contentHeight, onSubViewChang
585
324
  setSubView("inject");
586
325
  if (input === "m")
587
326
  setSubView("coworker-mail");
588
- if (input === "M")
589
- setSubView("memories");
590
327
  }
591
328
  }
592
329
  if (mode === "creating-pick-mode") {
@@ -824,9 +561,6 @@ export function SessionList({ serverUrl, password, contentHeight, onSubViewChang
824
561
  if (subView === "coworker-mail") {
825
562
  return (_jsx(CoworkerMailView, { serverUrl: serverUrl, password: password, sessionName: activeSession.name, contentHeight: contentHeight, onClose: closeSubView }));
826
563
  }
827
- if (subView === "memories") {
828
- return (_jsx(MemoryView, { serverUrl: serverUrl, password: password, sessionName: activeSession.name, contentHeight: contentHeight, onClose: closeSubView }));
829
- }
830
564
  }
831
565
  // ── Initial load ──────────────────────────────────────────────────────────
832
566
  if (loading && rows.length === 0) {
@@ -55,13 +55,6 @@ export interface CronHistoryEntry {
55
55
  success: boolean;
56
56
  error_message: string | null;
57
57
  }
58
- export interface MemoryRecord {
59
- id: string;
60
- content: string;
61
- metadata: Record<string, unknown>;
62
- createdAt: string;
63
- score?: number;
64
- }
65
58
  export declare function useApi(serverUrl: string, password: string): {
66
59
  listSessions: () => Promise<Session[]>;
67
60
  createSession: (name: string, agent: string) => Promise<Session>;
@@ -123,23 +116,6 @@ export declare function useApi(serverUrl: string, password: string): {
123
116
  enableCron: (id: number) => Promise<CronJob>;
124
117
  disableCron: (id: number) => Promise<CronJob>;
125
118
  getCronHistory: (id: number, limit?: number) => Promise<CronHistoryEntry[]>;
126
- addMemory: (sessionName: string, content: string, metadata?: Record<string, unknown>) => Promise<{
127
- ok: boolean;
128
- id: string;
129
- }>;
130
- listMemories: (sessionName: string, limit?: number) => Promise<{
131
- memories: MemoryRecord[];
132
- total: number;
133
- }>;
134
- getMemory: (sessionName: string, memoryId: string) => Promise<MemoryRecord>;
135
- updateMemory: (sessionName: string, memoryId: string, content: string, metadata?: Record<string, unknown>) => Promise<{
136
- ok: boolean;
137
- }>;
138
- deleteMemory: (sessionName: string, memoryId: string) => Promise<{
139
- deleted: boolean;
140
- id: string;
141
- }>;
142
- searchMemories: (sessionName: string, query: string, limit?: number) => Promise<MemoryRecord[]>;
143
119
  };
144
120
  export declare function useAsyncState<T>(): {
145
121
  run: (fn: () => Promise<T>) => Promise<T | null>;
@@ -115,24 +115,6 @@ export function useApi(serverUrl, password) {
115
115
  const getCronHistory = useCallback(async (id, limit = 10) => {
116
116
  return apiFetch(`${base}/crons/${id}/history?limit=${limit}`, password);
117
117
  }, [base, password]);
118
- const addMemory = useCallback(async (sessionName, content, metadata) => {
119
- return apiFetch(`${base}/sessions/${encodeURIComponent(sessionName)}/memories`, password, { method: "POST", body: JSON.stringify({ content, ...(metadata ? { metadata } : {}) }) });
120
- }, [base, password]);
121
- const listMemories = useCallback(async (sessionName, limit = 50) => {
122
- return apiFetch(`${base}/sessions/${encodeURIComponent(sessionName)}/memories?limit=${limit}`, password);
123
- }, [base, password]);
124
- const getMemory = useCallback(async (sessionName, memoryId) => {
125
- return apiFetch(`${base}/sessions/${encodeURIComponent(sessionName)}/memories/${encodeURIComponent(memoryId)}`, password);
126
- }, [base, password]);
127
- const updateMemory = useCallback(async (sessionName, memoryId, content, metadata) => {
128
- return apiFetch(`${base}/sessions/${encodeURIComponent(sessionName)}/memories/${encodeURIComponent(memoryId)}`, password, { method: "PUT", body: JSON.stringify({ content, ...(metadata ? { metadata } : {}) }) });
129
- }, [base, password]);
130
- const deleteMemory = useCallback(async (sessionName, memoryId) => {
131
- return apiFetch(`${base}/sessions/${encodeURIComponent(sessionName)}/memories/${encodeURIComponent(memoryId)}`, password, { method: "DELETE" });
132
- }, [base, password]);
133
- const searchMemories = useCallback(async (sessionName, query, limit = 10) => {
134
- return apiFetch(`${base}/sessions/${encodeURIComponent(sessionName)}/memories/search`, password, { method: "POST", body: JSON.stringify({ query, limit }) });
135
- }, [base, password]);
136
118
  return {
137
119
  listSessions,
138
120
  createSession,
@@ -156,12 +138,6 @@ export function useApi(serverUrl, password) {
156
138
  enableCron,
157
139
  disableCron,
158
140
  getCronHistory,
159
- addMemory,
160
- listMemories,
161
- getMemory,
162
- updateMemory,
163
- deleteMemory,
164
- searchMemories,
165
141
  };
166
142
  }
167
143
  export function useAsyncState() {
@@ -1,5 +1,4 @@
1
1
  import type { AgentOfficeStorage } from "../db/index.js";
2
2
  import type { AgenticCodingServer } from "../lib/agentic-coding-server.js";
3
3
  import { CronScheduler } from "./cron.js";
4
- import type { AgentOfficeMemory } from "./memory.js";
5
- export declare function createApp(storage: AgentOfficeStorage, agenticCodingServer: AgenticCodingServer, password: string, serverUrl: string, cronScheduler: CronScheduler, memoryManager: AgentOfficeMemory): import("express-serve-static-core").Express;
4
+ export declare function createApp(storage: AgentOfficeStorage, agenticCodingServer: AgenticCodingServer, password: string, serverUrl: string, cronScheduler: CronScheduler): import("express-serve-static-core").Express;
@@ -10,13 +10,13 @@ function authMiddleware(password) {
10
10
  next();
11
11
  };
12
12
  }
13
- export function createApp(storage, agenticCodingServer, password, serverUrl, cronScheduler, memoryManager) {
13
+ export function createApp(storage, agenticCodingServer, password, serverUrl, cronScheduler) {
14
14
  const app = express();
15
15
  app.use(express.json());
16
16
  // Worker routes are unauthenticated — mounted before auth middleware
17
- app.use("/", createWorkerRouter(storage, agenticCodingServer, serverUrl, memoryManager));
17
+ app.use("/", createWorkerRouter(storage, agenticCodingServer, serverUrl));
18
18
  // Everything else requires Bearer auth
19
19
  app.use(authMiddleware(password));
20
- app.use("/", createRouter(storage, agenticCodingServer, serverUrl, cronScheduler, memoryManager));
20
+ app.use("/", createRouter(storage, agenticCodingServer, serverUrl, cronScheduler));
21
21
  return app;
22
22
  }
@@ -2,7 +2,6 @@ import { Router } from "express";
2
2
  import type { AgentOfficeStorage } from "../db/index.js";
3
3
  import type { AgenticCodingServer } from "../lib/agentic-coding-server.js";
4
4
  import { CronScheduler } from "./cron.js";
5
- import type { AgentOfficeMemory } from "./memory.js";
6
5
  /**
7
6
  * Build the persistent system-prompt briefing for a worker session.
8
7
  * This is injected as the `system` field on every `promptAsync` call so the
@@ -10,5 +9,5 @@ import type { AgentOfficeMemory } from "./memory.js";
10
9
  * without consuming a user-message turn.
11
10
  */
12
11
  export declare function generateSystemPrompt(name: string, status: string | null, humanName: string, humanDescription: string, token: string): string;
13
- export declare function createRouter(storage: AgentOfficeStorage, agenticCodingServer: AgenticCodingServer, serverUrl: string, scheduler: CronScheduler, memoryManager: AgentOfficeMemory): Router;
14
- export declare function createWorkerRouter(storage: AgentOfficeStorage, agenticCodingServer: AgenticCodingServer, serverUrl: string, memoryManager: AgentOfficeMemory): Router;
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;