agent-office 0.0.3 → 0.0.6
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/dist/cli.js +59 -0
- package/dist/commands/communicator.d.ts +8 -0
- package/dist/commands/communicator.js +595 -0
- package/dist/commands/serve.d.ts +1 -0
- package/dist/commands/serve.js +18 -1
- package/dist/commands/worker.d.ts +4 -0
- package/dist/commands/worker.js +63 -0
- package/dist/manage/app.js +4 -3
- package/dist/manage/components/SessionList.d.ts +2 -1
- package/dist/manage/components/SessionList.js +309 -2
- package/dist/manage/hooks/useApi.d.ts +33 -0
- package/dist/manage/hooks/useApi.js +28 -0
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.js +3 -3
- package/dist/server/memory.d.ts +64 -0
- package/dist/server/memory.js +214 -0
- package/dist/server/routes.d.ts +3 -2
- package/dist/server/routes.js +347 -32
- package/package.json +4 -1
package/dist/server/routes.js
CHANGED
|
@@ -73,6 +73,24 @@ function generateWelcomeMessage(name, mode, status, humanName, humanDescription,
|
|
|
73
73
|
` agent-office worker cron \\`,
|
|
74
74
|
` ${token}`,
|
|
75
75
|
``,
|
|
76
|
+
` Store a memory (persistent across sessions)`,
|
|
77
|
+
` agent-office worker memory add \\`,
|
|
78
|
+
` --content "your memory here" \\`,
|
|
79
|
+
` ${token}`,
|
|
80
|
+
``,
|
|
81
|
+
` Search your memories`,
|
|
82
|
+
` agent-office worker memory search \\`,
|
|
83
|
+
` --query "your search" \\`,
|
|
84
|
+
` ${token}`,
|
|
85
|
+
``,
|
|
86
|
+
` List all your memories`,
|
|
87
|
+
` agent-office worker memory list \\`,
|
|
88
|
+
` ${token}`,
|
|
89
|
+
``,
|
|
90
|
+
` Forget a memory`,
|
|
91
|
+
` agent-office worker memory forget \\`,
|
|
92
|
+
` ${token} <memory-id>`,
|
|
93
|
+
``,
|
|
76
94
|
`════════════════════════════════════════════════════════`,
|
|
77
95
|
` ⚠ IMPORTANT: YOUR SESSIONS ARE PRIVATE`,
|
|
78
96
|
`════════════════════════════════════════════════════════`,
|
|
@@ -109,7 +127,7 @@ function generateWelcomeMessage(name, mode, status, humanName, humanDescription,
|
|
|
109
127
|
``,
|
|
110
128
|
].join("\n");
|
|
111
129
|
}
|
|
112
|
-
export function createRouter(sql, opencode, serverUrl, scheduler) {
|
|
130
|
+
export function createRouter(sql, opencode, serverUrl, scheduler, memoryManager) {
|
|
113
131
|
const router = Router();
|
|
114
132
|
router.get("/health", (_req, res) => {
|
|
115
133
|
res.json({ ok: true });
|
|
@@ -366,6 +384,47 @@ export function createRouter(sql, opencode, serverUrl, scheduler) {
|
|
|
366
384
|
res.status(502).json({ error: "Failed to revert session", detail: String(err) });
|
|
367
385
|
}
|
|
368
386
|
});
|
|
387
|
+
router.post("/sessions/revert-all", async (_req, res) => {
|
|
388
|
+
const allSessions = await sql `
|
|
389
|
+
SELECT id, name, session_id, agent_code, mode, status, created_at FROM sessions
|
|
390
|
+
`;
|
|
391
|
+
const providers = await opencode.app.providers();
|
|
392
|
+
const defaultEntry = Object.entries(providers.default)[0];
|
|
393
|
+
if (!defaultEntry) {
|
|
394
|
+
res.status(502).json({ error: "No default model configured in OpenCode" });
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
const results = [];
|
|
398
|
+
for (const session of allSessions) {
|
|
399
|
+
try {
|
|
400
|
+
const messages = await opencode.session.messages(session.session_id);
|
|
401
|
+
if (messages.length === 0) {
|
|
402
|
+
results.push({ name: session.name, ok: false, error: "No messages" });
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
const firstMessage = messages[0];
|
|
406
|
+
if (!firstMessage?.info?.id) {
|
|
407
|
+
results.push({ name: session.name, ok: false, error: "Failed to get first message ID" });
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
await opencode.session.revert(session.session_id, { messageID: firstMessage.info.id });
|
|
411
|
+
const clockInToken = `${session.agent_code}@${serverUrl}`;
|
|
412
|
+
const enrollmentMessage = `You have been enrolled in the agent office.\n\nTo clock in and receive your full briefing, run:\n\n agent-office worker clock-in ${clockInToken}`;
|
|
413
|
+
await opencode.session.chat(session.session_id, {
|
|
414
|
+
modelID: defaultEntry[0],
|
|
415
|
+
providerID: defaultEntry[1],
|
|
416
|
+
parts: [{ type: "text", text: enrollmentMessage }],
|
|
417
|
+
});
|
|
418
|
+
results.push({ name: session.name, ok: true });
|
|
419
|
+
}
|
|
420
|
+
catch (err) {
|
|
421
|
+
console.error(`POST /sessions/revert-all error for "${session.name}":`, err);
|
|
422
|
+
results.push({ name: session.name, ok: false, error: String(err) });
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
const failed = results.filter((r) => !r.ok);
|
|
426
|
+
res.json({ ok: failed.length === 0, total: allSessions.length, results });
|
|
427
|
+
});
|
|
369
428
|
router.delete("/sessions/:name", async (req, res) => {
|
|
370
429
|
const { name } = req.params;
|
|
371
430
|
const rows = await sql `
|
|
@@ -500,33 +559,34 @@ export function createRouter(sql, opencode, serverUrl, scheduler) {
|
|
|
500
559
|
res.status(400).json({ error: "No valid recipients found" });
|
|
501
560
|
return;
|
|
502
561
|
}
|
|
562
|
+
const providers = await opencode.app.providers();
|
|
563
|
+
const defaultEntry = Object.entries(providers.default)[0];
|
|
503
564
|
const results = [];
|
|
504
565
|
for (const recipient of validRecipients) {
|
|
505
|
-
let injected = false;
|
|
506
566
|
const [msgRow] = await sql `
|
|
507
567
|
INSERT INTO messages (from_name, to_name, body)
|
|
508
568
|
VALUES (${trimmedFrom}, ${recipient}, ${trimmedBody})
|
|
509
569
|
RETURNING id, from_name, to_name, body, read, injected, created_at
|
|
510
570
|
`;
|
|
511
|
-
|
|
571
|
+
const msgId = msgRow.id;
|
|
572
|
+
let injected = false;
|
|
573
|
+
if (sessionMap.has(recipient) && defaultEntry) {
|
|
512
574
|
const sessionId = sessionMap.get(recipient);
|
|
513
|
-
const
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
const defaultEntry = Object.entries(providers.default)[0];
|
|
517
|
-
if (!defaultEntry)
|
|
518
|
-
return;
|
|
519
|
-
const injectText = `[Message from "${trimmedFrom}"]: ${trimmedBody}${MAIL_INJECTION_BLURB}`;
|
|
520
|
-
return opencode.session.chat(sessionId, {
|
|
575
|
+
const injectText = `[Message from "${trimmedFrom}"]: ${trimmedBody}${MAIL_INJECTION_BLURB}`;
|
|
576
|
+
try {
|
|
577
|
+
await opencode.session.chat(sessionId, {
|
|
521
578
|
modelID: defaultEntry[0],
|
|
522
579
|
providerID: defaultEntry[1],
|
|
523
580
|
parts: [{ type: "text", text: injectText }],
|
|
524
|
-
})
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
}
|
|
581
|
+
});
|
|
582
|
+
await sql `UPDATE messages SET injected = TRUE WHERE id = ${msgId}`;
|
|
583
|
+
injected = true;
|
|
584
|
+
}
|
|
585
|
+
catch (err) {
|
|
586
|
+
console.warn(`Warning: could not inject message into session "${recipient}":`, err);
|
|
587
|
+
}
|
|
528
588
|
}
|
|
529
|
-
results.push({ to: recipient, messageId:
|
|
589
|
+
results.push({ to: recipient, messageId: msgId, injected });
|
|
530
590
|
}
|
|
531
591
|
res.status(201).json({ ok: true, results });
|
|
532
592
|
});
|
|
@@ -799,9 +859,135 @@ export function createRouter(sql, opencode, serverUrl, scheduler) {
|
|
|
799
859
|
res.status(500).json({ error: "Internal server error" });
|
|
800
860
|
}
|
|
801
861
|
});
|
|
862
|
+
// ── Memory Endpoints (authenticated, for manage TUI) ───────────────────────
|
|
863
|
+
router.get("/sessions/:name/memories", async (req, res) => {
|
|
864
|
+
const { name } = req.params;
|
|
865
|
+
const limit = Math.min(parseInt(req.query.limit ?? "50", 10), 200);
|
|
866
|
+
const rows = await sql `SELECT id FROM sessions WHERE name = ${name}`;
|
|
867
|
+
if (rows.length === 0) {
|
|
868
|
+
res.status(404).json({ error: `Session "${name}" not found` });
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
try {
|
|
872
|
+
const memories = memoryManager.listMemories(name, limit);
|
|
873
|
+
const stats = memoryManager.getStats(name);
|
|
874
|
+
res.json({ memories, total: stats.total });
|
|
875
|
+
}
|
|
876
|
+
catch (err) {
|
|
877
|
+
console.error("GET /sessions/:name/memories error:", err);
|
|
878
|
+
res.status(500).json({ error: "Internal server error" });
|
|
879
|
+
}
|
|
880
|
+
});
|
|
881
|
+
router.post("/sessions/:name/memories", async (req, res) => {
|
|
882
|
+
const { name } = req.params;
|
|
883
|
+
const { content, metadata } = req.body;
|
|
884
|
+
if (!content || typeof content !== "string" || !content.trim()) {
|
|
885
|
+
res.status(400).json({ error: "content is required" });
|
|
886
|
+
return;
|
|
887
|
+
}
|
|
888
|
+
const rows = await sql `SELECT id FROM sessions WHERE name = ${name}`;
|
|
889
|
+
if (rows.length === 0) {
|
|
890
|
+
res.status(404).json({ error: `Session "${name}" not found` });
|
|
891
|
+
return;
|
|
892
|
+
}
|
|
893
|
+
try {
|
|
894
|
+
const id = await memoryManager.addMemory(name, content.trim(), metadata ?? {});
|
|
895
|
+
res.status(201).json({ ok: true, id });
|
|
896
|
+
}
|
|
897
|
+
catch (err) {
|
|
898
|
+
console.error("POST /sessions/:name/memories error:", err);
|
|
899
|
+
res.status(500).json({ error: "Internal server error" });
|
|
900
|
+
}
|
|
901
|
+
});
|
|
902
|
+
router.get("/sessions/:name/memories/:memoryId", async (req, res) => {
|
|
903
|
+
const { name, memoryId } = req.params;
|
|
904
|
+
const rows = await sql `SELECT id FROM sessions WHERE name = ${name}`;
|
|
905
|
+
if (rows.length === 0) {
|
|
906
|
+
res.status(404).json({ error: `Session "${name}" not found` });
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
try {
|
|
910
|
+
const memory = memoryManager.getMemory(name, memoryId);
|
|
911
|
+
if (!memory) {
|
|
912
|
+
res.status(404).json({ error: "Memory not found" });
|
|
913
|
+
return;
|
|
914
|
+
}
|
|
915
|
+
res.json(memory);
|
|
916
|
+
}
|
|
917
|
+
catch (err) {
|
|
918
|
+
console.error("GET /sessions/:name/memories/:memoryId error:", err);
|
|
919
|
+
res.status(500).json({ error: "Internal server error" });
|
|
920
|
+
}
|
|
921
|
+
});
|
|
922
|
+
router.put("/sessions/:name/memories/:memoryId", async (req, res) => {
|
|
923
|
+
const { name, memoryId } = req.params;
|
|
924
|
+
const { content, metadata } = req.body;
|
|
925
|
+
if (!content || typeof content !== "string" || !content.trim()) {
|
|
926
|
+
res.status(400).json({ error: "content is required" });
|
|
927
|
+
return;
|
|
928
|
+
}
|
|
929
|
+
const rows = await sql `SELECT id FROM sessions WHERE name = ${name}`;
|
|
930
|
+
if (rows.length === 0) {
|
|
931
|
+
res.status(404).json({ error: `Session "${name}" not found` });
|
|
932
|
+
return;
|
|
933
|
+
}
|
|
934
|
+
try {
|
|
935
|
+
const updated = await memoryManager.updateMemory(name, memoryId, content.trim(), metadata);
|
|
936
|
+
if (!updated) {
|
|
937
|
+
res.status(404).json({ error: "Memory not found" });
|
|
938
|
+
return;
|
|
939
|
+
}
|
|
940
|
+
res.json({ ok: true });
|
|
941
|
+
}
|
|
942
|
+
catch (err) {
|
|
943
|
+
console.error("PUT /sessions/:name/memories/:memoryId error:", err);
|
|
944
|
+
res.status(500).json({ error: "Internal server error" });
|
|
945
|
+
}
|
|
946
|
+
});
|
|
947
|
+
router.delete("/sessions/:name/memories/:memoryId", async (req, res) => {
|
|
948
|
+
const { name, memoryId } = req.params;
|
|
949
|
+
const rows = await sql `SELECT id FROM sessions WHERE name = ${name}`;
|
|
950
|
+
if (rows.length === 0) {
|
|
951
|
+
res.status(404).json({ error: `Session "${name}" not found` });
|
|
952
|
+
return;
|
|
953
|
+
}
|
|
954
|
+
try {
|
|
955
|
+
const deleted = memoryManager.deleteMemory(name, memoryId);
|
|
956
|
+
if (!deleted) {
|
|
957
|
+
res.status(404).json({ error: "Memory not found" });
|
|
958
|
+
return;
|
|
959
|
+
}
|
|
960
|
+
res.json({ deleted: true, id: memoryId });
|
|
961
|
+
}
|
|
962
|
+
catch (err) {
|
|
963
|
+
console.error("DELETE /sessions/:name/memories/:memoryId error:", err);
|
|
964
|
+
res.status(500).json({ error: "Internal server error" });
|
|
965
|
+
}
|
|
966
|
+
});
|
|
967
|
+
router.post("/sessions/:name/memories/search", async (req, res) => {
|
|
968
|
+
const { name } = req.params;
|
|
969
|
+
const { query, limit } = req.body;
|
|
970
|
+
if (!query || typeof query !== "string" || !query.trim()) {
|
|
971
|
+
res.status(400).json({ error: "query is required" });
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
const rows = await sql `SELECT id FROM sessions WHERE name = ${name}`;
|
|
975
|
+
if (rows.length === 0) {
|
|
976
|
+
res.status(404).json({ error: `Session "${name}" not found` });
|
|
977
|
+
return;
|
|
978
|
+
}
|
|
979
|
+
try {
|
|
980
|
+
const results = await memoryManager.searchMemories(name, query.trim(), Math.min(limit ?? 10, 50));
|
|
981
|
+
res.json(results);
|
|
982
|
+
}
|
|
983
|
+
catch (err) {
|
|
984
|
+
console.error("POST /sessions/:name/memories/search error:", err);
|
|
985
|
+
res.status(500).json({ error: "Internal server error" });
|
|
986
|
+
}
|
|
987
|
+
});
|
|
802
988
|
return router;
|
|
803
989
|
}
|
|
804
|
-
export function createWorkerRouter(sql, opencode, serverUrl) {
|
|
990
|
+
export function createWorkerRouter(sql, opencode, serverUrl, memoryManager) {
|
|
805
991
|
const router = Router();
|
|
806
992
|
router.get("/worker/clock-in", async (req, res) => {
|
|
807
993
|
const { code } = req.query;
|
|
@@ -870,6 +1056,24 @@ export function createWorkerRouter(sql, opencode, serverUrl) {
|
|
|
870
1056
|
` agent-office worker cron \\`,
|
|
871
1057
|
` ${token}`,
|
|
872
1058
|
``,
|
|
1059
|
+
` Store a memory (persistent across sessions)`,
|
|
1060
|
+
` agent-office worker memory add \\`,
|
|
1061
|
+
` --content "your memory here" \\`,
|
|
1062
|
+
` ${token}`,
|
|
1063
|
+
``,
|
|
1064
|
+
` Search your memories`,
|
|
1065
|
+
` agent-office worker memory search \\`,
|
|
1066
|
+
` --query "your search" \\`,
|
|
1067
|
+
` ${token}`,
|
|
1068
|
+
``,
|
|
1069
|
+
` List all your memories`,
|
|
1070
|
+
` agent-office worker memory list \\`,
|
|
1071
|
+
` ${token}`,
|
|
1072
|
+
``,
|
|
1073
|
+
` Forget a memory`,
|
|
1074
|
+
` agent-office worker memory forget \\`,
|
|
1075
|
+
` ${token} <memory-id>`,
|
|
1076
|
+
``,
|
|
873
1077
|
`════════════════════════════════════════════════════════`,
|
|
874
1078
|
` ⚠ IMPORTANT: YOUR SESSIONS ARE PRIVATE`,
|
|
875
1079
|
`════════════════════════════════════════════════════════`,
|
|
@@ -1020,33 +1224,34 @@ export function createWorkerRouter(sql, opencode, serverUrl) {
|
|
|
1020
1224
|
res.status(400).json({ error: "No valid recipients found" });
|
|
1021
1225
|
return;
|
|
1022
1226
|
}
|
|
1227
|
+
const providers = await opencode.app.providers();
|
|
1228
|
+
const defaultEntry = Object.entries(providers.default)[0];
|
|
1023
1229
|
const results = [];
|
|
1024
1230
|
for (const recipient of validRecipients) {
|
|
1025
|
-
let injected = false;
|
|
1026
1231
|
const [msgRow] = await sql `
|
|
1027
1232
|
INSERT INTO messages (from_name, to_name, body)
|
|
1028
1233
|
VALUES (${session.name}, ${recipient}, ${trimmedBody})
|
|
1029
1234
|
RETURNING id, from_name, to_name, body, read, injected, created_at
|
|
1030
1235
|
`;
|
|
1031
|
-
|
|
1236
|
+
const msgId = msgRow.id;
|
|
1237
|
+
let injected = false;
|
|
1238
|
+
if (sessionMap.has(recipient) && defaultEntry) {
|
|
1032
1239
|
const recipientSessionId = sessionMap.get(recipient);
|
|
1033
|
-
const
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
const defaultEntry = Object.entries(providers.default)[0];
|
|
1037
|
-
if (!defaultEntry)
|
|
1038
|
-
return;
|
|
1039
|
-
const injectText = `[Message from "${session.name}"]: ${trimmedBody}${MAIL_INJECTION_BLURB}`;
|
|
1040
|
-
return opencode.session.chat(recipientSessionId, {
|
|
1240
|
+
const injectText = `[Message from "${session.name}"]: ${trimmedBody}${MAIL_INJECTION_BLURB}`;
|
|
1241
|
+
try {
|
|
1242
|
+
await opencode.session.chat(recipientSessionId, {
|
|
1041
1243
|
modelID: defaultEntry[0],
|
|
1042
1244
|
providerID: defaultEntry[1],
|
|
1043
1245
|
parts: [{ type: "text", text: injectText }],
|
|
1044
|
-
})
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
}
|
|
1246
|
+
});
|
|
1247
|
+
await sql `UPDATE messages SET injected = TRUE WHERE id = ${msgId}`;
|
|
1248
|
+
injected = true;
|
|
1249
|
+
}
|
|
1250
|
+
catch (err) {
|
|
1251
|
+
console.warn(`Warning: could not inject message into session "${recipient}":`, err);
|
|
1252
|
+
}
|
|
1048
1253
|
}
|
|
1049
|
-
results.push({ to: recipient, messageId:
|
|
1254
|
+
results.push({ to: recipient, messageId: msgId, injected });
|
|
1050
1255
|
}
|
|
1051
1256
|
res.status(201).json({ ok: true, results });
|
|
1052
1257
|
});
|
|
@@ -1370,5 +1575,115 @@ export function createWorkerRouter(sql, opencode, serverUrl) {
|
|
|
1370
1575
|
res.status(500).json({ error: "Internal server error" });
|
|
1371
1576
|
}
|
|
1372
1577
|
});
|
|
1578
|
+
// ── Worker Memory Endpoints (authenticated via agent_code in query) ────────
|
|
1579
|
+
router.post("/worker/memory/add", async (req, res) => {
|
|
1580
|
+
const { code } = req.query;
|
|
1581
|
+
const { content, metadata } = req.body;
|
|
1582
|
+
if (!code || typeof code !== "string") {
|
|
1583
|
+
res.status(400).json({ error: "code query parameter is required" });
|
|
1584
|
+
return;
|
|
1585
|
+
}
|
|
1586
|
+
if (!content || typeof content !== "string" || !content.trim()) {
|
|
1587
|
+
res.status(400).json({ error: "content is required" });
|
|
1588
|
+
return;
|
|
1589
|
+
}
|
|
1590
|
+
const session = await sql `
|
|
1591
|
+
SELECT name FROM sessions WHERE agent_code = ${code}
|
|
1592
|
+
`;
|
|
1593
|
+
if (session.length === 0) {
|
|
1594
|
+
res.status(401).json({ error: "Invalid agent code" });
|
|
1595
|
+
return;
|
|
1596
|
+
}
|
|
1597
|
+
const sessionName = session[0].name;
|
|
1598
|
+
try {
|
|
1599
|
+
const id = await memoryManager.addMemory(sessionName, content.trim(), metadata ?? {});
|
|
1600
|
+
res.status(201).json({ ok: true, id });
|
|
1601
|
+
}
|
|
1602
|
+
catch (err) {
|
|
1603
|
+
console.error("POST /worker/memory/add error:", err);
|
|
1604
|
+
res.status(500).json({ error: "Internal server error" });
|
|
1605
|
+
}
|
|
1606
|
+
});
|
|
1607
|
+
router.post("/worker/memory/search", async (req, res) => {
|
|
1608
|
+
const { code } = req.query;
|
|
1609
|
+
const { query, limit } = req.body;
|
|
1610
|
+
if (!code || typeof code !== "string") {
|
|
1611
|
+
res.status(400).json({ error: "code query parameter is required" });
|
|
1612
|
+
return;
|
|
1613
|
+
}
|
|
1614
|
+
if (!query || typeof query !== "string" || !query.trim()) {
|
|
1615
|
+
res.status(400).json({ error: "query is required" });
|
|
1616
|
+
return;
|
|
1617
|
+
}
|
|
1618
|
+
const session = await sql `
|
|
1619
|
+
SELECT name FROM sessions WHERE agent_code = ${code}
|
|
1620
|
+
`;
|
|
1621
|
+
if (session.length === 0) {
|
|
1622
|
+
res.status(401).json({ error: "Invalid agent code" });
|
|
1623
|
+
return;
|
|
1624
|
+
}
|
|
1625
|
+
const sessionName = session[0].name;
|
|
1626
|
+
try {
|
|
1627
|
+
const results = await memoryManager.searchMemories(sessionName, query.trim(), Math.min(limit ?? 10, 50));
|
|
1628
|
+
res.json(results);
|
|
1629
|
+
}
|
|
1630
|
+
catch (err) {
|
|
1631
|
+
console.error("POST /worker/memory/search error:", err);
|
|
1632
|
+
res.status(500).json({ error: "Internal server error" });
|
|
1633
|
+
}
|
|
1634
|
+
});
|
|
1635
|
+
router.get("/worker/memory/list", async (req, res) => {
|
|
1636
|
+
const { code, limit: limitStr } = req.query;
|
|
1637
|
+
if (!code || typeof code !== "string") {
|
|
1638
|
+
res.status(400).json({ error: "code query parameter is required" });
|
|
1639
|
+
return;
|
|
1640
|
+
}
|
|
1641
|
+
const session = await sql `
|
|
1642
|
+
SELECT name FROM sessions WHERE agent_code = ${code}
|
|
1643
|
+
`;
|
|
1644
|
+
if (session.length === 0) {
|
|
1645
|
+
res.status(401).json({ error: "Invalid agent code" });
|
|
1646
|
+
return;
|
|
1647
|
+
}
|
|
1648
|
+
const sessionName = session[0].name;
|
|
1649
|
+
const limit = Math.min(parseInt(limitStr ?? "50", 10), 200);
|
|
1650
|
+
try {
|
|
1651
|
+
const memories = memoryManager.listMemories(sessionName, limit);
|
|
1652
|
+
const stats = memoryManager.getStats(sessionName);
|
|
1653
|
+
res.json({ memories, total: stats.total });
|
|
1654
|
+
}
|
|
1655
|
+
catch (err) {
|
|
1656
|
+
console.error("GET /worker/memory/list error:", err);
|
|
1657
|
+
res.status(500).json({ error: "Internal server error" });
|
|
1658
|
+
}
|
|
1659
|
+
});
|
|
1660
|
+
router.delete("/worker/memory/:memoryId", async (req, res) => {
|
|
1661
|
+
const { code } = req.query;
|
|
1662
|
+
const { memoryId } = req.params;
|
|
1663
|
+
if (!code || typeof code !== "string") {
|
|
1664
|
+
res.status(400).json({ error: "code query parameter is required" });
|
|
1665
|
+
return;
|
|
1666
|
+
}
|
|
1667
|
+
const session = await sql `
|
|
1668
|
+
SELECT name FROM sessions WHERE agent_code = ${code}
|
|
1669
|
+
`;
|
|
1670
|
+
if (session.length === 0) {
|
|
1671
|
+
res.status(401).json({ error: "Invalid agent code" });
|
|
1672
|
+
return;
|
|
1673
|
+
}
|
|
1674
|
+
const sessionName = session[0].name;
|
|
1675
|
+
try {
|
|
1676
|
+
const deleted = memoryManager.deleteMemory(sessionName, memoryId);
|
|
1677
|
+
if (!deleted) {
|
|
1678
|
+
res.status(404).json({ error: "Memory not found" });
|
|
1679
|
+
return;
|
|
1680
|
+
}
|
|
1681
|
+
res.json({ deleted: true, id: memoryId });
|
|
1682
|
+
}
|
|
1683
|
+
catch (err) {
|
|
1684
|
+
console.error("DELETE /worker/memory/:memoryId error:", err);
|
|
1685
|
+
res.status(500).json({ error: "Internal server error" });
|
|
1686
|
+
}
|
|
1687
|
+
});
|
|
1373
1688
|
return router;
|
|
1374
1689
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-office",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "Manage OpenCode sessions with named aliases",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"dev:serve": "tsx --watch src/cli.ts serve",
|
|
24
24
|
"dev:manage": "tsx src/cli.ts manage",
|
|
25
25
|
"dev:worker": "tsx src/cli.ts worker",
|
|
26
|
+
"dev:communicator": "tsx src/cli.ts communicator web",
|
|
26
27
|
"build": "tsc",
|
|
27
28
|
"clean": "rm -rf dist",
|
|
28
29
|
"prepublishOnly": "npm run clean && npm run build"
|
|
@@ -38,11 +39,13 @@
|
|
|
38
39
|
"croner": "^10.0.1",
|
|
39
40
|
"dotenv": "^16.0.0",
|
|
40
41
|
"express": "^4.18.0",
|
|
42
|
+
"fastmemory": "^0.1.5",
|
|
41
43
|
"ink": "^5.0.0",
|
|
42
44
|
"postgres": "^3.4.0",
|
|
43
45
|
"react": "^18.0.0"
|
|
44
46
|
},
|
|
45
47
|
"devDependencies": {
|
|
48
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
46
49
|
"@types/express": "^4.17.0",
|
|
47
50
|
"@types/node": "^20.0.0",
|
|
48
51
|
"@types/react": "^18.0.0",
|