total-recall-brain 3.24.0 → 3.24.2
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/frontend/dist/assets/index-BQL-opnK.js +5742 -0
- package/frontend/dist/favicon.ico +0 -0
- package/frontend/dist/favicon.png +0 -0
- package/frontend/dist/favicon.svg +3 -6
- package/frontend/dist/icon-192.png +0 -0
- package/frontend/dist/index.html +1 -1
- package/frontend/src/api/api.spec.ts +2 -1
- package/frontend/src/api/system.ts +6 -0
- package/frontend/src/api/update.ts +1 -4
- package/frontend/src/components/MobilePairing.tsx +25 -18
- package/frontend/src/pages/ChatPage.tsx +25 -1
- package/frontend/src/pages/HealthPage.tsx +52 -3
- package/frontend/src/pages/SettingsPage.tsx +35 -8
- package/package.json +1 -1
- package/scaffold/.agent/skills/total-recall/SKILL.md +13 -0
- package/scaffold/.agent/skills/total-recall/memory-vault/preferences/always-websearch-gap.md +2 -0
- package/scaffold/.agent/skills/total-recall/memory-vault/preferences/topic-research-sop.md +2 -0
- package/scaffold/.agent/skills/total-recall/scripts/sync-repo.mjs +166 -61
- package/src/cli/backup.mjs +63 -0
- package/src/core/package-auto-update.mjs +13 -9
- package/src/core/surface.mjs +51 -22
- package/src/server/route-manifest.json +4 -0
- package/src/server/routes/system.mjs +15 -0
- package/src/server/routes/update.mjs +1 -1
- package/frontend/dist/assets/index-CtCDaZYZ.js +0 -5742
|
Binary file
|
|
Binary file
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
<path d="M24 42V28a8 8 0 0 1 16 0v14" stroke="#1e3a8a" stroke-width="4" stroke-linecap="round"/>
|
|
5
|
-
<rect x="20" y="40" width="24" height="6" rx="2" fill="#93c5fd"/>
|
|
6
|
-
</svg>
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
|
|
2
|
+
<image href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAWsElEQVR4nMVaB3hUx7WecsveXa20aiAkUUSTwEEyCAEGDAaDkTEdF9wI7tjBYOz42U7yHOcldp5x4gIkLgkmBByaMaaFXkzHIKopwhaOChLqbfu9M5Nv5t5drQQSGOd9b4Blv7tz7z1nzjn/+c+ZgYwxcLODAQDB//OQfszNMEIJcyEgtDRijNHQFQQhYPxP+NcfORhretSPUsCyHmuSGwBAhewYIxy6aBgEIv7nuo+CN6Zh5DTYmgtFanntCYALas4xP7nkQnQAQGl1/YJ1ebpOnpvYr2tSPFeDUMTVgK29i7X5xrCcLea0qsB1R+QTKeUOIwnR/1VR85d/frNox6XyCj8ggTgnm35Xr1mT+ndL5moQyhC80ZW+2j5XK3mTCoTvEo4OMeIPLS6v+Z/P9q89WFLdCIEjWsUUUD1oUOYNxsUpj45Me/aezPTURH4X5bcjcdeNQEEbxmnLL1t9nFgNajoMQhjBs0UVa/aellWp1h2oriFIs2k4YBgBQqEkKVqsq57YPlhbkPP88qffW19UWct9CUFC+WDw+ivYhsVuxgKEUgAARlz5CyUVC7/MW7br2/rawNQRXd6bM+ZMQeVT8zaXlutKfCyEMqEEcvwBCCGDQqO0ZOPCqfF2lVI2uHdn06n4rzcLUD9MgUjTny0sX7D+5Gf7i931OtQkBeNAnTfOBT742bAR/dJe/fOOZbuKQHSiTYZEDwBGAYQAYon6Ly568K3lRz7+8vxjuV2fHpc1oGeqpUbYqf4vFIgU/djFkj9vOL3ycJnXzWCUTZYh03Vq6LKMgwFK62qm5aYvmD0670LpM386WFgetEUp1NAZgwaTkqPphU+mPfT2jg2HygHxyVLg/jt6vDilf7/uyS1j4z+rgDm+zi9+d/XX644U+w27EuOUMSCUEIAohYDogBo8MiAk9b7YROWT54dl90j81eK9/9hZAOwuu03x+uiAbvY98yZkz1lzocir2mCQQuo3VA08MCjl+YlZ/YU1fpAabSlAeU7iv/p1Y8/JwvnrT207UAR8BnAoHDcYA5IMEAYQAwkDiSnUpyHgcKgJCdE2CTol49cP5dye1XPR1rxfLD5S4bYhKN8/LOGPz9ze64llbqJhSBiECGPCIGn0yjgwZXDqi1NzBqR3FG+nAPBY/8EKMHFzZM5Zu+fYukOXg1iLj1EUTAklNlVxaHKMU02McrgcikOVJYRsNuCwaS6HEmO32SSe4xkgxGCSJP2rsvaXSw79Y825nz814L6R6QOfXi7HxANGGeB4ABjACOoEULdbVtn9Q7vMnZKd3YM7FccATkbQzVjg8IXikhqvJmGAkENTICMB3fAbrDFIGn1+rz/Q6CEBv+H2Uxr0znvmTruiRC4D5eDDQZ4QK8fNW7mvS5KLSsqDr29R4+MIJYIjCWMKrMQIEcIMt0/V2JTBqbMm9h2cwZ2qjWTRTAEGGKXUIGTdwfy/bi/Ye6464DNMk/CVMicyyCGFcSbBv2MIAkavXs68Pz0qC3+AAAIut3hl6Nk8NLhbczVeWbxr3tIztsQ4gxDr5WIuDH0ijAzCiMdjs7FxOSmzJ2YNuaUz49c5kLVIas3IHMc5hH3+4JFvCvecKdeJQ46OkkHA0A0GEcSyyCghAieWBEJDr6kdN7CTJsuGwbUVTzdfAEPrK2Ip5Abfl9QBhBhfBcjniynie8iBCZUxDyZ/o2fbkUtDM+KH3tIFYWtCW1Si0R8srfOkJ8VySlNe8+7ak4s2n/O6DRzjlLBEedqGYjWRsDqDACLGgvVVG9+e0Cc1NjE+WpNkg1DOLPhrBN+jgFtFqHT8u9KPN55c8dUlP7ABjACUoOA3gipY1oIQ6jqlXn9yO+WZ3B7Pju+XGO3QKTt57rvs3t14MDR3JUsB0y7Fdd7nlp4e1iNmat8OXdu7+CsLSt9bffiLI2XeoF122DCkhkHM9wgWDYhBXbKnYNkTM95a3+ijH75wZ8/kBEooNxAffGq127fuYP7SnRf3nKkFXgDsGFADUCo8B4kEZwplPpFEO+nTuRkvTM5OSeAybNp/8jcL1iiavO9vr4OrSFHYhfhVjAGUbBsvBPcXXBzQNXpS3w79uiUvfXXK3ILSd9eeXHWgxB/AcpQNAUAIYQAgCGiQ3HZriorh0UJ/aTm5be7nr93f58WpgxGAhkEoJXvyzn66Nf9YQQ2UtUF92jk1GQOmcOciSOJDlSXNJhmEevwBXdeTXNrPxmf9pFN7AMDuvAt//MeuTYfyQaNv1LAMYdOWo1kMcGMCZlMVL5M2Xwh+9d1399wSfV8/rsaynyc/O7bonc/z1h+tYFSWNQUDwrkgMXJzOn17ua60KiC7nLV++vKCg7uOF/1p9pi09nEl5XVIcbz62CiEgccwIKMahyNIKAwS5tF1ypgMYNAXiLfD7Iy0MNTsPZX//rIt6w8VEgK16OgAVkJWalMBoQQxAJAhiLbLBpXXnvEcLLgwKsM1ISt5SO9OQ17vtDWv4Pcrjnx1ogwoUarTiWQ2vE/KzpMlwICQ6BgQlJC4Oa9h8Itf/PHJQaNvTflsx9m/f1WkqipketAAjIvCMzevIowAqG8AxDt6SNfXpg0ypT97qeT3izet3JZn6EiOcUk2zJGRMCYQ7DoKCAOIcII8VCUEJJtSa8hL8xp35p8be4vr7syUMdndxmR3W7XvzPx13xz4prFde6VLx9jNiw7zoKRBChCjVI22X/GDh/9wYPqIlN8+NfK2rO/nLNzjC2qyK4aRAKREUaRAkAHMRg/rNnty5ricdADApdKKD1buWrzlRGONV3bEqHZkcLbNsISFVNcezYK4tNHzzLLzPqZJPIHzEBOXKUZIJ8Dn97V3sLv7xE26tUO8ZgMAfPTPE5U19dPHZ/d6/DMdaIgJuOVLhRAHGByork1OoJ++lJveMX7Wwq82HS5DDjs1DOB398+Ie21a/ylDbxGIV7lg5e7FG47U1hPsjJIRMHTdbAMAxHl70BsYldN5+/w5rO0gFp8WdoR05rcYhKO1w2ar8rO/7K/deq52Wr/4cX1SZo7tCwA49X1ZOwcoLG0AdpuqKWaK40SGBhSXvdSt5766YfbUrOW/Grt0+zcvf3IoKUF75b6hT9zdDyNcVdfw58/3LFyzv7LcA50ONUblMMdxDkEuQihohTZtW4AHSWmjd6awAEbCjRinU+GbzTkQ4aBBEfFlJOIJmYm3Z7S3S1K12/fRhryPNp0tqZWBTVUVRjixphAALElYsfsqG9o5G//59r2aqsXG2DtEO9z+wIef716wal/x5ToQ5bApkkEIpICaKdJMCyI5YwSDnsCdOZ13LGjLAiFVIQ6pKkitmeZExrSKScpUDJBiu1jH3t5RvvxYxdT+7cbe0uGXDw59Mjfrw01nPt767ZXyBmi3yRJGUAowGKyu75isPnJ7pstu75acYBBj4epdC1btu3ipEtjtamwMpcTQSVPm5unZyiFhPwjTkraoRMiRLLLQZDT+XVAHwUV4BiIAQ4gUraCW/G5T2ZYzlY/mJA3qnvTGI4OfGNP7nTWH/74lv96jAYxi7YEZk9N+fu+A5HielRZv2P/Bit2nLlwBmqbGRnNmyzOjEE84jNWmCb9faBMWxqRLbVrA0paKep9LLe4O8RAKKARI+KbwPWpXod3mOFdFfrO5ODu1YuytSYPT2s2fmfvc+Oz31uQxgF6e2q9HSgIA4Ivdx/6wbOehk4VA1Wx81SkxBJeOFCiUq8IrZjmA0CpCxlbJnLkUQjZuPXMeDwjzJv7X8iXC63DrOrPJGELn/uLgnktFfTtemTEoObtT4sezc83Hbjv8zZt/3bj3eAFQnWqsizFOeIWbgJB7WCsf1iFMUpt8Ifx7mzHAoBm4lvYsaPBqQpE4z2YAUQAkJLoSosdkPhUCaBJ7RZJkLOcV6+dLL036SdXMET2Duj7zzSVLt58FDCou0Z8ziOmLYfeEEGJRPPE+DX97pDhilkUNWxjLGs3SGwOQQslcaSY6BR2iabQSdPuCDEIbCjixr9YT0KlAI4G3HOwYAbw4NJu5xOWQmOw8+L2XIeQL6l/uPw81uy3awbt3HBciZGAmuYUBt8df5w4GghAhEQeRbePrlJQtLYAYYfwiYwxJMPCbST2dGK89Xrr5dOUDA5Pu6Jmw7PDl7RfcPkNxaBJvhoYMLCKGEzxuKQgUGXO4QDDKobobuMdEeLPlHAgh3eu3KeSZh27v3N71t63HTl+skDWVU3BTBRHFlqvBG1FAwKRpLwqgJgOnhJKitGeHd5uY2S4uSrPJ0iu56VOzG9adKNua7wkCVRG1ouXIPFHwf4TQILWqMk4G+EVTdh415hojCEnQ6BCLtix8IbNbJwDAw+MG5/x0XkmVB0vYRFKxMs3McfVozpBMk5lrFS4NGfel5FinTZYMygzCuidGv3RX+ltT0mLVIGHclUTWM8PLikEm7uXMM9wADQGlOTjMMf/GhXPqPf7UO3+WM/3X8Q71roEZ0B80O60cLizpeQy01oFspoCVSEJQwKtY4egirfNfJAQlUdoFDKN/Sux9fWN1wy+ZlxgSd3DRmkDLDD7eOzTRLWR3jEi959Hxg1LbxeXOmn/ZjY7llxdV1isyIvWN12LOrXYeLAUiJBdihBDO/E90q2Cd1//pvoK3t3z71ffVqiRRxgalxUVBX01jkLuzyA5moWk+iLdEzSIr5MMRPW2eUx4fN/CTNXt9bmaPjQEe7+Xq+jH9u898fKQRDIax0qqYI/oD11bgKpSyClQRo2b+ZfN3FPxlX8WRS42vrDg7f2c+gjAt3vm/96YPTGVet0cnnOcLMORiikwUKhYtVLe8AIr2MHaonZPivy+rYQHib2yYnJvdKSFmwrB+cx8eLUoSE+NChChC/BaKNGOj4sWRmdd6JUKwzh84Xtj45PDk6YNSz1d4fvfFGZddmX5bWmZy3Pv3xx38V/XCHUWVQUVsh5mhF+6oWD2iME8wVwQxQhkzgoFB2R3fnD15ZP/e5gZPXYPXcl9LDGHDsAWuCuarypxmCjbN1SkwKBncPVbGOLND9DsP9d1w9PJ3VY2UsoU7zneJs88akRLw+QUBNXt6pkcJUZroiwVCAELd7a5q8Pz3Y7l7F786sn9vnkGIjhBkWERiaPetuRRNXbBWFRDOZ9kMhWOAUpemODWpqMZHGQvopHOsPbNL7LIDhQjB/FLP33fnpyVFI8goI9bih6LK5CYhKDELDkR93hd+OqZXarvunZJljJdu2neuoBhjWQhk4m9ECRZue11rNFfAdFOzIcg9FTLEvV/XqQzhiF6Jm06WIbFtalDWq3P8xTIPBeyt+7Om39613meIrUir/xQyvKmCgGQspONtH5IYH/XGzEl2VaGUrtpxdPrT89fvP20R6GsCfthzrtpfaw6jHG6tUMAI1PjgtvNVEEJVxYSyhwZ2qmgwlhy5LEtIQtAwDIwwodRpk5Pjopm5ycf1NQvrcOha6cWCIP4DtcmYGgajFCF08MS39g5xk0Zkh50szGVCYlnXr8+FIm+glKqq/On+ynk7v73S6MUIRinSa+O6LztQOPfzC4sOFa84UpESp8oIGTwamRSB9WHzRzhykyCWhXnTGQEA7s0dZECfZlM4++JNRXxNzGyNErVwoRABF2ZCvCC0fXnS/fyK/CWHC2u9/qwU10fT+1TWuxfvK7FL9MGBydbyWg1C84miCRoONcsnzCwXsUEd+uLzuLunxPn9AV5/YlRcUUN0hiP76eEgutYIw6hpadHaAk06YMhinWqdzj4+WLv5bO3EzNjJ/VKXPdG/tN7rUHCMpvIMHNqDMJNWJAxbggsqFLmoTbUJY5k9Ox1d9Y5dkes9vg/X7H5/9X5J1ZqX8IKztpLJmucBK/DCHshXljdrIYy2qxU++v6emtXHqx4dkDi5b0fTrVsQ5JBYYsvOerAFPaJRYXEsShlhzNztbB/nAoD9beO+3y/adLGwHjqjJQk1LWToCa25UMuSEiEARTUfgi6rEU0plRBwOW1VAfbOzort56qn9ms/PKO9xOPY6pQ37QaJZRe7q6bfC94dsfZmsWFu1G7Yd+KtZTsPnyoCCNniY0Uvy5pphYrYaGptj8ZSwOyVU0rrvTpUoCIDwpoKyzAXoZRoMkSqPb+W/nZr2aoTVQ/kJI3okQgB5OHMd79NwS1hhSQY8ELaIramXLKMou3Knryzb/114/ZTlwG22WJcjOi8sxIZJ2JgjKlfr290t6UAr28ZS3DYHs5JXHemoc4r8bYIT0zNXMRcFUo5VsiS/XwVeX1DyZDOFT+9LfmKW9cJkGSLCVqlSFMrxPJQxiDGsKrRGDlr/pGT+SQIldg4hJBA1ebHUCDguy1BI9hQ36Nr7JwHRlpLet09suI6z/KjZTvON3qJ5NRkCLizRqKyxdb5PgeHHG9Qd2IdIuhnskgkfLuuvYMumdHH5/NmTHuzvF6XuVs3wQMD0PAHZVVCmNfT5hUe/tDyNAljnVCjwZ3SIWbOtNtnThnm1DTREWoJRy1jgDLW0eX4r9HdJ2TWr/j6yr5Lbh0omirxnq3lmibJMHtcDDJiV7DOJNG345sGJhCIz6Z+TsihTTbETaRqCmWMEJGlwwYSSEoo89U1RkUpT00f/vLDozqIhhIhRMQMvF4Qi1McjIGM9jFvjI85Wli15NCVk6V+LCmaggAHD6vICq2HeWCFb4ayyBLGJDS8MIusxMxMz1GBWJgELQhnFENMEfY3eBQVzZjQ/6VHRv0kje+0Ggbhx6cwbisGWuhgttcBAzmdE7I7x+3Mr1qdV3HuSkCWFYci+hA8KiPzfci0FvsJVwEt/TNU6oXuEQNzggd9Hg8AZNLwPr+YcVdO7zRxRoogHsSojRM3rR4542ENBdhBNDq93R094redrVh9vKKwhsqKIkmINCWXyPItXMHwFnO4oIz0XbNkEBANOTxi5PP6gadxUFbqr54cf8/QW80DMRBASay62VRubbR1Zo7nduEtfCMI4Xv6dBiRHr/p1JWVx6uKGlCUTVVkfuBHyMRTDy/gxH0m7IZ27sxKxgxi0ypWWGCMgzqjbnefbvEvPTjxkXFDMN+84b+aKSKscBvjhg79mYcOKGN2Rbkvp9OIXokrjpWuO11X65FiNFnCvKMWSlmmu4fgLqKWEisvQJafHeKkWq+qSe2U8PJz45+aOFRTVXPhI0U3R9tn6X7AqUXRC+XnGxKitFl3dBuX6V5+9PKeiw1eQ45SFQCoYW1aW8VjU/loHtzgG+08KxmEBetqo+1w5ozhcx/JTbJAhiKMrpb+6mbozStgLagocRgDXeKiXhuTPrVv3RfHy/YV+HxEkmVZtLXNdqf5Wk6aGdP5XhV3etnX6Nc09PjUQXMfujO9szjOwU8zIjNSb2LczLlRcwfbzIs927lezXXdXVK95HDZgUseWdai7ZLB8V2c+RGHtBCmGDNfvRswfdLI7NefGNM3vUtIdNim6Nc/EHjzB1/NvTTzFEdWavy798btuFD+2dflBdUBxA+giTYtT0yY6sDn8w/LSnnlsbvHDuHbaoRQXn1i9ONPNv+ok7uR8Q0BHJWRNKxn4vazZWuOVwUCPFUQyirLy/ukdXzj8fsmj8jmdbY4xXtjDgNvSAL2o4d5sIsxXjmYX9yB4LbThUFCaxrcC1du9fj9YhrV+eED9p8d8Lpn5tpAscifrOPDAqauPidm0oHWIIWFntP2u655+80fPW7jfeYulUnRCW89RIDqVfOve0i7bQX+DRfjprLIE7BhAAAAAElFTkSuQmCC" width="64" height="64" />
|
|
3
|
+
</svg>
|
|
Binary file
|
package/frontend/dist/index.html
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
18
18
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
|
19
19
|
<title>Total Recall — Portable Memory</title>
|
|
20
|
-
<script type="module" crossorigin src="/assets/index-
|
|
20
|
+
<script type="module" crossorigin src="/assets/index-BQL-opnK.js"></script>
|
|
21
21
|
<link rel="stylesheet" crossorigin href="/assets/index-C7_Xpk27.css">
|
|
22
22
|
</head>
|
|
23
23
|
<body>
|
|
@@ -99,6 +99,7 @@ import {
|
|
|
99
99
|
triggerRecompile,
|
|
100
100
|
triggerDream,
|
|
101
101
|
runAgentDiagnostics,
|
|
102
|
+
restartDaemon,
|
|
102
103
|
fetchBrains,
|
|
103
104
|
listTasks,
|
|
104
105
|
createTask,
|
|
@@ -189,7 +190,7 @@ describe('API barrel exports — all functions exist', () => {
|
|
|
189
190
|
// research
|
|
190
191
|
listResearch, createResearch, patchResearch, deleteResearch,
|
|
191
192
|
// system
|
|
192
|
-
fetchHealth, fetchUsageStats, fetchLogs, triggerRecompile, triggerDream, runAgentDiagnostics,
|
|
193
|
+
fetchHealth, fetchUsageStats, fetchLogs, triggerRecompile, triggerDream, runAgentDiagnostics, restartDaemon,
|
|
193
194
|
fetchBrains, listTasks, createTask, listFiles, listScripts, readScript, saveScript, runScript,
|
|
194
195
|
shareToApi, runOkfLint, triggerOkfExport, postDecision,
|
|
195
196
|
// update
|
|
@@ -71,6 +71,12 @@ export async function runAgentDiagnostics(): Promise<{ success: boolean; output:
|
|
|
71
71
|
return res.json()
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
export async function restartDaemon(): Promise<{ success: boolean; message: string; pid?: number }> {
|
|
75
|
+
const res = await apiFetch(`${API_BASE}/api/daemon/restart`, { method: 'POST' })
|
|
76
|
+
if (!res.ok) throw new Error(`Restart daemon API error: ${res.status}`)
|
|
77
|
+
return res.json()
|
|
78
|
+
}
|
|
79
|
+
|
|
74
80
|
export async function fetchBrains(): Promise<Record<string, unknown>[]> {
|
|
75
81
|
const res = await apiFetch(`${API_BASE}/api/brains`)
|
|
76
82
|
const data = await res.json()
|
|
@@ -15,13 +15,10 @@ export async function checkUpdate(): Promise<UpdateCheckResult> {
|
|
|
15
15
|
// Normalize snake_case API fields for the Settings UI
|
|
16
16
|
const currentVersion = data.currentVersion ?? data.current ?? ''
|
|
17
17
|
const latestVersion = data.latestVersion ?? data.latest ?? ''
|
|
18
|
-
// Prefer host package comparison; fall back to API flag (includes consumers behind).
|
|
19
|
-
const hostBehind =
|
|
20
|
-
Boolean(latestVersion && currentVersion && latestVersion !== currentVersion)
|
|
21
18
|
return {
|
|
22
19
|
currentVersion,
|
|
23
20
|
latestVersion,
|
|
24
|
-
updateAvailable:
|
|
21
|
+
updateAvailable: Boolean(data.updateAvailable ?? data.update_available),
|
|
25
22
|
}
|
|
26
23
|
}
|
|
27
24
|
|
|
@@ -202,43 +202,50 @@ export function MobilePairing() {
|
|
|
202
202
|
</div>
|
|
203
203
|
|
|
204
204
|
{selected && (
|
|
205
|
-
<
|
|
206
|
-
{selected.reachable_hint}
|
|
207
|
-
</
|
|
205
|
+
<div style={{ fontSize: 12, color: 'var(--text-secondary)', margin: '0 0 10px', lineHeight: 1.5, background: 'rgba(255,255,255,0.03)', padding: '8px 12px', borderRadius: 6 }}>
|
|
206
|
+
<strong>Connection Route:</strong> {selected.reachable_hint}
|
|
207
|
+
</div>
|
|
208
208
|
)}
|
|
209
209
|
|
|
210
210
|
{isLoopback && (
|
|
211
|
-
<
|
|
211
|
+
<div
|
|
212
212
|
data-testid="pairing-loopback-warning"
|
|
213
|
-
style={{ fontSize: 12, color: '#f59e0b', margin: 0 }}
|
|
213
|
+
style={{ fontSize: 12, color: '#f59e0b', margin: '0 0 8px', background: 'rgba(245, 158, 11, 0.1)', padding: '8px 12px', borderRadius: 6, border: '1px solid rgba(245, 158, 11, 0.2)' }}
|
|
214
214
|
>
|
|
215
|
-
|
|
216
|
-
</
|
|
215
|
+
⚠️ <strong>Loopback Only:</strong> <code>127.0.0.1</code> only works on this computer. To open on your phone, select your Mesh IP (<code>100.64.x.x</code>) or enable <strong>Allow Public Bind</strong> below to use local Wi-Fi.
|
|
216
|
+
</div>
|
|
217
217
|
)}
|
|
218
218
|
</div>
|
|
219
219
|
</div>
|
|
220
220
|
)}
|
|
221
221
|
|
|
222
222
|
{info?.warnings && info.warnings.length > 0 && (
|
|
223
|
-
<
|
|
223
|
+
<div
|
|
224
224
|
data-testid="pairing-warnings"
|
|
225
225
|
style={{
|
|
226
226
|
margin: '16px 0 0',
|
|
227
|
-
|
|
227
|
+
padding: '10px 14px',
|
|
228
228
|
fontSize: 12,
|
|
229
|
-
color: '#
|
|
229
|
+
color: '#fbbf24',
|
|
230
|
+
background: 'rgba(251, 191, 36, 0.08)',
|
|
231
|
+
borderRadius: 8,
|
|
232
|
+
border: '1px solid rgba(251, 191, 36, 0.2)',
|
|
230
233
|
}}
|
|
231
234
|
>
|
|
232
|
-
{
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
235
|
+
<div style={{ fontWeight: 600, marginBottom: 4 }}>Network Notice:</div>
|
|
236
|
+
<ul style={{ margin: 0, paddingLeft: 18 }}>
|
|
237
|
+
{info.warnings.map((w) => (
|
|
238
|
+
<li key={w}>{w}</li>
|
|
239
|
+
))}
|
|
240
|
+
</ul>
|
|
241
|
+
</div>
|
|
236
242
|
)}
|
|
237
243
|
|
|
238
|
-
<
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
244
|
+
<div style={{ marginTop: 16, padding: '12px 14px', background: 'rgba(59, 130, 246, 0.06)', borderRadius: 8, border: '1px solid rgba(59, 130, 246, 0.15)', fontSize: 12, color: 'var(--text-secondary)', lineHeight: 1.5 }}>
|
|
245
|
+
<div style={{ color: 'var(--text-primary)', fontWeight: 600, marginBottom: 4 }}>📱 How to connect your phone:</div>
|
|
246
|
+
<div><strong>Option A (WireGuard / Mesh — Recommended):</strong> Install the standard <em>Tailscale</em> app on your phone (iOS App Store / Google Play). Log into your tailnet/headscale server. Scan the <code>100.64.x.x</code> QR code above.</div>
|
|
247
|
+
<div style={{ marginTop: 4 }}><strong>Option B (Local Home Wi-Fi):</strong> Check <strong>Allow Public Bind</strong> in <em>Network & Binding</em> below, restart the server, and scan your local Wi-Fi LAN QR code (e.g. <code>192.168.x.x</code>).</div>
|
|
248
|
+
</div>
|
|
242
249
|
</div>
|
|
243
250
|
);
|
|
244
251
|
}
|
|
@@ -46,6 +46,9 @@ export default function ChatPage({ activeBrainId, onBrainChange }: { activeBrain
|
|
|
46
46
|
const [extensionBannerDismissed, setExtensionBannerDismissed] = useState(
|
|
47
47
|
() => localStorage.getItem('tr-ext-banner-dismissed') === 'true'
|
|
48
48
|
)
|
|
49
|
+
const [dismissedUpdateVersion, setDismissedUpdateVersion] = useState<string | null>(
|
|
50
|
+
() => localStorage.getItem('tr-update-banner-dismissed-version')
|
|
51
|
+
)
|
|
49
52
|
|
|
50
53
|
// Threads listing & session control state
|
|
51
54
|
const [threads, setThreads] = useState<ChatThread[]>([])
|
|
@@ -671,7 +674,7 @@ export default function ChatPage({ activeBrainId, onBrainChange }: { activeBrain
|
|
|
671
674
|
</header>
|
|
672
675
|
|
|
673
676
|
{/* Update Available Banner */}
|
|
674
|
-
{updateInfo?.updateAvailable && (
|
|
677
|
+
{updateInfo?.updateAvailable && dismissedUpdateVersion !== updateInfo.latestVersion && (
|
|
675
678
|
<div className="animate-fade-in" style={{
|
|
676
679
|
margin: '0 16px 12px',
|
|
677
680
|
padding: '12px 16px',
|
|
@@ -710,6 +713,27 @@ export default function ChatPage({ activeBrainId, onBrainChange }: { activeBrain
|
|
|
710
713
|
>
|
|
711
714
|
Go to Update
|
|
712
715
|
</button>
|
|
716
|
+
<button
|
|
717
|
+
onClick={() => {
|
|
718
|
+
if (updateInfo?.latestVersion) {
|
|
719
|
+
localStorage.setItem('tr-update-banner-dismissed-version', updateInfo.latestVersion)
|
|
720
|
+
setDismissedUpdateVersion(updateInfo.latestVersion)
|
|
721
|
+
}
|
|
722
|
+
}}
|
|
723
|
+
title="Dismiss banner"
|
|
724
|
+
aria-label="Dismiss update banner"
|
|
725
|
+
style={{
|
|
726
|
+
background: 'transparent',
|
|
727
|
+
border: 'none',
|
|
728
|
+
color: 'var(--text-muted)',
|
|
729
|
+
fontSize: 16,
|
|
730
|
+
cursor: 'pointer',
|
|
731
|
+
padding: '4px 6px',
|
|
732
|
+
lineHeight: 1,
|
|
733
|
+
}}
|
|
734
|
+
>
|
|
735
|
+
✕
|
|
736
|
+
</button>
|
|
713
737
|
</div>
|
|
714
738
|
)}
|
|
715
739
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useState, useEffect } from 'react'
|
|
2
|
-
import { fetchHealth, checkUpdate, runUpdate } from '../api'
|
|
2
|
+
import { fetchHealth, checkUpdate, runUpdate, restartDaemon } from '../api'
|
|
3
3
|
import type { HealthData, UpdateCheckResult } from '../types'
|
|
4
4
|
|
|
5
5
|
function formatUptime(seconds: number): string {
|
|
@@ -23,6 +23,24 @@ export default function HealthPage() {
|
|
|
23
23
|
const [updateError, setUpdateError] = useState('')
|
|
24
24
|
const [isCheckingUpdate, setIsCheckingUpdate] = useState(false)
|
|
25
25
|
const [checkMessage, setCheckMessage] = useState('')
|
|
26
|
+
const [isRestartingDaemon, setIsRestartingDaemon] = useState(false)
|
|
27
|
+
const [daemonMessage, setDaemonMessage] = useState('')
|
|
28
|
+
|
|
29
|
+
const handleRestartDaemon = async () => {
|
|
30
|
+
setIsRestartingDaemon(true)
|
|
31
|
+
setDaemonMessage('')
|
|
32
|
+
try {
|
|
33
|
+
const res = await restartDaemon()
|
|
34
|
+
setDaemonMessage(res.message || 'Daemon restarted successfully')
|
|
35
|
+
setTimeout(() => setDaemonMessage(''), 4000)
|
|
36
|
+
const data = await fetchHealth()
|
|
37
|
+
setHealth(data)
|
|
38
|
+
} catch (e) {
|
|
39
|
+
setDaemonMessage(`Failed to restart daemon: ${(e as Error).message}`)
|
|
40
|
+
} finally {
|
|
41
|
+
setIsRestartingDaemon(false)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
26
44
|
|
|
27
45
|
const handleManualCheckUpdate = async () => {
|
|
28
46
|
setIsCheckingUpdate(true)
|
|
@@ -96,8 +114,14 @@ export default function HealthPage() {
|
|
|
96
114
|
setIsUpdating(false)
|
|
97
115
|
setCheckMessage(
|
|
98
116
|
result.message ||
|
|
99
|
-
'Registered projects updated. Restart
|
|
117
|
+
'Registered projects updated. Restart daemon if you need new code running.',
|
|
100
118
|
)
|
|
119
|
+
|
|
120
|
+
// Refresh version check immediately so banner / badge clears
|
|
121
|
+
const refreshed = await checkUpdate().catch(() => null)
|
|
122
|
+
if (refreshed) {
|
|
123
|
+
setUpdateInfo(refreshed)
|
|
124
|
+
}
|
|
101
125
|
} catch (e) {
|
|
102
126
|
setUpdateError((e as Error).message)
|
|
103
127
|
setIsUpdating(false)
|
|
@@ -278,7 +302,32 @@ export default function HealthPage() {
|
|
|
278
302
|
<tr><th>Version</th><td>{health.version}</td></tr>
|
|
279
303
|
<tr><th>Uptime</th><td>{formatUptime(health.uptime_seconds)}</td></tr>
|
|
280
304
|
<tr><th>Timestamp</th><td>{health.timestamp}</td></tr>
|
|
281
|
-
<tr
|
|
305
|
+
<tr>
|
|
306
|
+
<th>Daemon Status</th>
|
|
307
|
+
<td>
|
|
308
|
+
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12 }}>
|
|
309
|
+
<span style={{ fontWeight: 600 }}>{health.daemon || 'unknown'}</span>
|
|
310
|
+
<button
|
|
311
|
+
className="btn btn-secondary"
|
|
312
|
+
onClick={handleRestartDaemon}
|
|
313
|
+
disabled={isRestartingDaemon}
|
|
314
|
+
style={{
|
|
315
|
+
fontSize: 12,
|
|
316
|
+
padding: '4px 12px',
|
|
317
|
+
borderRadius: 6,
|
|
318
|
+
cursor: 'pointer'
|
|
319
|
+
}}
|
|
320
|
+
>
|
|
321
|
+
{isRestartingDaemon ? 'Restarting…' : 'Restart Daemon'}
|
|
322
|
+
</button>
|
|
323
|
+
</div>
|
|
324
|
+
{daemonMessage && (
|
|
325
|
+
<div style={{ fontSize: 12, color: daemonMessage.includes('Failed') ? '#ef4444' : '#3fb950', marginTop: 4 }}>
|
|
326
|
+
{daemonMessage}
|
|
327
|
+
</div>
|
|
328
|
+
)}
|
|
329
|
+
</td>
|
|
330
|
+
</tr>
|
|
282
331
|
{health.cli_agents && (
|
|
283
332
|
<tr><th>CLI Agents</th><td>{health.cli_agents.join(', ')}</td></tr>
|
|
284
333
|
)}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
runAgentDiagnostics,
|
|
7
7
|
checkUpdate,
|
|
8
8
|
runUpdate,
|
|
9
|
+
restartDaemon,
|
|
9
10
|
triggerRecompile,
|
|
10
11
|
apiFetch,
|
|
11
12
|
getApiBase,
|
|
@@ -50,6 +51,22 @@ export default function SettingsPage({ activeBrainId }: { activeBrainId?: string
|
|
|
50
51
|
} | null>(null);
|
|
51
52
|
const [updating, setUpdating] = useState(false);
|
|
52
53
|
const [updateMessage, setUpdateMessage] = useState<string | null>(null);
|
|
54
|
+
const [restartingDaemon, setRestartingDaemon] = useState(false);
|
|
55
|
+
|
|
56
|
+
const handleRestartDaemon = async () => {
|
|
57
|
+
setRestartingDaemon(true);
|
|
58
|
+
setUpdateMessage(null);
|
|
59
|
+
try {
|
|
60
|
+
const res = await restartDaemon();
|
|
61
|
+
setUpdateMessage(res.message || 'Daemon restarted successfully.');
|
|
62
|
+
const h = await fetchHealth().catch(() => null);
|
|
63
|
+
if (h) setHealth(h);
|
|
64
|
+
} catch (err: unknown) {
|
|
65
|
+
setUpdateMessage('Restart error: ' + (err as Error).message);
|
|
66
|
+
} finally {
|
|
67
|
+
setRestartingDaemon(false);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
53
70
|
const [rebuilding, setRebuilding] = useState(false);
|
|
54
71
|
|
|
55
72
|
const loadConfig = async () => {
|
|
@@ -984,14 +1001,24 @@ export default function SettingsPage({ activeBrainId }: { activeBrainId?: string
|
|
|
984
1001
|
</div>
|
|
985
1002
|
)}
|
|
986
1003
|
</div>
|
|
987
|
-
<
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
1004
|
+
<div style={{ display: 'flex', gap: 10, alignItems: 'center' }}>
|
|
1005
|
+
<button
|
|
1006
|
+
className="btn-secondary"
|
|
1007
|
+
onClick={handleRestartDaemon}
|
|
1008
|
+
disabled={restartingDaemon}
|
|
1009
|
+
style={{ fontSize: 13, padding: '8px 14px', borderRadius: 8, cursor: 'pointer' }}
|
|
1010
|
+
>
|
|
1011
|
+
{restartingDaemon ? 'Restarting…' : 'Restart Daemon'}
|
|
1012
|
+
</button>
|
|
1013
|
+
<button
|
|
1014
|
+
className="btn-primary"
|
|
1015
|
+
onClick={handleRunUpdate}
|
|
1016
|
+
disabled={updating}
|
|
1017
|
+
style={{ background: updateInfo?.updateAvailable ? '#3fb950' : undefined, border: 'none' }}
|
|
1018
|
+
>
|
|
1019
|
+
{updating ? 'Updating…' : updateInfo?.updateAvailable ? 'Apply Updates' : 'Check & Sync Projects'}
|
|
1020
|
+
</button>
|
|
1021
|
+
</div>
|
|
995
1022
|
</div>
|
|
996
1023
|
</div>
|
|
997
1024
|
|
package/package.json
CHANGED
|
@@ -597,6 +597,19 @@ Current baseline: **288 spec files / 1493 tests, ~160 s** on the Mac Mini.
|
|
|
597
597
|
>
|
|
598
598
|
> A non-login `ssh` shell has no Homebrew on PATH — export it or use `bash -lc`,
|
|
599
599
|
> otherwise the run dies with `command not found: npx` **and still exits 0**.
|
|
600
|
+
>
|
|
601
|
+
> **Never read a test result through a pipe.** `vitest run` exits 1 correctly on
|
|
602
|
+
> failure, but `npx vitest run | tail -20` reports *tail's* status — always 0 —
|
|
603
|
+
> so a red suite looks green. On 2026-08-19 this cost a full re-run and a wrong
|
|
604
|
+
> "the suite exits 0 on failure" claim about the repo; the defect was the
|
|
605
|
+
> pipeline, not vitest. Capture to a file and check the code separately:
|
|
606
|
+
>
|
|
607
|
+
> ```bash
|
|
608
|
+
> npx vitest run > /tmp/t.log 2>&1; echo "exit=$?"; tail -20 /tmp/t.log
|
|
609
|
+
> ```
|
|
610
|
+
>
|
|
611
|
+
> `check.mjs` is unaffected — it spawns without a shell and reads the real exit
|
|
612
|
+
> code — so prefer the gate over hand-rolled invocations.
|
|
600
613
|
|
|
601
614
|
**Never skip tests** to make a release look clean, and never use `--force` on a
|
|
602
615
|
checker. Audit and clean up any rows, files, or mock entries a suite leaves
|
package/scaffold/.agent/skills/total-recall/memory-vault/preferences/always-websearch-gap.md
CHANGED
|
@@ -3,6 +3,7 @@ type: memory
|
|
|
3
3
|
slug: always-websearch-gap
|
|
4
4
|
category: preferences
|
|
5
5
|
title: "Always Perform Web Search for Cutoff Gap"
|
|
6
|
+
description: "Web-search to confirm any fact that falls in or past the training-cutoff gap, rather than answering from weights."
|
|
6
7
|
status: active
|
|
7
8
|
confidence: 1
|
|
8
9
|
importance: 5
|
|
@@ -32,6 +33,7 @@ schema_version: 2
|
|
|
32
33
|
x_temporal_context: "2026-05-25T22:36:21.376Z"
|
|
33
34
|
priority: absolute
|
|
34
35
|
immutable: true
|
|
36
|
+
timestamp: "2026-05-25T22:36:21.376Z"
|
|
35
37
|
---
|
|
36
38
|
|
|
37
39
|
# Always Perform Web Search for Cutoff Gap
|
|
@@ -3,6 +3,7 @@ type: memory
|
|
|
3
3
|
slug: topic-research-sop
|
|
4
4
|
category: preferences
|
|
5
5
|
title: "Standard Operating Procedure for Topic Research"
|
|
6
|
+
description: "How the agent handles a research request: queue it to the background daemon, keep one living scratch document, and compile so it is searchable."
|
|
6
7
|
status: active
|
|
7
8
|
confidence: 1
|
|
8
9
|
importance: 5
|
|
@@ -32,6 +33,7 @@ schema_version: 2
|
|
|
32
33
|
x_temporal_context: "2026-05-25T22:36:21.376Z"
|
|
33
34
|
priority: absolute
|
|
34
35
|
immutable: true
|
|
36
|
+
timestamp: "2026-05-25T22:36:21.376Z"
|
|
35
37
|
---
|
|
36
38
|
|
|
37
39
|
# Standard Operating Procedure for Topic Research
|