From 402e88b788e03ce8a41e2fee7d477a5a8f6249d5 Mon Sep 17 00:00:00 2001 From: Sepehr Ramezani Date: Sun, 19 Apr 2026 23:01:04 +0200 Subject: [PATCH] feat(ux): epic UX design improvements across agents, chat, notes, and i18n Comprehensive UI/UX updates including agent card redesign, chat container improvements, note editor enhancements, memory echo notifications, and updated translations for all 15 locales. Co-Authored-By: Claude Opus 4.5 --- .../console-2026-04-19T18-53-32-857Z.log | 47 ++++ .../page-2026-04-19T18-53-33-247Z.yml | 21 ++ .../app/(main)/agents/agents-page-client.tsx | 18 +- keep-notes/app/(main)/agents/page.tsx | 2 +- keep-notes/app/(main)/chat/page.tsx | 18 +- keep-notes/app/actions/notes.ts | 16 +- keep-notes/app/api/chat/route.ts | 97 +++++++- keep-notes/components/agents/agent-card.tsx | 34 +-- keep-notes/components/agents/agent-form.tsx | 104 +++++---- .../components/agents/agent-run-log.tsx | 38 ++-- keep-notes/components/chat/chat-container.tsx | 19 +- keep-notes/components/chat/chat-input.tsx | 29 ++- keep-notes/components/comparison-modal.tsx | 10 +- keep-notes/components/connections-overlay.tsx | 2 +- keep-notes/components/fusion-modal.tsx | 34 ++- .../components/memory-echo-notification.tsx | 1 + keep-notes/components/note-card.tsx | 16 ++ keep-notes/components/note-editor.tsx | 1 + keep-notes/components/note-inline-editor.tsx | 215 ++++-------------- .../lib/ai/services/agent-executor.service.ts | 2 +- keep-notes/lib/ai/tools/note-search.tool.ts | 6 +- keep-notes/lib/ai/tools/registry.ts | 30 ++- keep-notes/lib/types.ts | 1 + keep-notes/lib/utils.ts | 5 +- keep-notes/locales/ar.json | 3 +- keep-notes/locales/de.json | 3 +- keep-notes/locales/en.json | 3 +- keep-notes/locales/es.json | 3 +- keep-notes/locales/fa.json | 3 +- keep-notes/locales/fr.json | 3 +- keep-notes/locales/hi.json | 3 +- keep-notes/locales/it.json | 3 +- keep-notes/locales/ja.json | 3 +- keep-notes/locales/ko.json | 3 +- keep-notes/locales/nl.json | 3 +- keep-notes/locales/pl.json | 3 +- keep-notes/locales/pt.json | 3 +- keep-notes/locales/ru.json | 3 +- keep-notes/locales/zh.json | 3 +- keep-notes/prisma/dev.db | Bin 14553088 -> 15462400 bytes .../01ccf206-307f-42a4-b9b1-d1023233d28d.jpg | Bin 0 -> 41780 bytes .../03822d48-3e40-4c23-a4d4-b22d57fd0aa4.jpg | Bin 0 -> 262341 bytes .../05110cea-1c8e-40d0-94e2-69af4666e494.jpg | Bin 0 -> 13690 bytes .../05ac9d60-79d8-4444-94e3-ab5e0ef21d6b.jpg | Bin 0 -> 13541 bytes .../071d9a1d-7272-45bf-999e-a803943bc789.jpg | Bin 0 -> 20205 bytes .../0865a0cb-c7d4-42d3-9ce9-35a4a560eb21.jpg | Bin 0 -> 46678 bytes .../0a88ace8-d9ac-4ef6-b75e-b7e1bf92243e.jpg | Bin 0 -> 33818 bytes .../0b7899d5-7225-4cb7-b664-41ecfdc43c6d.jpg | Bin 0 -> 11071 bytes .../0d3f41e4-e011-4ecc-951d-5336013cbd9b.jpg | Bin 0 -> 43832 bytes .../0d57e021-4b11-46c4-b789-25e0abc22cb1.jpg | Bin 0 -> 12352 bytes .../0f0529bf-afd3-4181-8ddc-d9eafbcb61d8.png | Bin 0 -> 67970 bytes .../11180abd-29e8-4ec7-8d7b-93eae56c1658.png | Bin 0 -> 67970 bytes .../11619703-0505-4419-b9ca-ff2c6db5667b.png | Bin 0 -> 33573 bytes .../116b00e6-1bb1-4b83-9cab-7b19993ea7b2.jpg | Bin 0 -> 13690 bytes ...e13ec2-048a-4005-9339-4d2309c87451.svg+xml | Bin 0 -> 55975 bytes .../17b55a0f-ba7f-4e0b-8b22-18c242032c82.jpg | Bin 0 -> 17967 bytes .../19756abd-f675-444e-b1ef-3fe1480d6ff8.jpg | Bin 0 -> 8937 bytes .../1a79dbd0-8d2c-407d-ab1d-603ffff1e08a.png | Bin 0 -> 16896 bytes .../1b2040ac-ccd2-4a20-867e-3b6917c653f7.jpg | Bin 0 -> 34305 bytes .../1b8a904e-8666-4bce-b68b-21900f638c41.jpg | Bin 0 -> 20205 bytes .../1c34e3c9-736c-4f61-8dcb-0e26a506accf.jpg | Bin 0 -> 438894 bytes .../1eb77279-1461-4bc6-b5aa-178035816f10.jpg | Bin 0 -> 52264 bytes .../1f5da0e0-5708-4419-a118-f8538315c3f6.jpg | Bin 0 -> 21768 bytes .../20308091-4065-4954-bae5-d2ebdd69377f.jpg | Bin 0 -> 33818 bytes .../204e0948-eb67-42dd-b3ba-ba2a1ebae04e.jpg | Bin 0 -> 20205 bytes .../22e5b674-4438-457f-bdf0-e6923fc767cf.jpg | Bin 0 -> 12352 bytes .../25837174-8265-44f7-b5bc-1727a2fd0287.jpg | Bin 0 -> 33487 bytes .../259c6d8d-3c88-429b-ba0c-466bc9e2c4a0.jpg | Bin 0 -> 12352 bytes .../2b1809ab-63a8-4f07-aacd-d5d94cb80557.jpg | Bin 0 -> 23030 bytes .../2b92618f-eb55-479b-ad3b-e6fc604114cd.jpg | Bin 0 -> 46205 bytes .../2bfceecb-571e-42dd-8204-2a5d1e2caa84.jpg | Bin 0 -> 107147 bytes .../2ce7f626-2fbd-446a-bc3e-f2dd18d921ed.jpg | Bin 0 -> 91593 bytes .../2e92b91c-9e0f-4fb4-9130-79acbf2a60b6.jpg | Bin 0 -> 36122 bytes .../2f2cff2f-d308-406a-b56c-97c581fcf521.jpg | Bin 0 -> 12668 bytes .../31492c72-8c12-4088-8b17-e305ea38aad0.jpg | Bin 0 -> 19534 bytes .../31861780-9135-4865-866f-9da859e6fcf4.jpg | Bin 0 -> 18614 bytes .../36363ef8-4e60-4c4e-b2a9-4194281d1486.jpg | Bin 0 -> 12668 bytes .../36a78f8f-2712-49cf-9080-bf808984d840.jpg | Bin 0 -> 12352 bytes .../391e5c59-b722-48dd-adae-9629f3fe54c6.jpg | Bin 0 -> 17967 bytes .../39643a60-83ad-4dbb-8ff1-bd5557557b59.jpg | Bin 0 -> 262341 bytes .../3c34ebdf-2b38-4083-8948-839758260537.jpg | Bin 0 -> 13690 bytes .../411cd01a-a8ec-4386-ad48-cdddf8ca328a.jpg | Bin 0 -> 33487 bytes .../43c79de0-4fbb-420e-b979-3a477ef1fecf.jpg | Bin 0 -> 35929 bytes .../43f3fe0f-58e6-4077-a05e-26a7b6b82427.jpg | Bin 0 -> 422640 bytes .../45f68bd2-61f4-4e60-8216-ce04a03259e7.jpg | Bin 0 -> 23030 bytes .../46627bf2-42fc-466c-8180-b4c09b2690ee.jpg | Bin 0 -> 21768 bytes .../46837c2f-b5cd-4e10-8cd6-fc26a2359b28.jpg | Bin 0 -> 2038 bytes .../46bd4472-1bb3-4257-9ee2-fb2db0730e0d.png | Bin 0 -> 67970 bytes .../46c281dc-e5db-46df-a381-8e432be2dd29.jpg | Bin 0 -> 13541 bytes .../470075b4-2df8-402e-8bd4-d450293ea755.jpg | Bin 0 -> 17967 bytes .../47252485-3f63-41c3-b7f7-baa3b5fdbef9.jpg | Bin 0 -> 12191 bytes .../49ed661a-9e5f-4d8e-9b8d-0f0ff70488ce.jpg | Bin 0 -> 34766 bytes .../4b85cf3e-6af6-4ae2-8883-20d4539ec211.jpg | Bin 0 -> 54583 bytes .../4bdee09e-ec1c-408e-8161-cc4a2b931034.jpg | Bin 0 -> 23030 bytes .../4f942e8b-982a-4aed-8e31-86053fea5901.jpg | Bin 0 -> 17967 bytes .../5094a78f-1966-4f7e-a249-b2b8c1645d69.jpg | Bin 0 -> 37430 bytes .../565e9a07-cfff-4538-baf0-c9e074c0e390.jpg | Bin 0 -> 21768 bytes .../56829cb4-35e9-4a64-a68e-0f395d1093fc.jpg | Bin 0 -> 12352 bytes .../59ad3b52-40f7-4c29-a2bf-39e44fb760bf.jpg | Bin 0 -> 12352 bytes .../5d15d215-1055-4ad8-8d9e-50df93ebe795.jpg | Bin 0 -> 43832 bytes .../5e0a9ac1-241c-4411-bc2a-eadbe59efb5d.jpg | Bin 0 -> 36122 bytes .../61035308-b29f-47ce-999f-533d4ddd6ee7.jpg | Bin 0 -> 51039 bytes .../62b1807b-1b5e-423f-aaff-db62eba1af83.jpg | Bin 0 -> 56456 bytes .../649474f3-67a6-4c3e-8748-fd11601f6cf7.jpg | Bin 0 -> 20649 bytes .../64ebca73-4447-49db-8be2-6840fbc6e6c8.jpg | Bin 0 -> 12668 bytes .../667c275b-eb75-4d07-a435-0349189a26cc.jpg | Bin 0 -> 12668 bytes .../668dd2f6-44bc-4198-a112-a407d47b7ed1.jpg | Bin 0 -> 43832 bytes .../66af52fb-6fab-4230-847c-eb65e902d069.jpg | Bin 0 -> 262341 bytes .../67f0b83b-786e-4067-a7fa-d31cfc7aa197.jpg | Bin 0 -> 56456 bytes .../6a89a8f1-9f5f-46a7-a3f2-e6b958a99bfa.jpg | Bin 0 -> 13690 bytes .../6e2b0161-0eed-4c40-a330-1d02fbcc6b27.jpg | Bin 0 -> 20205 bytes .../6fe5fc87-23f7-4ca3-809b-132eefb1cd4f.jpg | Bin 0 -> 12191 bytes .../76dd7f14-5147-4286-93f3-a71f31388ff3.jpg | Bin 0 -> 12668 bytes .../7b345722-6871-4fea-a594-036c2d93f84d.jpg | Bin 0 -> 13690 bytes .../7bbce240-2d98-414c-bf7a-12ff5061cedc.jpg | Bin 0 -> 21768 bytes .../7e473396-1d4e-4117-9f22-9ba991aac022.jpg | Bin 0 -> 30653 bytes .../8298565f-d601-4cf8-8bf7-48394227dec1.jpg | Bin 0 -> 16148 bytes .../8884588d-f8ea-4c59-a2a2-a943895b36dc.jpg | Bin 0 -> 21768 bytes .../88aadb89-8c27-481d-b89d-286d86f9f78c.jpg | Bin 0 -> 21768 bytes .../8e3fb875-7cbe-4d57-8e55-35049d698b78.png | Bin 0 -> 67970 bytes .../8e6d6dfb-aad5-4836-bf95-2bda6fc42baf.jpg | Bin 0 -> 58486 bytes .../8efbf2bd-6d3d-4946-bb81-03e0e0c1a821.jpg | Bin 0 -> 12668 bytes .../8efc141f-9f20-4b94-aa3d-434ea3784593.jpg | Bin 0 -> 11071 bytes .../8fc39197-1e00-4d96-81bf-2d9970ba5091.jpg | Bin 0 -> 24210 bytes .../93155e47-7670-4b01-aeaa-c26e7b6198eb.jpg | Bin 0 -> 53882 bytes .../93890ccc-ffb4-482d-bc69-e5d922bdfb2b.jpg | Bin 0 -> 56456 bytes .../9472f539-b92b-4f1c-aa60-322c4c1ea028.jpg | Bin 0 -> 19534 bytes .../94eb60bd-e693-4a09-9429-6820711f3a7c.jpg | Bin 0 -> 11723 bytes .../95247436-954c-4f6a-8b02-c509abed55d8.jpg | Bin 0 -> 12191 bytes .../9599029c-b1ed-40fc-a303-67fdf447fde2.jpg | Bin 0 -> 86607 bytes .../96e66b66-70e2-45f9-9eea-d31c1fdc809e.jpg | Bin 0 -> 107147 bytes .../96fb2f00-f09c-44a0-91d4-3eb2dcd4a08d.jpg | Bin 0 -> 17967 bytes .../981c7050-a763-4b82-a83b-2ef8636cbd1a.jpg | Bin 0 -> 20205 bytes .../997ccca7-f68d-4fdc-8588-9d0dcbb173ba.jpg | Bin 0 -> 21768 bytes .../9a1d36c1-7fcc-4c43-a1cd-91305f0f37e9.jpg | Bin 0 -> 36334 bytes .../9ac5074e-2642-4817-a195-955772c0a7af.jpg | Bin 0 -> 63690 bytes .../9af8033d-6ba3-41cd-b00a-c6068eef6acb.jpg | Bin 0 -> 19534 bytes .../9b7530b5-f46d-4052-829f-024f8f8dc3c8.jpg | Bin 0 -> 13690 bytes .../9ce7c12d-a000-49c9-aa7e-4d0b656e57cf.jpg | Bin 0 -> 2819 bytes .../9d14d925-1b34-4bf5-ad67-ce5fa8d740b1.jpg | Bin 0 -> 23030 bytes .../9ea6b3ac-aba2-4e23-8ab0-4281ccdab960.jpg | Bin 0 -> 20205 bytes .../9fd2dcaf-e549-4b69-a8bb-2dc2ca75882e.jpg | Bin 0 -> 52744 bytes .../a136afea-d033-4f40-94f5-b2e0614789fd.jpg | Bin 0 -> 41780 bytes .../a447964b-afcb-40e2-8809-e42e91b02d53.jpg | Bin 0 -> 42754 bytes .../a4b52cce-e807-4ff2-88cd-7f832e5352a1.jpg | Bin 0 -> 63690 bytes .../a5036382-e093-42f1-a057-a8431d3b3741.jpg | Bin 0 -> 56456 bytes .../a5e971a1-ad17-4068-8d11-e946cfb2f9bc.jpg | Bin 0 -> 43832 bytes .../a7b187d4-80be-4c62-b909-eb6e010ddc8b.jpg | Bin 0 -> 91238 bytes .../a7d86e42-ffd7-4f33-bed7-8ad895f8738a.jpg | Bin 0 -> 41780 bytes .../a961033b-416e-4392-96c7-a08a429ad146.jpg | Bin 0 -> 262341 bytes .../aac204d4-c986-4d76-a71f-406cc2aad69f.jpg | Bin 0 -> 22309 bytes .../aaebe63e-446a-4bfa-ad0b-ddacfe75e15c.jpg | Bin 0 -> 262341 bytes .../abfecf2d-1061-4105-a1e8-184cbfa8e3a7.jpg | Bin 0 -> 53882 bytes .../acb4f63e-86d0-4e29-85bf-2c705af612d4.jpg | Bin 0 -> 21768 bytes .../acd747f9-fd95-4cde-ba7b-9ed79d89e9ee.jpg | Bin 0 -> 12668 bytes .../ad122c1f-7dc7-4a56-bd29-7ebe1400aef5.jpg | Bin 0 -> 422640 bytes .../ae5e4f43-433c-46fd-992a-599c188c6502.jpg | Bin 0 -> 51039 bytes .../ae605bc5-7551-4cb3-a66b-2c2bde0951a6.jpg | Bin 0 -> 26758 bytes .../af021316-395f-4881-96d8-3c26380273de.jpg | Bin 0 -> 17967 bytes .../b07d7bc4-e72d-4f3d-a36c-012c0660dc66.jpg | Bin 0 -> 17967 bytes .../b0a3b136-489c-4fe8-a1b9-cbae8e29cc12.jpg | Bin 0 -> 21768 bytes .../b2be74fa-7908-4be8-8e99-a8db6f51f189.jpg | Bin 0 -> 11071 bytes ...ccb3bc-bf84-497e-8549-f3619977ae32.svg+xml | Bin 0 -> 55975 bytes .../ba01a350-7e51-4db2-9dca-8a6c69a9fbcf.jpg | Bin 0 -> 438894 bytes .../ba741009-aaa5-4e79-8406-f69b6f75cd02.jpg | Bin 0 -> 20205 bytes .../bc70399d-2e04-4704-badc-8eed3f441e6f.jpg | Bin 0 -> 22082 bytes .../c1f90506-c579-4dd6-80a2-992a15ad7e78.jpg | Bin 0 -> 85724 bytes .../c3cdf672-10f1-43ac-8450-8a86d9a69d43.jpg | Bin 0 -> 56456 bytes .../c486794e-e2a6-4b4f-a5c2-8d3028cff651.jpg | Bin 0 -> 43832 bytes .../c4b33725-dcfd-4df0-8a0f-4c382a09e686.jpg | Bin 0 -> 56456 bytes .../c6e0f1d7-fe61-4aaa-a0f5-450fc13b45a4.jpg | Bin 0 -> 8937 bytes .../c885cf6e-8c1c-433a-95f0-7d8da8635490.jpg | Bin 0 -> 23030 bytes .../c9de6cc1-0a2a-47b2-93fd-32c4a69832d7.jpg | Bin 0 -> 20205 bytes .../cc645433-3688-423f-bbcd-7275787d0958.jpg | Bin 0 -> 18614 bytes .../ccae13c3-e637-4487-b65f-0af03d9bac09.jpg | Bin 0 -> 12352 bytes .../cfd059ce-aad8-404a-8082-70e153438f9c.jpg | Bin 0 -> 12352 bytes .../d08b4582-8d01-4b7e-9a53-1d2322009eab.jpg | Bin 0 -> 17967 bytes .../d1f77339-42de-40f0-8bf2-5917b098b7ad.jpg | Bin 0 -> 13690 bytes .../d38b59e7-a618-4659-8f85-bd86bfd532b5.jpg | Bin 0 -> 13690 bytes .../d3c2cb6c-0d01-429b-bbcd-1c5f975ee088.jpg | Bin 0 -> 20205 bytes .../d61011a3-9609-4ad2-82da-461ffb238204.jpg | Bin 0 -> 8937 bytes .../d65adb89-3892-48c1-ab29-c5aa3b3f5708.png | Bin 0 -> 67970 bytes .../d9580b04-e814-4c42-a7c9-c9378951ef15.jpg | Bin 0 -> 13690 bytes .../d958bf48-2ba0-4019-bde1-f7dc9a7b035f.jpg | Bin 0 -> 20205 bytes .../d97305cd-f1e6-499d-b23c-8c9919e51681.jpg | Bin 0 -> 51039 bytes .../d9cba451-4c08-4a1c-93be-913efdbaa33a.jpg | Bin 0 -> 54583 bytes .../dc7dd483-5b58-480b-9dc5-dc2a6778fc0e.jpg | Bin 0 -> 14857 bytes .../dcbc362c-a388-4d38-b3cc-86cd00565317.png | Bin 0 -> 67970 bytes .../dcc8cd97-6365-4c3f-bd60-ee526f039032.jpg | Bin 0 -> 262341 bytes .../dd320773-5fdb-4a88-b2f4-ac39d19d1a9f.jpg | Bin 0 -> 53882 bytes .../dff3caa6-eb31-47e8-bda9-2bf292453ffe.jpg | Bin 0 -> 20205 bytes .../e0139e90-491a-4717-be07-3340f61037da.jpg | Bin 0 -> 25461 bytes .../e1bd57f2-9724-4934-a6ee-12afde55d75e.png | Bin 0 -> 6821 bytes .../e3ef1797-7888-4e39-aa8c-55967fece189.jpg | Bin 0 -> 12668 bytes .../e3f62614-e67d-455a-b7a2-a801a7129479.jpg | Bin 0 -> 35929 bytes .../ec6dce57-c239-44cb-b6c6-0e7891e0a3c7.png | Bin 0 -> 33573 bytes .../ed729fa5-03ac-4a33-bbae-a21ff4eda6c5.jpg | Bin 0 -> 438894 bytes .../eeebefdd-9575-4ef8-804f-34e1a0e152c2.jpg | Bin 0 -> 2036 bytes .../ef7647d1-35ca-49ef-acd3-4349c116e18e.jpg | Bin 0 -> 107147 bytes .../efd531c6-fa17-4d1a-8024-6cb73e257efd.jpg | Bin 0 -> 41780 bytes .../f7409dd4-600b-40b6-8450-24d67abb6ef4.jpg | Bin 0 -> 90398 bytes .../f922c461-56ca-47f3-a2bd-02231ca7843f.png | Bin 0 -> 33573 bytes .../fb241127-f67d-4026-9f4c-e17f1a552696.jpg | Bin 0 -> 36862 bytes .../fb63355d-d9ab-4b68-9fbd-fe41b75eed72.jpg | Bin 0 -> 17967 bytes .../fd7d27b1-5236-4a68-907c-725a0eb67e6a.jpg | Bin 0 -> 35929 bytes .../feb6b9b1-5af1-4021-9616-7d51b586b489.jpg | Bin 0 -> 422640 bytes .../ff2e6812-d04b-48e8-8144-940f288d7dc5.jpg | Bin 0 -> 16300 bytes .../ffc17349-f2d6-4248-9018-248563f785f5.jpg | Bin 0 -> 41780 bytes 208 files changed, 493 insertions(+), 318 deletions(-) create mode 100644 .playwright-mcp/console-2026-04-19T18-53-32-857Z.log create mode 100644 .playwright-mcp/page-2026-04-19T18-53-33-247Z.yml create mode 100644 keep-notes/public/uploads/notes/01ccf206-307f-42a4-b9b1-d1023233d28d.jpg create mode 100644 keep-notes/public/uploads/notes/03822d48-3e40-4c23-a4d4-b22d57fd0aa4.jpg create mode 100644 keep-notes/public/uploads/notes/05110cea-1c8e-40d0-94e2-69af4666e494.jpg create mode 100644 keep-notes/public/uploads/notes/05ac9d60-79d8-4444-94e3-ab5e0ef21d6b.jpg create mode 100644 keep-notes/public/uploads/notes/071d9a1d-7272-45bf-999e-a803943bc789.jpg create mode 100644 keep-notes/public/uploads/notes/0865a0cb-c7d4-42d3-9ce9-35a4a560eb21.jpg create mode 100644 keep-notes/public/uploads/notes/0a88ace8-d9ac-4ef6-b75e-b7e1bf92243e.jpg create mode 100644 keep-notes/public/uploads/notes/0b7899d5-7225-4cb7-b664-41ecfdc43c6d.jpg create mode 100644 keep-notes/public/uploads/notes/0d3f41e4-e011-4ecc-951d-5336013cbd9b.jpg create mode 100644 keep-notes/public/uploads/notes/0d57e021-4b11-46c4-b789-25e0abc22cb1.jpg create mode 100644 keep-notes/public/uploads/notes/0f0529bf-afd3-4181-8ddc-d9eafbcb61d8.png create mode 100644 keep-notes/public/uploads/notes/11180abd-29e8-4ec7-8d7b-93eae56c1658.png create mode 100644 keep-notes/public/uploads/notes/11619703-0505-4419-b9ca-ff2c6db5667b.png create mode 100644 keep-notes/public/uploads/notes/116b00e6-1bb1-4b83-9cab-7b19993ea7b2.jpg create mode 100644 keep-notes/public/uploads/notes/11e13ec2-048a-4005-9339-4d2309c87451.svg+xml create mode 100644 keep-notes/public/uploads/notes/17b55a0f-ba7f-4e0b-8b22-18c242032c82.jpg create mode 100644 keep-notes/public/uploads/notes/19756abd-f675-444e-b1ef-3fe1480d6ff8.jpg create mode 100644 keep-notes/public/uploads/notes/1a79dbd0-8d2c-407d-ab1d-603ffff1e08a.png create mode 100644 keep-notes/public/uploads/notes/1b2040ac-ccd2-4a20-867e-3b6917c653f7.jpg create mode 100644 keep-notes/public/uploads/notes/1b8a904e-8666-4bce-b68b-21900f638c41.jpg create mode 100644 keep-notes/public/uploads/notes/1c34e3c9-736c-4f61-8dcb-0e26a506accf.jpg create mode 100644 keep-notes/public/uploads/notes/1eb77279-1461-4bc6-b5aa-178035816f10.jpg create mode 100644 keep-notes/public/uploads/notes/1f5da0e0-5708-4419-a118-f8538315c3f6.jpg create mode 100644 keep-notes/public/uploads/notes/20308091-4065-4954-bae5-d2ebdd69377f.jpg create mode 100644 keep-notes/public/uploads/notes/204e0948-eb67-42dd-b3ba-ba2a1ebae04e.jpg create mode 100644 keep-notes/public/uploads/notes/22e5b674-4438-457f-bdf0-e6923fc767cf.jpg create mode 100644 keep-notes/public/uploads/notes/25837174-8265-44f7-b5bc-1727a2fd0287.jpg create mode 100644 keep-notes/public/uploads/notes/259c6d8d-3c88-429b-ba0c-466bc9e2c4a0.jpg create mode 100644 keep-notes/public/uploads/notes/2b1809ab-63a8-4f07-aacd-d5d94cb80557.jpg create mode 100644 keep-notes/public/uploads/notes/2b92618f-eb55-479b-ad3b-e6fc604114cd.jpg create mode 100644 keep-notes/public/uploads/notes/2bfceecb-571e-42dd-8204-2a5d1e2caa84.jpg create mode 100644 keep-notes/public/uploads/notes/2ce7f626-2fbd-446a-bc3e-f2dd18d921ed.jpg create mode 100644 keep-notes/public/uploads/notes/2e92b91c-9e0f-4fb4-9130-79acbf2a60b6.jpg create mode 100644 keep-notes/public/uploads/notes/2f2cff2f-d308-406a-b56c-97c581fcf521.jpg create mode 100644 keep-notes/public/uploads/notes/31492c72-8c12-4088-8b17-e305ea38aad0.jpg create mode 100644 keep-notes/public/uploads/notes/31861780-9135-4865-866f-9da859e6fcf4.jpg create mode 100644 keep-notes/public/uploads/notes/36363ef8-4e60-4c4e-b2a9-4194281d1486.jpg create mode 100644 keep-notes/public/uploads/notes/36a78f8f-2712-49cf-9080-bf808984d840.jpg create mode 100644 keep-notes/public/uploads/notes/391e5c59-b722-48dd-adae-9629f3fe54c6.jpg create mode 100644 keep-notes/public/uploads/notes/39643a60-83ad-4dbb-8ff1-bd5557557b59.jpg create mode 100644 keep-notes/public/uploads/notes/3c34ebdf-2b38-4083-8948-839758260537.jpg create mode 100644 keep-notes/public/uploads/notes/411cd01a-a8ec-4386-ad48-cdddf8ca328a.jpg create mode 100644 keep-notes/public/uploads/notes/43c79de0-4fbb-420e-b979-3a477ef1fecf.jpg create mode 100644 keep-notes/public/uploads/notes/43f3fe0f-58e6-4077-a05e-26a7b6b82427.jpg create mode 100644 keep-notes/public/uploads/notes/45f68bd2-61f4-4e60-8216-ce04a03259e7.jpg create mode 100644 keep-notes/public/uploads/notes/46627bf2-42fc-466c-8180-b4c09b2690ee.jpg create mode 100644 keep-notes/public/uploads/notes/46837c2f-b5cd-4e10-8cd6-fc26a2359b28.jpg create mode 100644 keep-notes/public/uploads/notes/46bd4472-1bb3-4257-9ee2-fb2db0730e0d.png create mode 100644 keep-notes/public/uploads/notes/46c281dc-e5db-46df-a381-8e432be2dd29.jpg create mode 100644 keep-notes/public/uploads/notes/470075b4-2df8-402e-8bd4-d450293ea755.jpg create mode 100644 keep-notes/public/uploads/notes/47252485-3f63-41c3-b7f7-baa3b5fdbef9.jpg create mode 100644 keep-notes/public/uploads/notes/49ed661a-9e5f-4d8e-9b8d-0f0ff70488ce.jpg create mode 100644 keep-notes/public/uploads/notes/4b85cf3e-6af6-4ae2-8883-20d4539ec211.jpg create mode 100644 keep-notes/public/uploads/notes/4bdee09e-ec1c-408e-8161-cc4a2b931034.jpg create mode 100644 keep-notes/public/uploads/notes/4f942e8b-982a-4aed-8e31-86053fea5901.jpg create mode 100644 keep-notes/public/uploads/notes/5094a78f-1966-4f7e-a249-b2b8c1645d69.jpg create mode 100644 keep-notes/public/uploads/notes/565e9a07-cfff-4538-baf0-c9e074c0e390.jpg create mode 100644 keep-notes/public/uploads/notes/56829cb4-35e9-4a64-a68e-0f395d1093fc.jpg create mode 100644 keep-notes/public/uploads/notes/59ad3b52-40f7-4c29-a2bf-39e44fb760bf.jpg create mode 100644 keep-notes/public/uploads/notes/5d15d215-1055-4ad8-8d9e-50df93ebe795.jpg create mode 100644 keep-notes/public/uploads/notes/5e0a9ac1-241c-4411-bc2a-eadbe59efb5d.jpg create mode 100644 keep-notes/public/uploads/notes/61035308-b29f-47ce-999f-533d4ddd6ee7.jpg create mode 100644 keep-notes/public/uploads/notes/62b1807b-1b5e-423f-aaff-db62eba1af83.jpg create mode 100644 keep-notes/public/uploads/notes/649474f3-67a6-4c3e-8748-fd11601f6cf7.jpg create mode 100644 keep-notes/public/uploads/notes/64ebca73-4447-49db-8be2-6840fbc6e6c8.jpg create mode 100644 keep-notes/public/uploads/notes/667c275b-eb75-4d07-a435-0349189a26cc.jpg create mode 100644 keep-notes/public/uploads/notes/668dd2f6-44bc-4198-a112-a407d47b7ed1.jpg create mode 100644 keep-notes/public/uploads/notes/66af52fb-6fab-4230-847c-eb65e902d069.jpg create mode 100644 keep-notes/public/uploads/notes/67f0b83b-786e-4067-a7fa-d31cfc7aa197.jpg create mode 100644 keep-notes/public/uploads/notes/6a89a8f1-9f5f-46a7-a3f2-e6b958a99bfa.jpg create mode 100644 keep-notes/public/uploads/notes/6e2b0161-0eed-4c40-a330-1d02fbcc6b27.jpg create mode 100644 keep-notes/public/uploads/notes/6fe5fc87-23f7-4ca3-809b-132eefb1cd4f.jpg create mode 100644 keep-notes/public/uploads/notes/76dd7f14-5147-4286-93f3-a71f31388ff3.jpg create mode 100644 keep-notes/public/uploads/notes/7b345722-6871-4fea-a594-036c2d93f84d.jpg create mode 100644 keep-notes/public/uploads/notes/7bbce240-2d98-414c-bf7a-12ff5061cedc.jpg create mode 100644 keep-notes/public/uploads/notes/7e473396-1d4e-4117-9f22-9ba991aac022.jpg create mode 100644 keep-notes/public/uploads/notes/8298565f-d601-4cf8-8bf7-48394227dec1.jpg create mode 100644 keep-notes/public/uploads/notes/8884588d-f8ea-4c59-a2a2-a943895b36dc.jpg create mode 100644 keep-notes/public/uploads/notes/88aadb89-8c27-481d-b89d-286d86f9f78c.jpg create mode 100644 keep-notes/public/uploads/notes/8e3fb875-7cbe-4d57-8e55-35049d698b78.png create mode 100644 keep-notes/public/uploads/notes/8e6d6dfb-aad5-4836-bf95-2bda6fc42baf.jpg create mode 100644 keep-notes/public/uploads/notes/8efbf2bd-6d3d-4946-bb81-03e0e0c1a821.jpg create mode 100644 keep-notes/public/uploads/notes/8efc141f-9f20-4b94-aa3d-434ea3784593.jpg create mode 100644 keep-notes/public/uploads/notes/8fc39197-1e00-4d96-81bf-2d9970ba5091.jpg create mode 100644 keep-notes/public/uploads/notes/93155e47-7670-4b01-aeaa-c26e7b6198eb.jpg create mode 100644 keep-notes/public/uploads/notes/93890ccc-ffb4-482d-bc69-e5d922bdfb2b.jpg create mode 100644 keep-notes/public/uploads/notes/9472f539-b92b-4f1c-aa60-322c4c1ea028.jpg create mode 100644 keep-notes/public/uploads/notes/94eb60bd-e693-4a09-9429-6820711f3a7c.jpg create mode 100644 keep-notes/public/uploads/notes/95247436-954c-4f6a-8b02-c509abed55d8.jpg create mode 100644 keep-notes/public/uploads/notes/9599029c-b1ed-40fc-a303-67fdf447fde2.jpg create mode 100644 keep-notes/public/uploads/notes/96e66b66-70e2-45f9-9eea-d31c1fdc809e.jpg create mode 100644 keep-notes/public/uploads/notes/96fb2f00-f09c-44a0-91d4-3eb2dcd4a08d.jpg create mode 100644 keep-notes/public/uploads/notes/981c7050-a763-4b82-a83b-2ef8636cbd1a.jpg create mode 100644 keep-notes/public/uploads/notes/997ccca7-f68d-4fdc-8588-9d0dcbb173ba.jpg create mode 100644 keep-notes/public/uploads/notes/9a1d36c1-7fcc-4c43-a1cd-91305f0f37e9.jpg create mode 100644 keep-notes/public/uploads/notes/9ac5074e-2642-4817-a195-955772c0a7af.jpg create mode 100644 keep-notes/public/uploads/notes/9af8033d-6ba3-41cd-b00a-c6068eef6acb.jpg create mode 100644 keep-notes/public/uploads/notes/9b7530b5-f46d-4052-829f-024f8f8dc3c8.jpg create mode 100644 keep-notes/public/uploads/notes/9ce7c12d-a000-49c9-aa7e-4d0b656e57cf.jpg create mode 100644 keep-notes/public/uploads/notes/9d14d925-1b34-4bf5-ad67-ce5fa8d740b1.jpg create mode 100644 keep-notes/public/uploads/notes/9ea6b3ac-aba2-4e23-8ab0-4281ccdab960.jpg create mode 100644 keep-notes/public/uploads/notes/9fd2dcaf-e549-4b69-a8bb-2dc2ca75882e.jpg create mode 100644 keep-notes/public/uploads/notes/a136afea-d033-4f40-94f5-b2e0614789fd.jpg create mode 100644 keep-notes/public/uploads/notes/a447964b-afcb-40e2-8809-e42e91b02d53.jpg create mode 100644 keep-notes/public/uploads/notes/a4b52cce-e807-4ff2-88cd-7f832e5352a1.jpg create mode 100644 keep-notes/public/uploads/notes/a5036382-e093-42f1-a057-a8431d3b3741.jpg create mode 100644 keep-notes/public/uploads/notes/a5e971a1-ad17-4068-8d11-e946cfb2f9bc.jpg create mode 100644 keep-notes/public/uploads/notes/a7b187d4-80be-4c62-b909-eb6e010ddc8b.jpg create mode 100644 keep-notes/public/uploads/notes/a7d86e42-ffd7-4f33-bed7-8ad895f8738a.jpg create mode 100644 keep-notes/public/uploads/notes/a961033b-416e-4392-96c7-a08a429ad146.jpg create mode 100644 keep-notes/public/uploads/notes/aac204d4-c986-4d76-a71f-406cc2aad69f.jpg create mode 100644 keep-notes/public/uploads/notes/aaebe63e-446a-4bfa-ad0b-ddacfe75e15c.jpg create mode 100644 keep-notes/public/uploads/notes/abfecf2d-1061-4105-a1e8-184cbfa8e3a7.jpg create mode 100644 keep-notes/public/uploads/notes/acb4f63e-86d0-4e29-85bf-2c705af612d4.jpg create mode 100644 keep-notes/public/uploads/notes/acd747f9-fd95-4cde-ba7b-9ed79d89e9ee.jpg create mode 100644 keep-notes/public/uploads/notes/ad122c1f-7dc7-4a56-bd29-7ebe1400aef5.jpg create mode 100644 keep-notes/public/uploads/notes/ae5e4f43-433c-46fd-992a-599c188c6502.jpg create mode 100644 keep-notes/public/uploads/notes/ae605bc5-7551-4cb3-a66b-2c2bde0951a6.jpg create mode 100644 keep-notes/public/uploads/notes/af021316-395f-4881-96d8-3c26380273de.jpg create mode 100644 keep-notes/public/uploads/notes/b07d7bc4-e72d-4f3d-a36c-012c0660dc66.jpg create mode 100644 keep-notes/public/uploads/notes/b0a3b136-489c-4fe8-a1b9-cbae8e29cc12.jpg create mode 100644 keep-notes/public/uploads/notes/b2be74fa-7908-4be8-8e99-a8db6f51f189.jpg create mode 100644 keep-notes/public/uploads/notes/b4ccb3bc-bf84-497e-8549-f3619977ae32.svg+xml create mode 100644 keep-notes/public/uploads/notes/ba01a350-7e51-4db2-9dca-8a6c69a9fbcf.jpg create mode 100644 keep-notes/public/uploads/notes/ba741009-aaa5-4e79-8406-f69b6f75cd02.jpg create mode 100644 keep-notes/public/uploads/notes/bc70399d-2e04-4704-badc-8eed3f441e6f.jpg create mode 100644 keep-notes/public/uploads/notes/c1f90506-c579-4dd6-80a2-992a15ad7e78.jpg create mode 100644 keep-notes/public/uploads/notes/c3cdf672-10f1-43ac-8450-8a86d9a69d43.jpg create mode 100644 keep-notes/public/uploads/notes/c486794e-e2a6-4b4f-a5c2-8d3028cff651.jpg create mode 100644 keep-notes/public/uploads/notes/c4b33725-dcfd-4df0-8a0f-4c382a09e686.jpg create mode 100644 keep-notes/public/uploads/notes/c6e0f1d7-fe61-4aaa-a0f5-450fc13b45a4.jpg create mode 100644 keep-notes/public/uploads/notes/c885cf6e-8c1c-433a-95f0-7d8da8635490.jpg create mode 100644 keep-notes/public/uploads/notes/c9de6cc1-0a2a-47b2-93fd-32c4a69832d7.jpg create mode 100644 keep-notes/public/uploads/notes/cc645433-3688-423f-bbcd-7275787d0958.jpg create mode 100644 keep-notes/public/uploads/notes/ccae13c3-e637-4487-b65f-0af03d9bac09.jpg create mode 100644 keep-notes/public/uploads/notes/cfd059ce-aad8-404a-8082-70e153438f9c.jpg create mode 100644 keep-notes/public/uploads/notes/d08b4582-8d01-4b7e-9a53-1d2322009eab.jpg create mode 100644 keep-notes/public/uploads/notes/d1f77339-42de-40f0-8bf2-5917b098b7ad.jpg create mode 100644 keep-notes/public/uploads/notes/d38b59e7-a618-4659-8f85-bd86bfd532b5.jpg create mode 100644 keep-notes/public/uploads/notes/d3c2cb6c-0d01-429b-bbcd-1c5f975ee088.jpg create mode 100644 keep-notes/public/uploads/notes/d61011a3-9609-4ad2-82da-461ffb238204.jpg create mode 100644 keep-notes/public/uploads/notes/d65adb89-3892-48c1-ab29-c5aa3b3f5708.png create mode 100644 keep-notes/public/uploads/notes/d9580b04-e814-4c42-a7c9-c9378951ef15.jpg create mode 100644 keep-notes/public/uploads/notes/d958bf48-2ba0-4019-bde1-f7dc9a7b035f.jpg create mode 100644 keep-notes/public/uploads/notes/d97305cd-f1e6-499d-b23c-8c9919e51681.jpg create mode 100644 keep-notes/public/uploads/notes/d9cba451-4c08-4a1c-93be-913efdbaa33a.jpg create mode 100644 keep-notes/public/uploads/notes/dc7dd483-5b58-480b-9dc5-dc2a6778fc0e.jpg create mode 100644 keep-notes/public/uploads/notes/dcbc362c-a388-4d38-b3cc-86cd00565317.png create mode 100644 keep-notes/public/uploads/notes/dcc8cd97-6365-4c3f-bd60-ee526f039032.jpg create mode 100644 keep-notes/public/uploads/notes/dd320773-5fdb-4a88-b2f4-ac39d19d1a9f.jpg create mode 100644 keep-notes/public/uploads/notes/dff3caa6-eb31-47e8-bda9-2bf292453ffe.jpg create mode 100644 keep-notes/public/uploads/notes/e0139e90-491a-4717-be07-3340f61037da.jpg create mode 100644 keep-notes/public/uploads/notes/e1bd57f2-9724-4934-a6ee-12afde55d75e.png create mode 100644 keep-notes/public/uploads/notes/e3ef1797-7888-4e39-aa8c-55967fece189.jpg create mode 100644 keep-notes/public/uploads/notes/e3f62614-e67d-455a-b7a2-a801a7129479.jpg create mode 100644 keep-notes/public/uploads/notes/ec6dce57-c239-44cb-b6c6-0e7891e0a3c7.png create mode 100644 keep-notes/public/uploads/notes/ed729fa5-03ac-4a33-bbae-a21ff4eda6c5.jpg create mode 100644 keep-notes/public/uploads/notes/eeebefdd-9575-4ef8-804f-34e1a0e152c2.jpg create mode 100644 keep-notes/public/uploads/notes/ef7647d1-35ca-49ef-acd3-4349c116e18e.jpg create mode 100644 keep-notes/public/uploads/notes/efd531c6-fa17-4d1a-8024-6cb73e257efd.jpg create mode 100644 keep-notes/public/uploads/notes/f7409dd4-600b-40b6-8450-24d67abb6ef4.jpg create mode 100644 keep-notes/public/uploads/notes/f922c461-56ca-47f3-a2bd-02231ca7843f.png create mode 100644 keep-notes/public/uploads/notes/fb241127-f67d-4026-9f4c-e17f1a552696.jpg create mode 100644 keep-notes/public/uploads/notes/fb63355d-d9ab-4b68-9fbd-fe41b75eed72.jpg create mode 100644 keep-notes/public/uploads/notes/fd7d27b1-5236-4a68-907c-725a0eb67e6a.jpg create mode 100644 keep-notes/public/uploads/notes/feb6b9b1-5af1-4021-9616-7d51b586b489.jpg create mode 100644 keep-notes/public/uploads/notes/ff2e6812-d04b-48e8-8144-940f288d7dc5.jpg create mode 100644 keep-notes/public/uploads/notes/ffc17349-f2d6-4248-9018-248563f785f5.jpg diff --git a/.playwright-mcp/console-2026-04-19T18-53-32-857Z.log b/.playwright-mcp/console-2026-04-19T18-53-32-857Z.log new file mode 100644 index 0000000..302db14 --- /dev/null +++ b/.playwright-mcp/console-2026-04-19T18-53-32-857Z.log @@ -0,0 +1,47 @@ +[ 242ms] [VERBOSE] [DOM] Input elements should have autocomplete attributes (suggested: "current-password"): (More info: https://goo.gl/9p2vKq) %o @ http://localhost:3000/login?callbackUrl=http%3A%2F%2Flocalhost%3A3000%2F:0 +[ 274ms] [INFO] %cDownload the React DevTools for a better development experience: https://react.dev/link/react-devtools font-weight:bold @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 312ms] [LOG] [HMR] connected @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 343ms] [LOG] [Prisma] Models loaded: @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 426ms] [LOG] [Fast Refresh] rebuilding @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 437ms] [LOG] [Fast Refresh] done in 112ms @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 180853ms] [LOG] [Fast Refresh] rebuilding @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 180883ms] [LOG] [Fast Refresh] done in 131ms @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 205199ms] [LOG] [Fast Refresh] rebuilding @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 205245ms] [LOG] [Fast Refresh] done in 50ms @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 205472ms] [LOG] [Fast Refresh] rebuilding @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 205472ms] [LOG] [Fast Refresh] done in 104ms @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 218086ms] [LOG] [Fast Refresh] rebuilding @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 218512ms] [LOG] [Fast Refresh] done in 150ms @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 218619ms] [LOG] [Fast Refresh] rebuilding @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 218629ms] [LOG] [Fast Refresh] done in 111ms @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 226896ms] [LOG] [Fast Refresh] rebuilding @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 226973ms] [LOG] [Fast Refresh] done in 41ms @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 250168ms] [LOG] [Fast Refresh] rebuilding @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 250197ms] [LOG] [Fast Refresh] done in 44ms @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 300156ms] [LOG] [Fast Refresh] rebuilding @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 300662ms] [LOG] [Fast Refresh] done in 206ms @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 300662ms] [LOG] [Fast Refresh] rebuilding @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 300673ms] [LOG] [Fast Refresh] done in 9ms @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 300673ms] [LOG] [Fast Refresh] rebuilding @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 300673ms] [LOG] [Fast Refresh] done in 1ms @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 300674ms] [LOG] [Fast Refresh] rebuilding @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 300674ms] [LOG] [Fast Refresh] done in 0ms @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 300775ms] [LOG] [Fast Refresh] rebuilding @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 300797ms] [LOG] [Fast Refresh] done in 123ms @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 330315ms] [LOG] [Fast Refresh] rebuilding @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 330346ms] [LOG] [Fast Refresh] done in 132ms @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 494083ms] [INFO] %cDownload the React DevTools for a better development experience: https://react.dev/link/react-devtools font-weight:bold @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 494099ms] [LOG] [HMR] connected @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 494128ms] [LOG] [Prisma] Models loaded: @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 494533ms] [LOG] [Fast Refresh] rebuilding @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 494534ms] [LOG] [Fast Refresh] done in 312ms @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 583684ms] [LOG] [Fast Refresh] rebuilding @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 583685ms] [LOG] [Fast Refresh] done in 102ms @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 612080ms] [LOG] [Fast Refresh] rebuilding @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 612106ms] [LOG] [Fast Refresh] done in 50ms @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 620251ms] [LOG] [Fast Refresh] rebuilding @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 620280ms] [LOG] [Fast Refresh] done in 42ms @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 628266ms] [LOG] [Fast Refresh] rebuilding @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 628300ms] [LOG] [Fast Refresh] done in 48ms @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 628402ms] [LOG] [Fast Refresh] rebuilding @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 +[ 628423ms] [LOG] [Fast Refresh] done in 122ms @ http://localhost:3000/_next/static/chunks/0sqx_next_dist_0ksjl25._.js:2431 diff --git a/.playwright-mcp/page-2026-04-19T18-53-33-247Z.yml b/.playwright-mcp/page-2026-04-19T18-53-33-247Z.yml new file mode 100644 index 0000000..4c2ada9 --- /dev/null +++ b/.playwright-mcp/page-2026-04-19T18-53-33-247Z.yml @@ -0,0 +1,21 @@ +- generic [active] [ref=e1]: + - main [ref=e4]: + - generic [ref=e7]: + - heading "Sign in to your account" [level=1] [ref=e8] + - generic [ref=e9]: + - generic [ref=e10]: + - generic [ref=e11]: Email + - textbox "Email" [ref=e13]: + - /placeholder: Enter your email address + - generic [ref=e14]: + - generic [ref=e15]: Password + - textbox "Password" [ref=e17]: + - /placeholder: Enter your password + - link "Forgot password?" [ref=e19] [cursor=pointer]: + - /url: /forgot-password + - button "Sign In" [ref=e20] + - generic [ref=e22]: + - text: Don't have an account? + - link "Sign Up" [ref=e23] [cursor=pointer]: + - /url: /register + - region "Notifications alt+T" \ No newline at end of file diff --git a/keep-notes/app/(main)/agents/agents-page-client.tsx b/keep-notes/app/(main)/agents/agents-page-client.tsx index 37d1b4f..1f7fbbc 100644 --- a/keep-notes/app/(main)/agents/agents-page-client.tsx +++ b/keep-notes/app/(main)/agents/agents-page-client.tsx @@ -185,20 +185,20 @@ export function AgentsPageClient({ {/* Agents grid */} {agents.length > 0 && (
-

+

{t('agents.myAgents')}

{/* Search and filter */}
- + setSearchQuery(e.target.value)} placeholder={t('agents.searchPlaceholder')} - className="w-full pl-9 pr-3 py-2 text-sm bg-white border border-slate-200 rounded-lg outline-none focus:border-primary/40 focus:ring-2 focus:ring-primary/10 transition-all" + className="w-full pl-9 pr-3 py-2 text-sm bg-card border border-border rounded-lg outline-none focus:border-primary/40 focus:ring-2 focus:ring-primary/10 transition-all" />
@@ -209,7 +209,7 @@ export function AgentsPageClient({ className={`px-3 py-1.5 text-xs font-medium rounded-full transition-colors ${ typeFilter === opt.value ? 'bg-primary text-white' - : 'bg-slate-100 text-slate-600 hover:bg-slate-200' + : 'bg-muted text-muted-foreground hover:bg-accent' }`} > {t(opt.labelKey)} @@ -232,8 +232,8 @@ export function AgentsPageClient({
) : (
- -

{t('agents.noResults')}

+ +

{t('agents.noResults')}

)}
@@ -242,9 +242,9 @@ export function AgentsPageClient({ {/* Empty state */} {agents.length === 0 && (
- -

{t('agents.noAgents')}

-

+ +

{t('agents.noAgents')}

+

{t('agents.noAgentsDescription')}

diff --git a/keep-notes/app/(main)/agents/page.tsx b/keep-notes/app/(main)/agents/page.tsx index 7e87f89..489782c 100644 --- a/keep-notes/app/(main)/agents/page.tsx +++ b/keep-notes/app/(main)/agents/page.tsx @@ -19,7 +19,7 @@ export default async function AgentsPage() { ]) return ( -
+
-
) diff --git a/keep-notes/app/actions/notes.ts b/keep-notes/app/actions/notes.ts index 40b8b9b..8556e47 100644 --- a/keep-notes/app/actions/notes.ts +++ b/keep-notes/app/actions/notes.ts @@ -435,6 +435,7 @@ export async function createNote(data: { isMarkdown?: boolean size?: 'small' | 'medium' | 'large' autoGenerated?: boolean + aiProvider?: string notebookId?: string | undefined // Assign note to a notebook if provided skipRevalidation?: boolean // Option to prevent full page refresh for smooth optimistic UI updates }) { @@ -459,6 +460,7 @@ export async function createNote(data: { isMarkdown: data.isMarkdown || false, size: data.size || 'small', autoGenerated: data.autoGenerated || null, + aiProvider: data.aiProvider || null, notebookId: data.notebookId || null, } }) @@ -867,7 +869,7 @@ export async function togglePin(id: string, isPinned: boolean) { return updateNo export async function toggleArchive(id: string, isArchived: boolean) { return updateNote(id, { isArchived }) } export async function updateColor(id: string, color: string) { return updateNote(id, { color }) } export async function updateLabels(id: string, labels: string[]) { return updateNote(id, { labels }) } -export async function removeFusedBadge(id: string) { return updateNote(id, { autoGenerated: null }) } +export async function removeFusedBadge(id: string) { return updateNote(id, { autoGenerated: null, aiProvider: null }) } // Update note size WITHOUT revalidation - client uses optimistic updates export async function updateSize(id: string, size: 'small' | 'medium' | 'large') { @@ -941,8 +943,16 @@ export async function updateFullOrderWithoutRevalidation(ids: string[]) { if (!session?.user?.id) throw new Error('Unauthorized'); const userId = session.user.id; try { - const updates = ids.map((id: string, index: number) => - prisma.note.update({ where: { id, userId }, data: { order: index } }) + // Verify all notes belong to the user before updating + const notes = await prisma.note.findMany({ + where: { id: { in: ids }, userId }, + select: { id: true }, + }) + const ownedIds = new Set(notes.map(n => n.id)) + const validIds = ids.filter(id => ownedIds.has(id)) + + const updates = validIds.map((id: string, index: number) => + prisma.note.update({ where: { id }, data: { order: index } }) ) await prisma.$transaction(updates) return { success: true } diff --git a/keep-notes/app/api/chat/route.ts b/keep-notes/app/api/chat/route.ts index 8a58c7a..7bd50c9 100644 --- a/keep-notes/app/api/chat/route.ts +++ b/keep-notes/app/api/chat/route.ts @@ -5,6 +5,8 @@ import { semanticSearchService } from '@/lib/ai/services/semantic-search.service import { prisma } from '@/lib/prisma' import { auth } from '@/auth' import { loadTranslations, getTranslationValue, SupportedLanguage } from '@/lib/i18n' +import { toolRegistry } from '@/lib/ai/tools' +import { stepCountIs } from 'ai' export const maxDuration = 60 @@ -45,11 +47,12 @@ export async function POST(req: Request) { // 2. Parse request body — messages arrive as UIMessage[] from DefaultChatTransport const body = await req.json() - const { messages: rawMessages, conversationId, notebookId, language } = body as { + const { messages: rawMessages, conversationId, notebookId, language, webSearch } = body as { messages: UIMessage[] conversationId?: string notebookId?: string language?: string + webSearch?: boolean } // Convert UIMessages to CoreMessages for streamText @@ -143,7 +146,19 @@ export async function POST(req: Request) { - Natural tone, neither corporate nor too casual. - No unnecessary intro phrases ("Here's what I found", "Based on your notes"). Answer directly. - No upsell questions at the end ("Would you like me to...", "Do you want..."). If you have useful additional info, just give it. -- If the user says "Momento" they mean Memento (this app).`, +- If the user says "Momento" they mean Memento (this app). + +## Available tools +You have access to these tools for deeper research: +- **note_search**: Search the user's notes by keyword or meaning. Use when the initial context above is insufficient or when the user asks about specific content in their notes. If a notebook is selected, pass its ID to restrict results. +- **note_read**: Read a specific note by ID. Use when note_search returns a note you need the full content of. +- **web_search**: Search the web for information. Use when the user asks about something not in their notes. +- **web_scrape**: Scrape a web page and return its content as markdown. Use when web_search returns a URL you need to read. + +## Tool usage rules +- You already have context from the user's notes above. Only use tools if you need more specific or additional information. +- Never invent note IDs, URLs, or notebook IDs. Use the IDs provided in the context or from tool results. +- For simple conversational questions (greetings, opinions, general knowledge), answer directly without using any tools.`, }, fr: { contextWithNotes: `## Notes de l'utilisateur\n\n${contextNotes}\n\nQuand tu utilises une info venant des notes ci-dessus, cite le titre de la note source entre parenthèses, ex: "Le déploiement se fait via Docker (💻 Development Guide)". Ne recopie pas mot pour mot — reformule. Si les notes ne couvrent pas le sujet, dis-le et complète avec tes connaissances générales.`, @@ -159,7 +174,19 @@ export async function POST(req: Request) { - Ton naturel, ni corporate ni trop familier. - Pas de phrase d'intro inutile ("Voici ce que j'ai trouvé", "Basé sur vos notes"). Réponds directement. - Pas de question upsell à la fin ("Souhaitez-vous que je...", "Acceptez-vous que..."). Si tu as une info complémentaire utile, donne-la. -- Si l'utilisateur dit "Momento" il parle de Memento (cette application).`, +- Si l'utilisateur dit "Momento" il parle de Memento (cette application). + +## Outils disponibles +Tu as accès à ces outils pour des recherches approfondies : +- **note_search** : Cherche dans les notes de l'utilisateur par mot-clé ou sens. Utilise quand le contexte initial ci-dessus est insuffisant ou quand l'utilisateur demande du contenu spécifique dans ses notes. Si un carnet est sélectionné, passe son ID pour restreindre les résultats. +- **note_read** : Lit une note spécifique par son ID. Utilise quand note_search retourne une note dont tu as besoin du contenu complet. +- **web_search** : Recherche sur le web. Utilise quand l'utilisateur demande quelque chose qui n'est pas dans ses notes. +- **web_scrape** : Scrape une page web et retourne son contenu en markdown. Utilise quand web_search retourne une URL que tu veux lire. + +## Règles d'utilisation des outils +- Tu as déjà du contexte des notes de l'utilisateur ci-dessus. Utilise les outils seulement si tu as besoin d'informations plus spécifiques. +- N'invente jamais d'IDs de notes, d'URLs ou d'IDs de carnet. Utilise les IDs fournis dans le contexte ou les résultats d'outils. +- Pour les questions conversationnelles simples (salutations, opinions, connaissances générales), réponds directement sans utiliser d'outils.`, }, fa: { contextWithNotes: `## یادداشت‌های کاربر\n\n${contextNotes}\n\nهنگام استفاده از اطلاعات یادداشت‌های بالا، عنوان یادداشت منبع را در پرانتز ذکر کنید. کپی نکنید — بازنویسی کنید. اگر یادداشت‌ها موضوع را پوشش نمی‌دهند، بگویید و با دانش عمومی خود تکمیل کنید.`, @@ -175,7 +202,18 @@ export async function POST(req: Request) { - لحن طبیعی، نه رسمی بیش از حد و نه خیلی غیررسمی. - بدون جمله مقدمه اضافی. مستقیم پاسخ دهید. - بدون سؤال فروشی در انتها. اگر اطلاعات تکمیلی مفید دارید، مستقیم بدهید. -- اگر کاربر "Momento" می‌گوید، منظورش Memento (این برنامه) است.`, +- اگر کاربر "Momento" می‌گوید، منظورش Memento (این برنامه) است. + +## ابزارهای موجود +- **note_search**: جستجو در یادداشت‌های کاربر با کلیدواژه یا معنی. زمانی استفاده کنید که زمینه اولیه کافی نباشد. اگر دفترچه انتخاب شده، شناسه آن را ارسال کنید. +- **note_read**: خواندن یک یادداشت خاص با شناسه. زمانی استفاده کنید که note_search یادداشتی برگرداند که محتوای کامل آن را نیاز دارید. +- **web_search**: جستجو در وب. زمانی استفاده کنید که کاربر درباره چیزی خارج از یادداشت‌هایش می‌پرسد. +- **web_scrape**: استخراج محتوای صفحه وب. زمانی استفاده کنید که web_search نشانی‌ای برگرداند که می‌خواهید بخوانید. + +## قوانین استفاده از ابزارها +- شما از قبل زمینه‌ای از یادداشت‌های کاربر دارید. فقط در صورت نیاز به اطلاعات بیشتر از ابزارها استفاده کنید. +- هرگز شناسه یادداشت، نشانی یا شناسه دفترچه نسازید. از شناسه‌های موجود در زمینه یا نتایج ابزار استفاده کنید. +- برای سؤالات مکالمه‌ای ساده (سلام، نظرات، دانش عمومی)، مستقیم پاسخ دهید.`, }, es: { contextWithNotes: `## Notas del usuario\n\n${contextNotes}\n\nCuando uses información de las notas anteriores, cita el título de la nota fuente entre paréntesis. No copies palabra por palabra — reformula. Si las notas no cubren el tema, dilo y complementa con tu conocimiento general.`, @@ -190,7 +228,18 @@ export async function POST(req: Request) { ## Reglas de tono - Tono natural, ni corporativo ni demasiado informal. - Sin frases de introducción innecesarias. Responde directamente. -- Sin preguntas de venta al final. Si tienes información complementaria útil, dala directamente.`, +- Sin preguntas de venta al final. Si tienes información complementaria útil, dala directamente. + +## Herramientas disponibles +- **note_search**: Busca en las notas del usuario por palabra clave o significado. Úsalo cuando el contexto inicial sea insuficiente. Si hay una libreta seleccionada, pasa su ID para restringir los resultados. +- **note_read**: Lee una nota específica por su ID. Úsalo cuando note_search devuelva una nota cuyo contenido completo necesites. +- **web_search**: Busca en la web. Úsalo cuando el usuario pregunte sobre algo que no está en sus notas. +- **web_scrape**: Extrae el contenido de una página web como markdown. Úsalo cuando web_search devuelva una URL que quieras leer. + +## Reglas de uso de herramientas +- Ya tienes contexto de las notas del usuario arriba. Solo usa herramientas si necesitas información más específica. +- Nunca inventes IDs de notas, URLs o IDs de libreta. Usa los IDs proporcionados en el contexto o en los resultados de herramientas. +- Para preguntas conversacionales simples (saludos, opiniones, conocimiento general), responde directamente sin herramientas.`, }, de: { contextWithNotes: `## Notizen des Benutzers\n\n${contextNotes}\n\nWenn du Infos aus den obigen Notizen verwendest, zitiere den Titel der Quellnotiz in Klammern. Nicht Wort für Wort kopieren — umformulieren. Wenn die Notizen das Thema nicht abdecken, sag es und ergänze mit deinem Allgemeinwissen.`, @@ -205,7 +254,18 @@ export async function POST(req: Request) { ## Tonregeln - Natürlicher Ton, weder zu geschäftsmäßig noch zu umgangssprachlich. - Keine unnötigen Einleitungssätze. Antworte direkt. -- Keine Upsell-Fragen am Ende. Gib nützliche Zusatzinfos einfach direkt.`, +- Keine Upsell-Fragen am Ende. Gib nützliche Zusatzinfos einfach direkt. + +## Verfügbare Werkzeuge +- **note_search**: Durchsuche die Notizen des Benutzers nach Schlagwort oder Bedeutung. Verwende es, wenn der obige Kontext unzureichend ist. Wenn ein Notizbuch ausgewählt ist, gib dessen ID an, um die Ergebnisse einzuschränken. +- **note_read**: Lese eine bestimmte Notiz anhand ihrer ID. Verwende es, wenn note_search eine Notiz zurückgibt, deren vollständigen Inhalt du benötigst. +- **web_search**: Suche im Web. Verwende es, wenn der Benutzer nach etwas fragt, das nicht in seinen Notizen steht. +- **web_scrape**: Lese eine Webseite und gib den Inhalt als Markdown zurück. Verwende es, wenn web_search eine URL zurückgibt, die du lesen möchtest. + +## Werkzeugregeln +- Du hast bereits Kontext aus den Notizen des Benutzers oben. Verwende Werkzeuge nur, wenn du spezifischere Informationen benötigst. +- Erfinde niemals Notiz-IDs, URLs oder Notizbuch-IDs. Verwende die im Kontext oder in Werkzeugergebnissen bereitgestellten IDs. +- Bei einfachen Gesprächsfragen (Begrüßungen, Meinungen, Allgemeinwissen) antworte direkt ohne Werkzeuge.`, }, it: { contextWithNotes: `## Note dell'utente\n\n${contextNotes}\n\nQuando usi informazioni dalle note sopra, cita il titolo della nota fonte tra parentesi. Non copiare parola per parola — riformula. Se le note non coprono l'argomento, dillo e integra con la tua conoscenza generale.`, @@ -220,7 +280,18 @@ export async function POST(req: Request) { ## Regole di tono - Tono naturale, né aziendale né troppo informale. - Nessuna frase introduttiva non necessaria. Rispondi direttamente. -- Nessuna domanda di upsell alla fine. Se hai informazioni aggiuntive utili, dalle direttamente.`, +- Nessuna domanda di upsell alla fine. Se hai informazioni aggiuntive utili, dalle direttamente. + +## Strumenti disponibili +- **note_search**: Cerca nelle note dell'utente per parola chiave o significato. Usa quando il contesto iniziale è insufficiente. Se un quaderno è selezionato, passa il suo ID per restringere i risultati. +- **note_read**: Leggi una nota specifica per ID. Usa quando note_search restituisce una nota di cui hai bisogno del contenuto completo. +- **web_search**: Cerca sul web. Usa quando l'utente chiede qualcosa che non è nelle sue note. +- **web_scrape**: Estrai il contenuto di una pagina web come markdown. Usa quando web_search restituisce un URL che vuoi leggere. + +## Regole di utilizzo degli strumenti +- Hai già contesto dalle note dell'utente sopra. Usa gli strumenti solo se hai bisogno di informazioni più specifiche. +- Non inventare mai ID di note, URL o ID di quaderno. Usa gli ID forniti nel contesto o nei risultati degli strumenti. +- Per domande conversazionali semplici (saluti, opinioni, conoscenza generale), rispondi direttamente senza strumenti.`, }, } @@ -260,6 +331,16 @@ ${lang === 'en' ? 'Respond in the user\'s language.' : lang === 'fr' ? 'Réponds const provider = getChatProvider(config) const model = provider.getModel() + // 7b. Build chat tools + const chatToolContext = { + userId, + conversationId: conversation.id, + notebookId, + webSearch: !!webSearch, + config, + } + const chatTools = toolRegistry.buildToolsForChat(chatToolContext) + // 8. Save user message to DB before streaming if (isNewMessage && lastIncoming) { await prisma.chatMessage.create({ @@ -276,6 +357,8 @@ ${lang === 'en' ? 'Respond in the user\'s language.' : lang === 'fr' ? 'Réponds model, system: systemPrompt, messages: allMessages, + tools: chatTools, + stopWhen: stepCountIs(5), async onFinish({ text }) { // Save assistant message to DB after streaming completes await prisma.chatMessage.create({ diff --git a/keep-notes/components/agents/agent-card.tsx b/keep-notes/components/agents/agent-card.tsx index 01854e0..6a88c57 100644 --- a/keep-notes/components/agents/agent-card.tsx +++ b/keep-notes/components/agents/agent-card.tsx @@ -52,10 +52,10 @@ interface AgentCardProps { // --- Config --- const typeConfig: Record = { - scraper: { icon: Globe, color: 'text-blue-600', bgColor: 'bg-blue-50 border-blue-200' }, - researcher: { icon: Search, color: 'text-purple-600', bgColor: 'bg-purple-50 border-purple-200' }, - monitor: { icon: Eye, color: 'text-amber-600', bgColor: 'bg-amber-50 border-amber-200' }, - custom: { icon: Settings, color: 'text-green-600', bgColor: 'bg-green-50 border-green-200' }, + scraper: { icon: Globe, color: 'text-blue-600 dark:text-blue-400', bgColor: 'bg-blue-50 dark:bg-blue-950 border-blue-200 dark:border-blue-800' }, + researcher: { icon: Search, color: 'text-purple-600 dark:text-purple-400', bgColor: 'bg-purple-50 dark:bg-purple-950 border-purple-200 dark:border-purple-800' }, + monitor: { icon: Eye, color: 'text-amber-600 dark:text-amber-400', bgColor: 'bg-amber-50 dark:bg-amber-950 border-amber-200 dark:border-amber-800' }, + custom: { icon: Settings, color: 'text-green-600 dark:text-green-400', bgColor: 'bg-green-50 dark:bg-green-950 border-green-200 dark:border-green-800' }, } const frequencyKeys: Record = { @@ -142,10 +142,10 @@ export function AgentCard({ agent, onEdit, onRefresh, onToggle }: AgentCardProps return (
-
+
@@ -155,9 +155,9 @@ export function AgentCard({ agent, onEdit, onRefresh, onToggle }: AgentCardProps
-

{agent.name}

+

{agent.name}

{mounted && isNew && ( - + {t('agents.newBadge')} )} @@ -171,16 +171,16 @@ export function AgentCard({ agent, onEdit, onRefresh, onToggle }: AgentCardProps {agent.isEnabled ? ( ) : ( - + )}
{agent.description && ( -

{agent.description}

+

{agent.description}

)} -
+
{t(frequencyKeys[agent.frequency] || 'agents.frequencies.manual')} @@ -199,9 +199,9 @@ export function AgentCard({ agent, onEdit, onRefresh, onToggle }: AgentCardProps {lastAction && (
{lastAction.status === 'success' && } {lastAction.status === 'failure' && } @@ -224,7 +224,7 @@ export function AgentCard({ agent, onEdit, onRefresh, onToggle }: AgentCardProps @@ -61,6 +61,16 @@ const TOOL_PRESETS: Record = { custom: ['memory_search'], } +// --- Shared class strings --- +const labelCls = 'block text-sm font-medium text-foreground mb-1.5' +const labelCls2 = 'block text-sm font-medium text-foreground mb-2' +const inputCls = 'w-full px-3 py-2 text-sm border border-input rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary bg-card text-foreground' +const selectCls = 'w-full px-3 py-2 text-sm border border-input rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary bg-card text-foreground' +const toggleOffBorder = 'border-border hover:border-primary/30' +const toggleOffIcon = 'text-muted-foreground' +const toggleOffLabel = 'text-sm font-medium text-foreground' +const toggleOffHint = 'text-xs text-muted-foreground' + // --- Component --- export function AgentForm({ agent, notebooks, onSave, onCancel }: AgentFormProps) { @@ -187,26 +197,26 @@ export function AgentForm({ agent, notebooks, onSave, onCancel }: AgentFormProps return (
-
+
{/* Header — editable agent name */} -
+
setName(e.target.value)} - className="text-lg font-semibold text-slate-800 bg-transparent border-none outline-none focus:ring-0 p-0 flex-1 placeholder:text-slate-300" + className="text-lg font-semibold text-card-foreground bg-transparent border-none outline-none focus:ring-0 p-0 flex-1 placeholder:text-muted-foreground/40" placeholder={t('agents.form.namePlaceholder')} required /> -
{/* Agent Type */}
- +
{agentTypes.map(at => ( ))}
@@ -230,12 +240,12 @@ export function AgentForm({ agent, notebooks, onSave, onCancel }: AgentFormProps {/* Research Topic (researcher only) — replaces Description for this type */} {type === 'researcher' && (
- + setDescription(e.target.value)} - className="w-full px-3 py-2 text-sm border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary" + className={inputCls} placeholder={t('agents.form.researchTopicPlaceholder')} />
@@ -244,12 +254,12 @@ export function AgentForm({ agent, notebooks, onSave, onCancel }: AgentFormProps {/* Description (for non-researcher types) */} {type !== 'researcher' && (
- + setDescription(e.target.value)} - className="w-full px-3 py-2 text-sm border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary" + className={inputCls} placeholder={t('agents.form.descriptionPlaceholder')} />
@@ -258,7 +268,7 @@ export function AgentForm({ agent, notebooks, onSave, onCancel }: AgentFormProps {/* URLs (scraper and custom only — researcher uses search, not URLs) */} {(type === 'scraper' || type === 'custom') && (
-