@memtensor/memos-local-openclaw-plugin 0.1.2 → 0.1.4
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/.env.example +13 -5
- package/README.md +180 -68
- package/dist/capture/index.d.ts +5 -7
- package/dist/capture/index.d.ts.map +1 -1
- package/dist/capture/index.js +72 -43
- package/dist/capture/index.js.map +1 -1
- package/dist/ingest/providers/anthropic.d.ts +2 -0
- package/dist/ingest/providers/anthropic.d.ts.map +1 -1
- package/dist/ingest/providers/anthropic.js +110 -1
- package/dist/ingest/providers/anthropic.js.map +1 -1
- package/dist/ingest/providers/bedrock.d.ts +2 -5
- package/dist/ingest/providers/bedrock.d.ts.map +1 -1
- package/dist/ingest/providers/bedrock.js +110 -6
- package/dist/ingest/providers/bedrock.js.map +1 -1
- package/dist/ingest/providers/gemini.d.ts +2 -0
- package/dist/ingest/providers/gemini.d.ts.map +1 -1
- package/dist/ingest/providers/gemini.js +106 -1
- package/dist/ingest/providers/gemini.js.map +1 -1
- package/dist/ingest/providers/index.d.ts +9 -0
- package/dist/ingest/providers/index.d.ts.map +1 -1
- package/dist/ingest/providers/index.js +66 -4
- package/dist/ingest/providers/index.js.map +1 -1
- package/dist/ingest/providers/openai.d.ts +2 -0
- package/dist/ingest/providers/openai.d.ts.map +1 -1
- package/dist/ingest/providers/openai.js +112 -1
- package/dist/ingest/providers/openai.js.map +1 -1
- package/dist/ingest/task-processor.d.ts +63 -0
- package/dist/ingest/task-processor.d.ts.map +1 -0
- package/dist/ingest/task-processor.js +339 -0
- package/dist/ingest/task-processor.js.map +1 -0
- package/dist/ingest/worker.d.ts +1 -1
- package/dist/ingest/worker.d.ts.map +1 -1
- package/dist/ingest/worker.js +18 -13
- package/dist/ingest/worker.js.map +1 -1
- package/dist/recall/engine.d.ts +1 -0
- package/dist/recall/engine.d.ts.map +1 -1
- package/dist/recall/engine.js +21 -11
- package/dist/recall/engine.js.map +1 -1
- package/dist/recall/mmr.d.ts.map +1 -1
- package/dist/recall/mmr.js +3 -1
- package/dist/recall/mmr.js.map +1 -1
- package/dist/storage/sqlite.d.ts +67 -1
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +251 -5
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/types.d.ts +15 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -1
- package/dist/viewer/html.d.ts +1 -1
- package/dist/viewer/html.d.ts.map +1 -1
- package/dist/viewer/html.js +955 -115
- package/dist/viewer/html.js.map +1 -1
- package/dist/viewer/server.d.ts +3 -0
- package/dist/viewer/server.d.ts.map +1 -1
- package/dist/viewer/server.js +59 -1
- package/dist/viewer/server.js.map +1 -1
- package/index.ts +221 -45
- package/openclaw.plugin.json +20 -45
- package/package.json +3 -4
- package/skill/SKILL.md +59 -0
- package/src/capture/index.ts +85 -45
- package/src/ingest/providers/anthropic.ts +128 -1
- package/src/ingest/providers/bedrock.ts +130 -6
- package/src/ingest/providers/gemini.ts +128 -1
- package/src/ingest/providers/index.ts +74 -8
- package/src/ingest/providers/openai.ts +130 -1
- package/src/ingest/task-processor.ts +380 -0
- package/src/ingest/worker.ts +21 -15
- package/src/recall/engine.ts +22 -12
- package/src/recall/mmr.ts +3 -1
- package/src/storage/sqlite.ts +298 -5
- package/src/types.ts +19 -0
- package/src/viewer/html.ts +955 -115
- package/src/viewer/server.ts +63 -1
- package/SKILL.md +0 -43
- package/www/index.html +0 -606
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../src/storage/sqlite.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../src/storage/sqlite.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,oEAAsC;AACtC,mCAAoC;AACpC,uCAAyB;AACzB,2CAA6B;AAG7B,MAAa,WAAW;IAGc;IAF5B,EAAE,CAAoB;IAE9B,YAAY,MAAc,EAAU,GAAW;QAAX,QAAG,GAAH,GAAG,CAAQ;QAC7C,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,IAAI,CAAC,EAAE,GAAG,IAAI,wBAAQ,CAAC,MAAM,CAAC,CAAC;QAC/B,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACrC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;QACpC,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,iBAAiB;IAET,OAAO;QACb,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAyEZ,CAAC,CAAC;QAEH,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAChD,CAAC;IAEO,aAAa;QACnB,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC,GAAG,EAA6B,CAAC;QAC3F,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,EAAE,CAAC;YAC5C,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC;YAChF,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAC;YAC9E,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAEO,kBAAkB;QACxB,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC,GAAG,EAA6B,CAAC;QAC3F,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,EAAE,CAAC;YACjD,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;YAChE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,wFAAwF,CAAC,CAAC;YAEvG,yBAAyB;YACzB,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,2DAA2D,CAAC,CAAC,GAAG,EAA4C,CAAC;YAC1I,MAAM,UAAU,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,iDAAiD,CAAC,CAAC;YACtF,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;gBACrB,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YAC/C,CAAC;YACD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,yCAAyC,IAAI,CAAC,MAAM,SAAS,CAAC,CAAC;YAC/E,CAAC;QACH,CAAC;IACH,CAAC;IAED,mEAAmE;IACnE,iBAAiB,CAAC,SAAiB;QACjC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,kEAAkE,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACjH,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,IAAY;QAOrB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,CAAC;QAC/C,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;QAExF,MAAM,UAAU,GAAG,IAAI,CAAC,EAAE;aACvB,OAAO,CACN;+DACuD,CACxD;aACA,GAAG,CAAC,KAAK,CAAoC,CAAC;QACjD,MAAM,YAAY,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAExE,MAAM,UAAU,GAAG,IAAI,CAAC,EAAE;aACvB,OAAO,CACN;kFAC0E,CAC3E;aACA,GAAG,CAAC,KAAK,CAAwD,CAAC;QACrE,MAAM,MAAM,GAAG,IAAI,GAAG,EAA4C,CAAC;QACnE,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;YAC3B,IAAI,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1B,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,GAAG,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;gBAC7B,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;YACvB,CAAC;YACD,IAAI,CAAC,CAAC,UAAU,KAAK,MAAM;gBAAE,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;iBACxC,IAAI,CAAC,CAAC,UAAU,KAAK,QAAQ;gBAAE,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC;QACxD,CAAC;QACD,MAAM,iBAAiB,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;aACnD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aACxC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAE5F,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,0DAA0D,CAAC,CAAC,GAAG,EAA4C,CAAC;QAC1I,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,0DAA0D,CAAC,CAAC,GAAG,EAA4C,CAAC;QAC1I,MAAM,aAAa,GAAG,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC9E,MAAM,aAAa,GAAG,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAE9E,MAAM,WAAW,GAAI,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,kCAAkC,CAAC,CAAC,GAAG,EAAoB,CAAC,CAAC,CAAC;QACnG,MAAM,aAAa,GAAI,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,qDAAqD,CAAC,CAAC,GAAG,EAAoB,CAAC,CAAC,CAAC;QACxH,MAAM,eAAe,GAAI,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,sCAAsC,CAAC,CAAC,GAAG,EAAoB,CAAC,CAAC,CAAC;QAC3G,MAAM,WAAW,GAAI,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,wDAAwD,CAAC,CAAC,GAAG,CAAC,UAAU,CAAmB,CAAC,CAAC,CAAC;QACnI,MAAM,gBAAgB,GAAI,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,+DAA+D,CAAC,CAAC,GAAG,CAAC,UAAU,CAAmB,CAAC,CAAC,CAAC;QAE/I,OAAO;YACL,YAAY;YACZ,iBAAiB;YACjB,aAAa;YACb,aAAa;YACb,MAAM,EAAE;gBACN,QAAQ,EAAE,WAAW;gBACrB,QAAQ,EAAE,aAAa;gBACvB,UAAU,EAAE,eAAe;gBAC3B,WAAW;gBACX,gBAAgB;aACjB;SACF,CAAC;IACJ,CAAC;IAED,gBAAgB;IAEhB,WAAW,CAAC,KAAY;QACtB,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;KAG5B,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CACN,KAAK,CAAC,EAAE,EACR,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,MAAM,EACZ,KAAK,CAAC,GAAG,EACT,KAAK,CAAC,IAAI,EACV,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,IAAI,EACV,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,MAAM,EACZ,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,EAC1B,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,SAAS,CAChB,CAAC;IACJ,CAAC;IAED,aAAa,CAAC,OAAe,EAAE,OAAe;QAC5C,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,4DAA4D,CAAC,CAAC,GAAG,CAC/E,OAAO,EACP,IAAI,CAAC,GAAG,EAAE,EACV,OAAO,CACR,CAAC;IACJ,CAAC;IAED,eAAe,CAAC,OAAe,EAAE,MAAgB;QAC/C,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;QACzD,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;KAGf,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,eAAe;IAEf,QAAQ,CAAC,OAAe;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,mCAAmC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAyB,CAAC;QACtG,OAAO,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACtC,CAAC;IAED,cAAc,CAAC,GAAa;QAC1B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,iBAAiB,CAAC,UAAkB,EAAE,MAAc,EAAE,GAAW,EAAE,MAAc;QAC/E,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;;KAI/B,CAAC,CAAC,GAAG,CAAC,UAAU,CAAe,CAAC;QAEjC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CACjC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,MAAM,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,CAC7C,CAAC;QACF,IAAI,SAAS,KAAK,CAAC,CAAC;YAAE,OAAO,EAAE,CAAC;QAEhC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC;QAC7D,OAAO,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACnD,CAAC;IAED,qBAAqB;IAErB,SAAS,CAAC,KAAa,EAAE,KAAa;QACpC,MAAM,SAAS,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,CAAC,SAAS;YAAE,OAAO,EAAE,CAAC;QAE1B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;;;;;OAO5B,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAA8C,CAAC;YAEtE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;YACjC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACtB,OAAO,EAAE,CAAC,CAAC,QAAQ;gBACnB,KAAK,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;aAC1D,CAAC,CAAC,CAAC;QACN,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,0BAA0B,SAAS,oBAAoB,CAAC,CAAC;YACvE,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,mFAAmF;IAEnF,aAAa,CAAC,QAAkB,EAAE,OAA0C,EAAE;QAC5E,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QAE/B,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,CAAC;QAC1D,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,MAAM,MAAM,GAAwB,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChE,IAAI,IAAI,CAAC,IAAI;YAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEnB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;iBAGlB,WAAW,IAAI,UAAU;;;OAGnC,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAmF,CAAC;YAEpG,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACpB,OAAO,EAAE,CAAC,CAAC,QAAQ;gBACnB,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,SAAS,EAAE,CAAC,CAAC,UAAU;aACxB,CAAC,CAAC,CAAC;QACN,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,wBAAwB;IAExB,gBAAgB;QACd,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC1B,qDAAqD,CACtD,CAAC,GAAG,EAAqE,CAAC;QAE3E,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACtB,OAAO,EAAE,CAAC,CAAC,QAAQ;YACnB,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;SACzF,CAAC,CAAC,CAAC;IACN,CAAC;IAED,YAAY,CAAC,OAAe;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CACzB,8DAA8D,CAC/D,CAAC,GAAG,CAAC,OAAO,CAAuD,CAAC;QACrE,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;IAChG,CAAC;IAED,iBAAiB;IAEjB,WAAW,CAAC,OAAe,EAAE,MAA4E;QACvG,MAAM,IAAI,GAAa,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAc,EAAE,CAAC;QAE7B,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACzB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;QACD,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACzB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC9B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACtB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC9B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACtB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QAEpC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACxB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAErB,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC5B,qBAAqB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CACpD,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;QACjB,OAAO,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,iBAAiB;IAEjB,WAAW,CAAC,OAAe;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC/E,OAAO,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,aAAa,CAAC,UAAkB;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,0CAA0C,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC3F,OAAO,MAAM,CAAC,OAAO,CAAC;IACxB,CAAC;IAED,SAAS;QACP,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,GAAG,EAAE,CAAC;QAC5C,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC,GAAG,EAAE,CAAC;QAC3C,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC,GAAG,EAAE,CAAC;QACnD,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACrC,OAAO,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC;IAED,oBAAoB;IAEpB,UAAU,CAAC,IAAU;QACnB,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;KAGf,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IACxH,CAAC;IAED,OAAO,CAAC,MAAc;QACpB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,kCAAkC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAwB,CAAC;QACnG,OAAO,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACrC,CAAC;IAED,aAAa,CAAC,UAAkB;QAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CACzB,kGAAkG,CACnG,CAAC,GAAG,CAAC,UAAU,CAAwB,CAAC;QACzC,OAAO,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACrC,CAAC;IAED,iBAAiB;QACf,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC1B,sEAAsE,CACvE,CAAC,GAAG,EAAe,CAAC;QACrB,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC7B,CAAC;IAED,UAAU,CAAC,MAAc,EAAE,MAAmF;QAC5G,MAAM,IAAI,GAAa,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAc,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAAC,CAAC;QACtF,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAAC,CAAC;QAC5F,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAAC,CAAC;QACzF,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAAC,CAAC;QAC7F,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACpC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACxB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpB,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,oBAAoB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;QAClG,OAAO,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,eAAe,CAAC,MAAc;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,iEAAiE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAe,CAAC;QAC1H,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC9B,CAAC;IAED,SAAS,CAAC,OAA6D,EAAE;QACvE,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,MAAM,MAAM,GAAc,EAAE,CAAC;QAC7B,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAAC,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAAC,CAAC;QAC7E,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAErF,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,mCAAmC,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAkB,CAAC;QACnH,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC;QAEzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;QAChC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC1B,uBAAuB,WAAW,4CAA4C,CAC/E,CAAC,GAAG,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,CAAc,CAAC;QAE7C,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC;IAC/C,CAAC;IAED,iBAAiB,CAAC,MAAc;QAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,oDAAoD,CAAC,CAAC,GAAG,CAAC,MAAM,CAAkB,CAAC;QAC/G,OAAO,GAAG,CAAC,CAAC,CAAC;IACf,CAAC;IAED,cAAc,CAAC,OAAe,EAAE,MAAc;QAC5C,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,4DAA4D,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;IACjH,CAAC;IAED,mBAAmB,CAAC,UAAkB;QACpC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC1B,yFAAyF,CAC1F,CAAC,GAAG,CAAC,UAAU,CAAe,CAAC;QAChC,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC9B,CAAC;IAED;;;;OAIG;IACH,oBAAoB,CAAC,UAAkB,EAAE,IAAY,EAAE,OAAe;QACpE,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CACzB,sFAAsF,CACvF,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAC9B,OAAO,CAAC,CAAC,GAAG,CAAC;IACf,CAAC;IAED,eAAe;IAEf,iBAAiB,CAAC,KAAa;QAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC1B,wDAAwD,CACzD,CAAC,GAAG,CAAC,KAAK,CAA0B,CAAC;QACtC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED,WAAW;QACT,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,oCAAoC,CAAC,CAAC,GAAG,EAAqB,CAAC;QAC3F,OAAO,GAAG,CAAC,GAAG,CAAC;IACjB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;CACF;AA9fD,kCA8fC;AAED,sBAAsB;AAEtB;;;;GAIG;AACH,SAAS,gBAAgB,CAAC,GAAW;IACnC,MAAM,MAAM,GAAG,GAAG;SACf,OAAO,CAAC,mCAAmC,EAAE,GAAG,CAAC;SACjD,KAAK,CAAC,KAAK,CAAC;SACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;SAC5C,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;SAC3B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IAErD,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;AAkB3D,SAAS,UAAU,CAAC,GAAa;IAC/B,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,UAAU,EAAE,GAAG,CAAC,WAAW;QAC3B,MAAM,EAAE,GAAG,CAAC,OAAO;QACnB,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,IAAI,EAAE,GAAG,CAAC,IAAqB;QAC/B,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,IAAI,EAAE,GAAG,CAAC,IAAqB;QAC/B,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,SAAS,EAAE,IAAI;QACf,MAAM,EAAE,GAAG,CAAC,OAAO;QACnB,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,SAAS,EAAE,GAAG,CAAC,UAAU;KAC1B,CAAC;AACJ,CAAC;AAaD,SAAS,SAAS,CAAC,GAAY;IAC7B,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,UAAU,EAAE,GAAG,CAAC,WAAW;QAC3B,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,MAAM,EAAE,GAAG,CAAC,MAAwB;QACpC,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,OAAO,EAAE,GAAG,CAAC,QAAQ;QACrB,SAAS,EAAE,GAAG,CAAC,UAAU;KAC1B,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,OAAe;IAClC,OAAO,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACzE,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -17,9 +17,21 @@ export interface Chunk {
|
|
|
17
17
|
kind: ChunkKind;
|
|
18
18
|
summary: string;
|
|
19
19
|
embedding: number[] | null;
|
|
20
|
+
taskId: string | null;
|
|
20
21
|
createdAt: number;
|
|
21
22
|
updatedAt: number;
|
|
22
23
|
}
|
|
24
|
+
export type TaskStatus = "active" | "completed" | "skipped";
|
|
25
|
+
export interface Task {
|
|
26
|
+
id: string;
|
|
27
|
+
sessionKey: string;
|
|
28
|
+
title: string;
|
|
29
|
+
summary: string;
|
|
30
|
+
status: TaskStatus;
|
|
31
|
+
startedAt: number;
|
|
32
|
+
endedAt: number | null;
|
|
33
|
+
updatedAt: number;
|
|
34
|
+
}
|
|
23
35
|
export type ChunkKind = "paragraph" | "code_block" | "error_stack" | "command" | "list" | "mixed" | "tool_result";
|
|
24
36
|
export interface ChunkRef {
|
|
25
37
|
sessionKey: string;
|
|
@@ -32,6 +44,7 @@ export interface SearchHit {
|
|
|
32
44
|
original_excerpt: string;
|
|
33
45
|
ref: ChunkRef;
|
|
34
46
|
score: number;
|
|
47
|
+
taskId: string | null;
|
|
35
48
|
source: {
|
|
36
49
|
ts: number;
|
|
37
50
|
role: Role;
|
|
@@ -136,6 +149,8 @@ export declare const DEFAULTS: {
|
|
|
136
149
|
readonly localEmbeddingModel: "Xenova/all-MiniLM-L6-v2";
|
|
137
150
|
readonly localEmbeddingDimensions: 384;
|
|
138
151
|
readonly toolResultMaxChars: 2000;
|
|
152
|
+
readonly taskIdleTimeoutMs: number;
|
|
153
|
+
readonly taskSummaryMaxTokens: 2000;
|
|
139
154
|
};
|
|
140
155
|
export interface PluginContext {
|
|
141
156
|
stateDir: string;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
CHANGED
|
@@ -21,5 +21,7 @@ exports.DEFAULTS = {
|
|
|
21
21
|
localEmbeddingModel: "Xenova/all-MiniLM-L6-v2",
|
|
22
22
|
localEmbeddingDimensions: 384,
|
|
23
23
|
toolResultMaxChars: 2000,
|
|
24
|
+
taskIdleTimeoutMs: 2 * 60 * 60 * 1000, // 2 hour gap → new task
|
|
25
|
+
taskSummaryMaxTokens: 2000,
|
|
24
26
|
};
|
|
25
27
|
//# sourceMappingURL=types.js.map
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA,yBAAyB;;;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA,yBAAyB;;;AA2LzB,mBAAmB;AAEN,QAAA,QAAQ,GAAG;IACtB,iBAAiB,EAAE,CAAC;IACpB,aAAa,EAAE,EAAE;IACjB,eAAe,EAAE,IAAI;IACrB,aAAa,EAAE,IAAI;IACnB,IAAI,EAAE,EAAE;IACR,SAAS,EAAE,GAAG;IACd,mBAAmB,EAAE,EAAE;IACvB,wBAAwB,EAAE,IAAI;IAC9B,kBAAkB,EAAE,eAAe;IACnC,eAAe,EAAE,GAAG;IACpB,eAAe,EAAE,GAAG;IACpB,kBAAkB,EAAE,IAAI;IACxB,cAAc,EAAE,IAAI;IACpB,qBAAqB,EAAE,CAAC;IACxB,mBAAmB,EAAE,yBAAyB;IAC9C,wBAAwB,EAAE,GAAG;IAC7B,kBAAkB,EAAE,IAAI;IACxB,iBAAiB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,wBAAwB;IAC/D,oBAAoB,EAAE,IAAI;CAClB,CAAC"}
|
package/dist/viewer/html.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const viewerHTML = "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>OpenClaw Memory - Powered by MemOS</title>\n<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n<link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n<link href=\"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap\" rel=\"stylesheet\">\n<style>\n*{margin:0;padding:0;box-sizing:border-box}\n:root{\n --bg:#050510;--bg-card:rgba(255,255,255,.04);--bg-card-hover:rgba(255,255,255,.07);\n --border:rgba(255,255,255,.08);--border-glow:rgba(0,187,238,.25);\n --text:#f0f4f8;--text-sec:#8b95a5;--text-muted:#5a6373;\n --pri:#00bbee;--pri-glow:rgba(0,187,238,.15);--pri-dark:#0088aa;\n --pri-grad:linear-gradient(135deg,#00bbee,#00a0cc);\n --accent:#e63946;--accent-glow:rgba(230,57,70,.15);\n --green:#10b981;--green-bg:rgba(16,185,129,.12);\n --amber:#f59e0b;--amber-bg:rgba(245,158,11,.12);\n --violet:#8b5cf6;--rose:#f43f5e;--rose-bg:rgba(244,63,94,.12);\n --shadow-sm:0 1px 2px rgba(0,0,0,.2);--shadow:0 4px 12px rgba(0,0,0,.25);\n --shadow-lg:0 20px 40px rgba(0,0,0,.35);\n --radius:12px;--radius-lg:14px;--radius-xl:18px;\n}\nbody{font-family:'Inter',-apple-system,BlinkMacSystemFont,sans-serif;background:var(--bg);color:var(--text);line-height:1.6}\nbutton{cursor:pointer;font-family:inherit;font-size:inherit}\ninput,textarea,select{font-family:inherit;font-size:inherit}\n\n/* \u2500\u2500\u2500 Auth (Linkify \u914D\u8272: globals.css .dark + \u84DD\u7D2B\u6E10\u53D8) \u2500\u2500\u2500 */\n.auth-screen{display:flex;align-items:center;justify-content:center;min-height:100vh;padding:20px;background:linear-gradient(135deg,rgb(36,0,255) 0%,rgb(0,135,255) 35%,rgb(108,39,157) 70%,rgb(105,30,255) 100%);position:relative;overflow:hidden}\n.auth-card{background:hsl(0 0% 100%);border:none;border-radius:8px;padding:48px 40px;width:100%;max-width:420px;box-shadow:0 25px 50px -12px rgba(0,0,0,.25);text-align:center;position:relative;z-index:1}\n.auth-card .logo{width:56px;height:56px;margin:0 auto 20px;display:flex;align-items:center;justify-content:center;font-size:48px;background:none;border-radius:0}\n.auth-card h1{font-size:22px;font-weight:700;margin-bottom:4px;color:hsl(0 0% 3.9%);letter-spacing:-.02em}\n.auth-card p{color:hsl(0 0% 45.1%);margin-bottom:24px;font-size:14px}\n.auth-card input{width:100%;padding:12px 16px;border:1px solid hsl(0 0% 89.8%);border-radius:8px;font-size:14px;transition:all .2s;margin-bottom:10px;outline:none;background:#fff;color:hsl(0 0% 3.9%)}\n.auth-card input::placeholder{color:hsl(0 0% 45.1%)}\n.auth-card input:focus{border-color:rgb(168,85,247);box-shadow:0 0 0 3px rgba(168,85,247,.2)}\n.auth-card .btn-auth{width:100%;padding:12px;border:none;border-radius:8px;background:hsl(0 0% 9%);color:hsl(0 0% 98%);font-weight:600;font-size:14px;transition:all .2s}\n.auth-card .btn-auth:hover{background:hsl(0 0% 14%);transform:translateY(-1px);box-shadow:0 8px 25px rgba(0,0,0,.2)}\n.auth-card .error-msg{color:hsl(0 84.2% 60.2%);font-size:13px;margin-top:8px;min-height:20px}\n.auth-card .btn-text{color:hsl(0 0% 45.1%)}\n.auth-card .btn-text:hover{color:rgb(168,85,247)}\n\n.reset-guide{text-align:left;margin-bottom:20px}\n.reset-step{display:flex;gap:14px;margin-bottom:16px}\n.step-num{width:28px;height:28px;border-radius:50%;background:hsl(0 0% 9%);color:hsl(0 0% 98%);font-size:12px;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}\n.step-body{flex:1;min-width:0}\n.step-title{font-size:14px;font-weight:600;color:hsl(0 0% 3.9%);margin-bottom:2px}\n.step-desc{font-size:13px;color:hsl(0 0% 45.1%);line-height:1.5}\n.cmd-box{margin-top:8px;background:hsl(0 0% 96.1%);border:1px solid hsl(0 0% 89.8%);border-radius:8px;padding:12px 14px;font-size:12px;font-family:ui-monospace,monospace;cursor:pointer;transition:all .15s;display:flex;align-items:center;justify-content:space-between;gap:8px;word-break:break-all;color:hsl(0 0% 3.9%)}\n.cmd-box:hover{border-color:rgb(168,85,247);background:rgba(168,85,247,.08)}\n.cmd-box code{flex:1}\n.copy-hint{font-size:11px;color:hsl(0 0% 45.1%);white-space:nowrap}\n.cmd-box.copied .copy-hint{color:hsl(142 71% 45%)}\n\n/* \u2500\u2500\u2500 App Layout (dark dashboard, same as www) \u2500\u2500\u2500 */\n.app{display:none;flex-direction:column;min-height:100vh}\n.topbar{background:rgba(5,5,16,.85);border-bottom:1px solid var(--border);padding:0 28px;height:64px;display:flex;align-items:center;justify-content:space-between;position:sticky;top:0;z-index:100;backdrop-filter:blur(12px)}\n.topbar .brand{display:flex;align-items:center;gap:12px;font-weight:700;font-size:17px;color:var(--text);letter-spacing:-.02em}\n.topbar .brand .icon{width:38px;height:38px;display:flex;align-items:center;justify-content:center;font-size:26px;background:none;border-radius:0}\n.topbar .actions{display:flex;align-items:center;gap:10px}\n\n.main-content{display:flex;flex:1;max-width:1400px;margin:0 auto;width:100%;padding:28px 32px;gap:28px}\n\n/* \u2500\u2500\u2500 Sidebar \u2500\u2500\u2500 */\n.sidebar{width:260px;flex-shrink:0}\n.sidebar .stats-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:24px}\n.stat-card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:18px;transition:all .2s}\n.stat-card:hover{border-color:var(--border-glow);background:var(--bg-card-hover)}\n.stat-card .stat-value{font-size:22px;font-weight:700;color:var(--text);letter-spacing:-.02em}\n.stat-card .stat-label{font-size:12px;color:var(--text-sec);margin-top:4px;font-weight:500}\n.stat-card.pri .stat-value{color:var(--pri)}\n.stat-card.green .stat-value{color:var(--green)}\n.stat-card.amber .stat-value{color:var(--amber)}\n.stat-card.rose .stat-value{color:var(--rose)}\n\n.sidebar .section-title{font-size:11px;font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:.08em;margin:24px 0 12px;padding:0 2px}\n.sidebar .session-list{display:flex;flex-direction:column;gap:6px;max-height:280px;overflow-y:auto}\n.session-item{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;background:var(--bg-card);border:1px solid var(--border);border-radius:10px;cursor:pointer;transition:all .15s;font-size:13px;color:var(--text)}\n.session-item:hover{border-color:var(--pri);background:var(--pri-glow)}\n.session-item.active{border-color:var(--pri);background:var(--pri-glow);font-weight:600;color:var(--pri)}\n.session-item .count{color:var(--text-sec);font-size:11px;font-weight:600;background:rgba(0,0,0,.2);padding:3px 8px;border-radius:8px}\n\n.provider-badge{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;background:var(--green-bg);color:var(--green);border-radius:999px;font-size:11px;font-weight:600;margin-top:10px}\n.provider-badge.offline{background:var(--amber-bg);color:var(--amber)}\n\n/* \u2500\u2500\u2500 Feed \u2500\u2500\u2500 */\n.feed{flex:1;min-width:0}\n.search-bar{display:flex;gap:12px;margin-bottom:16px;position:relative}\n.search-bar input{flex:1;padding:12px 16px 12px 44px;border:1px solid var(--border);border-radius:12px;font-size:14px;outline:none;background:var(--bg-card);color:var(--text);transition:all .2s}\n.search-bar input::placeholder{color:var(--text-muted)}\n.search-bar input:focus{border-color:var(--pri);box-shadow:0 0 0 3px var(--pri-glow)}\n.search-bar .search-icon{position:absolute;left:16px;top:50%;transform:translateY(-50%);color:var(--text-muted);font-size:15px;pointer-events:none}\n.search-meta{font-size:12px;color:var(--text-sec);margin-bottom:14px;padding:0 2px}\n\n.filter-bar{display:flex;gap:8px;margin-bottom:16px;flex-wrap:wrap}\n.filter-chip{padding:6px 14px;border:1px solid var(--border);border-radius:999px;background:var(--bg-card);color:var(--text-sec);font-size:13px;font-weight:500;transition:all .15s}\n.filter-chip:hover{border-color:var(--pri);color:var(--pri)}\n.filter-chip.active{background:var(--pri);color:#000;border-color:var(--pri)}\n\n.memory-list{display:flex;flex-direction:column;gap:16px}\n.memory-card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:20px 24px;transition:all .2s}\n.memory-card:hover{border-color:var(--border-glow);background:var(--bg-card-hover)}\n.memory-card .card-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;flex-wrap:wrap;gap:8px}\n.memory-card .meta{display:flex;align-items:center;gap:8px}\n.role-tag{padding:4px 10px;border-radius:8px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.03em}\n.role-tag.user{background:var(--pri-glow);color:var(--pri);border:1px solid rgba(0,187,238,.2)}\n.role-tag.assistant{background:var(--accent-glow);color:var(--accent);border:1px solid rgba(230,57,70,.2)}\n.role-tag.system{background:var(--amber-bg);color:var(--amber);border:1px solid rgba(245,158,11,.2)}\n.kind-tag{padding:4px 10px;border-radius:8px;font-size:11px;color:var(--text-sec);background:rgba(0,0,0,.2);font-weight:500}\n.card-time{font-size:12px;color:var(--text-sec);display:flex;align-items:center;gap:8px}\n.session-tag{font-size:11px;font-family:ui-monospace,monospace;color:var(--text-muted);background:rgba(0,0,0,.2);padding:3px 8px;border-radius:6px;cursor:default}\n.card-summary{font-size:15px;font-weight:600;color:var(--text);margin-bottom:10px;line-height:1.5;letter-spacing:-.01em}\n.card-content{font-size:13px;color:var(--text-sec);line-height:1.65;max-height:0;overflow:hidden;transition:max-height .3s ease}\n.card-content.show{max-height:600px;overflow-y:auto}\n.card-content pre{white-space:pre-wrap;word-break:break-all;background:rgba(0,0,0,.25);padding:14px;border-radius:10px;font-size:12px;font-family:ui-monospace,monospace;margin-top:10px;border:1px solid var(--border);color:var(--text-sec)}\n.card-actions{display:flex;align-items:center;gap:8px;margin-top:14px}\n.vscore-badge{display:inline-flex;align-items:center;background:linear-gradient(135deg,var(--pri),var(--violet));color:#fff;font-size:10px;font-weight:700;padding:4px 10px;border-radius:8px;margin-left:auto}\n\n/* \u2500\u2500\u2500 Buttons \u2500\u2500\u2500 */\n.btn{padding:8px 16px;border-radius:10px;border:1px solid var(--border);background:var(--bg-card);color:var(--text);font-size:13px;font-weight:500;transition:all .15s;display:inline-flex;align-items:center;gap:6px}\n.btn:hover{border-color:var(--pri);color:var(--pri)}\n.btn-primary{background:var(--pri);color:#000;border:none}\n.btn-primary:hover{background:#4dd9ff;transform:translateY(-1px);box-shadow:0 6px 20px rgba(0,187,238,.25)}\n.btn-danger{color:var(--accent);border-color:var(--accent)}\n.btn-danger:hover{background:var(--accent);color:#fff;border-color:var(--accent)}\n.btn-sm{padding:6px 12px;font-size:12px}\n.btn-icon{padding:6px 8px;font-size:14px}\n.btn-text{border:none;background:none;color:var(--text-sec);font-size:13px;padding:4px 8px}\n.btn-text:hover{color:var(--pri)}\n\n/* \u2500\u2500\u2500 Modal \u2500\u2500\u2500 */\n.modal-overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:500;align-items:center;justify-content:center;backdrop-filter:blur(8px)}\n.modal-overlay.show{display:flex}\n.modal{background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-xl);padding:32px;width:100%;max-width:520px;box-shadow:var(--shadow-lg);max-height:85vh;overflow-y:auto}\n.modal h2{font-size:20px;font-weight:700;margin-bottom:24px;color:var(--text);letter-spacing:-.02em}\n.form-group{margin-bottom:18px}\n.form-group label{display:block;font-size:13px;font-weight:600;color:var(--text-sec);margin-bottom:6px}\n.form-group input,.form-group textarea,.form-group select{width:100%;padding:10px 14px;border:1px solid var(--border);border-radius:10px;font-size:14px;outline:none;transition:all .2s;background:var(--bg-card);color:var(--text)}\n.form-group input::placeholder,.form-group textarea::placeholder{color:var(--text-muted)}\n.form-group input:focus,.form-group textarea:focus,.form-group select:focus{border-color:var(--pri);box-shadow:0 0 0 3px var(--pri-glow)}\n.form-group textarea{min-height:100px;resize:vertical}\n.modal-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:28px}\n\n/* \u2500\u2500\u2500 Toast \u2500\u2500\u2500 */\n.toast-container{position:fixed;top:80px;right:24px;z-index:1000;display:flex;flex-direction:column;gap:8px}\n.toast{padding:14px 20px;border-radius:10px;font-size:13px;font-weight:500;box-shadow:var(--shadow-lg);animation:slideIn .3s ease;display:flex;align-items:center;gap:10px;max-width:360px;border:1px solid}\n.toast.success{background:var(--green-bg);color:var(--green);border-color:rgba(16,185,129,.3)}\n.toast.error{background:var(--rose-bg);color:var(--rose);border-color:rgba(244,63,94,.3)}\n.toast.info{background:var(--pri-glow);color:var(--pri);border-color:rgba(0,187,238,.3)}\n@keyframes slideIn{from{transform:translateX(100px);opacity:0}to{transform:translateX(0);opacity:1}}\n\n.empty{text-align:center;padding:64px 20px;color:var(--text-sec)}\n.empty .icon{font-size:52px;margin-bottom:16px;opacity:.5}\n.empty p{font-size:15px;font-weight:500}\n\n.spinner{width:40px;height:40px;border:3px solid var(--border);border-top-color:var(--pri);border-radius:50%;animation:spin .8s linear infinite;margin:48px auto}\n@keyframes spin{to{transform:rotate(360deg)}}\n\n::-webkit-scrollbar{width:6px;height:6px}\n::-webkit-scrollbar-track{background:transparent}\n::-webkit-scrollbar-thumb{background:rgba(255,255,255,.15);border-radius:3px}\n::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.25)}\n\n.filter-sep{width:1px;height:20px;background:var(--border);margin:0 4px}\n.filter-select{padding:6px 12px;border:1px solid var(--border);border-radius:999px;background:var(--bg-card);color:var(--text-sec);font-size:13px;outline:none;cursor:pointer}\n.filter-select:focus{border-color:var(--pri)}\n.date-filter{display:flex;align-items:center;gap:10px;margin-bottom:18px;font-size:13px;color:var(--text-sec)}\n.date-filter input[type=\"datetime-local\"]{padding:6px 10px;border:1px solid var(--border);border-radius:8px;font-size:12px;outline:none;background:var(--bg-card);color:var(--text)}\n.date-filter input[type=\"datetime-local\"]:focus{border-color:var(--pri)}\n.date-filter label{font-weight:500}\n\n.pagination{display:flex;align-items:center;justify-content:center;gap:6px;padding:28px 0;flex-wrap:wrap}\n.pagination .pg-btn{min-width:38px;height:38px;display:flex;align-items:center;justify-content:center;border:1px solid var(--border);border-radius:10px;background:var(--bg-card);color:var(--text-sec);font-size:13px;font-weight:500;cursor:pointer;transition:all .15s}\n.pagination .pg-btn:hover{border-color:var(--pri);color:var(--pri)}\n.pagination .pg-btn.active{background:var(--pri);color:#000;border-color:var(--pri)}\n.pagination .pg-btn.disabled{opacity:.4;pointer-events:none}\n.pagination .pg-info{font-size:12px;color:var(--text-sec);padding:0 12px}\n\n@media(max-width:900px){.main-content{flex-direction:column;padding:20px}.sidebar{width:100%}.sidebar .stats-grid{grid-template-columns:repeat(4,1fr)}}\n</style>\n</head>\n<body>\n\n<!-- \u2500\u2500\u2500 Auth: Setup Password \u2500\u2500\u2500 -->\n<div id=\"setupScreen\" class=\"auth-screen\" style=\"display:none\">\n <div class=\"auth-card\">\n <div class=\"logo\">\uD83E\uDD9E</div>\n <h1>OpenClaw Memory</h1>\n <p style=\"font-size:12px;color:var(--text-sec);margin-bottom:6px\">Powered by MemOS</p>\n <p>Set a password to protect your memories</p>\n <input type=\"password\" id=\"setupPw\" placeholder=\"Enter a password (4+ characters)\" autofocus>\n <input type=\"password\" id=\"setupPw2\" placeholder=\"Confirm password\">\n <button class=\"btn-auth\" onclick=\"doSetup()\">Set Password & Enter</button>\n <div class=\"error-msg\" id=\"setupErr\"></div>\n </div>\n</div>\n\n<!-- \u2500\u2500\u2500 Auth: Login \u2500\u2500\u2500 -->\n<div id=\"loginScreen\" class=\"auth-screen\" style=\"display:none\">\n <div class=\"auth-card\">\n <div class=\"logo\">\uD83E\uDD9E</div>\n <h1>OpenClaw Memory</h1>\n <p style=\"font-size:12px;color:var(--text-sec);margin-bottom:6px\">Powered by MemOS</p>\n <p>Enter your password to access memories</p>\n <div id=\"loginForm\">\n <input type=\"password\" id=\"loginPw\" placeholder=\"Password\" autofocus>\n <button class=\"btn-auth\" onclick=\"doLogin()\">Unlock</button>\n <div class=\"error-msg\" id=\"loginErr\"></div>\n <button class=\"btn-text\" style=\"margin-top:12px;font-size:13px;color:var(--text-sec)\" onclick=\"showResetForm()\">Forgot password?</button>\n </div>\n <div id=\"resetForm\" style=\"display:none\">\n <div class=\"reset-guide\">\n <div class=\"reset-step\">\n <div class=\"step-num\">1</div>\n <div class=\"step-body\">\n <div class=\"step-title\">Open Terminal</div>\n <div class=\"step-desc\">Run the following command to get your reset token (use the pattern below so you get the line that contains the token):</div>\n <div class=\"cmd-box\" onclick=\"copyCmd(this)\">\n <code>grep \"password reset token:\" /tmp/openclaw/openclaw-*.log ~/.openclaw/logs/gateway.log 2>/dev/null | tail -1</code>\n <span class=\"copy-hint\">Click to copy</span>\n </div>\n </div>\n </div>\n <div class=\"reset-step\">\n <div class=\"step-num\">2</div>\n <div class=\"step-body\">\n <div class=\"step-title\">Find the token</div>\n <div class=\"step-desc\">In the output, find <span style=\"font-family:monospace;font-size:12px;color:var(--pri)\">password reset token: <strong>a1b2c3d4e5f6...</strong></span> (plain line or inside JSON). Copy the 32-character hex string after the colon.</div>\n </div>\n </div>\n <div class=\"reset-step\">\n <div class=\"step-num\">3</div>\n <div class=\"step-body\">\n <div class=\"step-title\">Paste & reset</div>\n <div class=\"step-desc\">Paste the token below and set your new password.</div>\n </div>\n </div>\n </div>\n <input type=\"text\" id=\"resetToken\" placeholder=\"Paste reset token here\" style=\"margin-bottom:8px;font-family:monospace\">\n <input type=\"password\" id=\"resetNewPw\" placeholder=\"New password (4+ characters)\">\n <input type=\"password\" id=\"resetNewPw2\" placeholder=\"Confirm new password\">\n <button class=\"btn-auth\" onclick=\"doReset()\">Reset Password</button>\n <div class=\"error-msg\" id=\"resetErr\"></div>\n <button class=\"btn-text\" style=\"margin-top:12px;font-size:13px;color:var(--text-sec)\" onclick=\"showLoginForm()\">\u2190 Back to login</button>\n </div>\n </div>\n</div>\n\n<!-- \u2500\u2500\u2500 Main App \u2500\u2500\u2500 -->\n<div class=\"app\" id=\"app\">\n <div class=\"topbar\">\n <div class=\"brand\">\n <div class=\"icon\">\uD83E\uDD9E</div>\n <span>OpenClaw Memory <span style=\"font-weight:400;color:var(--text-sec);font-size:12px\">by MemOS</span></span>\n </div>\n <div class=\"actions\">\n <button class=\"btn btn-primary\" onclick=\"openCreateModal()\">+ New Memory</button>\n <button class=\"btn\" onclick=\"loadAll()\">Refresh</button>\n <button class=\"btn btn-danger\" onclick=\"clearAll()\">Clear All</button>\n <button class=\"btn btn-text\" onclick=\"doLogout()\">Logout</button>\n </div>\n </div>\n\n <div class=\"main-content\">\n <div class=\"sidebar\" id=\"sidebar\">\n <div class=\"stats-grid\" id=\"statsGrid\">\n <div class=\"stat-card pri\"><div class=\"stat-value\" id=\"statTotal\">-</div><div class=\"stat-label\">Memories</div></div>\n <div class=\"stat-card green\"><div class=\"stat-value\" id=\"statSessions\">-</div><div class=\"stat-label\">Sessions</div></div>\n <div class=\"stat-card amber\"><div class=\"stat-value\" id=\"statEmbeddings\">-</div><div class=\"stat-label\">Embeddings</div></div>\n <div class=\"stat-card rose\"><div class=\"stat-value\" id=\"statTimeSpan\">-</div><div class=\"stat-label\">Days</div></div>\n </div>\n <div id=\"embeddingStatus\"></div>\n <div class=\"section-title\">Sessions</div>\n <div class=\"session-list\" id=\"sessionList\"></div>\n </div>\n\n <div class=\"feed\">\n <div class=\"search-bar\">\n <span class=\"search-icon\">\uD83D\uDD0D</span>\n <input type=\"text\" id=\"searchInput\" placeholder=\"Search memories (supports semantic search)...\" oninput=\"debounceSearch()\">\n </div>\n <div class=\"search-meta\" id=\"searchMeta\"></div>\n <div class=\"filter-bar\" id=\"filterBar\">\n <button class=\"filter-chip active\" data-role=\"\" onclick=\"setRoleFilter(this,'')\">All</button>\n <button class=\"filter-chip\" data-role=\"user\" onclick=\"setRoleFilter(this,'user')\">User</button>\n <button class=\"filter-chip\" data-role=\"assistant\" onclick=\"setRoleFilter(this,'assistant')\">Assistant</button>\n <button class=\"filter-chip\" data-role=\"system\" onclick=\"setRoleFilter(this,'system')\">System</button>\n <span class=\"filter-sep\"></span>\n <select id=\"filterKind\" class=\"filter-select\" onchange=\"applyFilters()\">\n <option value=\"\">All kinds</option>\n <option value=\"paragraph\">Paragraph</option>\n <option value=\"code_block\">Code</option>\n <option value=\"dialog\">Dialog</option>\n <option value=\"list\">List</option>\n <option value=\"error_stack\">Error</option>\n <option value=\"command\">Command</option>\n </select>\n <select id=\"filterSort\" class=\"filter-select\" onchange=\"applyFilters()\">\n <option value=\"newest\">Newest first</option>\n <option value=\"oldest\">Oldest first</option>\n </select>\n </div>\n <div class=\"date-filter\">\n <label>From</label><input type=\"datetime-local\" id=\"dateFrom\" step=\"1\" onchange=\"applyFilters()\">\n <label>To</label><input type=\"datetime-local\" id=\"dateTo\" step=\"1\" onchange=\"applyFilters()\">\n <button class=\"btn btn-sm btn-text\" onclick=\"clearDateFilter()\">Clear</button>\n </div>\n <div class=\"memory-list\" id=\"memoryList\"><div class=\"spinner\"></div></div>\n <div class=\"pagination\" id=\"pagination\"></div>\n </div>\n </div>\n</div>\n\n<!-- \u2500\u2500\u2500 Memory Modal \u2500\u2500\u2500 -->\n<div class=\"modal-overlay\" id=\"modalOverlay\">\n <div class=\"modal\">\n <h2 id=\"modalTitle\">New Memory</h2>\n <div class=\"form-group\"><label>Role</label><select id=\"mRole\"><option value=\"user\">User</option><option value=\"assistant\">Assistant</option><option value=\"system\">System</option></select></div>\n <div class=\"form-group\"><label>Content</label><textarea id=\"mContent\" rows=\"4\" placeholder=\"Memory content...\"></textarea></div>\n <div class=\"form-group\"><label>Summary</label><input type=\"text\" id=\"mSummary\" placeholder=\"Brief summary (optional)\"></div>\n <div class=\"form-group\"><label>Kind</label><select id=\"mKind\"><option value=\"paragraph\">Paragraph</option><option value=\"code\">Code</option><option value=\"dialog\">Dialog</option></select></div>\n <div class=\"modal-actions\">\n <button class=\"btn\" onclick=\"closeModal()\">Cancel</button>\n <button class=\"btn btn-primary\" id=\"modalSubmit\" onclick=\"submitModal()\">Create</button>\n </div>\n </div>\n</div>\n\n<!-- \u2500\u2500\u2500 Toast \u2500\u2500\u2500 -->\n<div class=\"toast-container\" id=\"toasts\"></div>\n\n<script>\nlet activeSession=null,activeRole='',editingId=null,searchTimer=null,memoryCache={},currentPage=1,totalPages=1,totalCount=0,PAGE_SIZE=30;\n\n/* \u2500\u2500\u2500 Auth flow \u2500\u2500\u2500 */\nasync function checkAuth(){\n const r=await fetch('/api/auth/status');\n const d=await r.json();\n if(d.needsSetup){\n document.getElementById('setupScreen').style.display='flex';\n document.getElementById('setupPw').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('setupPw2').focus()});\n document.getElementById('setupPw2').addEventListener('keydown',e=>{if(e.key==='Enter')doSetup()});\n } else if(!d.loggedIn){\n document.getElementById('loginScreen').style.display='flex';\n document.getElementById('loginPw').addEventListener('keydown',e=>{if(e.key==='Enter')doLogin()});\n } else {\n enterApp();\n }\n}\n\nasync function doSetup(){\n const pw=document.getElementById('setupPw').value;\n const pw2=document.getElementById('setupPw2').value;\n const err=document.getElementById('setupErr');\n if(pw.length<4){err.textContent='Password must be at least 4 characters';return}\n if(pw!==pw2){err.textContent='Passwords do not match';return}\n const r=await fetch('/api/auth/setup',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({password:pw})});\n const d=await r.json();\n if(d.ok){document.getElementById('setupScreen').style.display='none';enterApp();}\n else{err.textContent=d.error||'Setup failed'}\n}\n\nasync function doLogin(){\n const pw=document.getElementById('loginPw').value;\n const err=document.getElementById('loginErr');\n const r=await fetch('/api/auth/login',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({password:pw})});\n const d=await r.json();\n if(d.ok){document.getElementById('loginScreen').style.display='none';enterApp();}\n else{err.textContent='Incorrect password';document.getElementById('loginPw').value='';document.getElementById('loginPw').focus();}\n}\n\nasync function doLogout(){\n await fetch('/api/auth/logout',{method:'POST'});\n location.reload();\n}\n\nfunction showResetForm(){\n document.getElementById('loginForm').style.display='none';\n document.getElementById('resetForm').style.display='block';\n document.getElementById('resetToken').focus();\n}\n\nfunction showLoginForm(){\n document.getElementById('resetForm').style.display='none';\n document.getElementById('loginForm').style.display='block';\n document.getElementById('loginPw').focus();\n}\n\nfunction copyCmd(el){\n const code=el.querySelector('code').textContent;\n navigator.clipboard.writeText(code).then(()=>{\n el.classList.add('copied');\n el.querySelector('.copy-hint').textContent='Copied!';\n setTimeout(()=>{el.classList.remove('copied');el.querySelector('.copy-hint').textContent='Click to copy'},2000);\n });\n}\n\nasync function doReset(){\n const token=document.getElementById('resetToken').value.trim();\n const pw=document.getElementById('resetNewPw').value;\n const pw2=document.getElementById('resetNewPw2').value;\n const err=document.getElementById('resetErr');\n if(!token){err.textContent='Please enter the reset token';return}\n if(pw.length<4){err.textContent='Password must be at least 4 characters';return}\n if(pw!==pw2){err.textContent='Passwords do not match';return}\n const r=await fetch('/api/auth/reset',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({token,newPassword:pw})});\n const d=await r.json();\n if(d.ok){document.getElementById('loginScreen').style.display='none';enterApp();}\n else{err.textContent=d.error||'Reset failed'}\n}\n\nfunction enterApp(){\n document.getElementById('app').style.display='flex';\n loadAll();\n}\n\n/* \u2500\u2500\u2500 Data loading \u2500\u2500\u2500 */\nasync function loadAll(){\n await Promise.all([loadStats(),loadMemories()]);\n}\n\nasync function loadStats(){\n const r=await fetch('/api/stats');\n const d=await r.json();\n document.getElementById('statTotal').textContent=d.totalMemories;\n document.getElementById('statSessions').textContent=d.totalSessions;\n document.getElementById('statEmbeddings').textContent=d.totalEmbeddings;\n const days=d.timeRange.earliest?Math.max(1,Math.round((new Date(d.timeRange.latest)-new Date(d.timeRange.earliest))/(86400000))):0;\n document.getElementById('statTimeSpan').textContent=days;\n\n const provEl=document.getElementById('embeddingStatus');\n if(d.embeddingProvider && d.embeddingProvider!=='none'){\n provEl.innerHTML='<div class=\"provider-badge\"><span>\\u2713</span> Embedding: '+d.embeddingProvider+'</div>';\n } else {\n provEl.innerHTML='<div class=\"provider-badge offline\"><span>\\u26A0</span> No embedding model</div>';\n }\n\n const sl=document.getElementById('sessionList');\n sl.innerHTML='<div class=\"session-item'+(activeSession===null?' active':'')+'\" onclick=\"filterSession(null)\"><span>All Sessions</span><span class=\"count\">'+d.totalMemories+'</span></div>';\n (d.sessions||[]).forEach(s=>{\n const isActive=activeSession===s.session_key;\n const name=s.session_key.length>20?s.session_key.slice(0,8)+'...'+s.session_key.slice(-8):s.session_key;\n sl.innerHTML+='<div class=\"session-item'+(isActive?' active':'')+'\" onclick=\"filterSession(\\''+s.session_key.replace(/'/g,\"\\\\'\")+'\\')\"><span title=\"'+s.session_key+'\">'+name+'</span><span class=\"count\">'+s.count+'</span></div>';\n });\n}\n\nfunction getFilterParams(){\n const p=new URLSearchParams();\n if(activeSession) p.set('session',activeSession);\n if(activeRole) p.set('role',activeRole);\n const kind=document.getElementById('filterKind').value;\n if(kind) p.set('kind',kind);\n const df=document.getElementById('dateFrom').value;\n if(df) p.set('dateFrom',df);\n const dt=document.getElementById('dateTo').value;\n if(dt) p.set('dateTo',dt);\n const sort=document.getElementById('filterSort').value;\n if(sort==='oldest') p.set('sort','oldest');\n return p;\n}\n\nasync function loadMemories(page){\n if(page) currentPage=page;\n const list=document.getElementById('memoryList');\n list.innerHTML='<div class=\"spinner\"></div>';\n const p=getFilterParams();\n p.set('limit',PAGE_SIZE);\n p.set('page',currentPage);\n const r=await fetch('/api/memories?'+p.toString());\n const d=await r.json();\n totalPages=d.totalPages||1;\n totalCount=d.total||0;\n document.getElementById('searchMeta').textContent=totalCount+' memories total';\n renderMemories(d.memories||[]);\n renderPagination();\n}\n\nasync function doSearch(q){\n if(!q.trim()){currentPage=1;loadMemories();return}\n const list=document.getElementById('memoryList');\n list.innerHTML='<div class=\"spinner\"></div>';\n const p=getFilterParams();\n p.set('q',q);\n const r=await fetch('/api/search?'+p.toString());\n const d=await r.json();\n const meta=[];\n if(d.vectorCount>0) meta.push(d.vectorCount+' semantic');\n if(d.ftsCount>0) meta.push(d.ftsCount+' text');\n meta.push(d.total+' results');\n document.getElementById('searchMeta').textContent=meta.join(' \\u00B7 ');\n renderMemories(d.results||[]);\n document.getElementById('pagination').innerHTML='';\n}\n\nfunction debounceSearch(){\n clearTimeout(searchTimer);\n searchTimer=setTimeout(()=>doSearch(document.getElementById('searchInput').value),350);\n}\n\nfunction filterSession(key){\n activeSession=key;\n currentPage=1;\n loadAll();\n}\n\nfunction setRoleFilter(btn,role){\n activeRole=role;\n currentPage=1;\n document.querySelectorAll('.filter-chip').forEach(c=>c.classList.remove('active'));\n btn.classList.add('active');\n applyFilters();\n}\n\nfunction applyFilters(){\n currentPage=1;\n if(document.getElementById('searchInput').value.trim()){\n doSearch(document.getElementById('searchInput').value);\n } else {\n loadMemories();\n }\n}\n\nfunction clearDateFilter(){\n document.getElementById('dateFrom').value='';\n document.getElementById('dateTo').value='';\n applyFilters();\n}\n\n/* \u2500\u2500\u2500 Rendering \u2500\u2500\u2500 */\nfunction renderMemories(items){\n const list=document.getElementById('memoryList');\n if(!items.length){\n list.innerHTML='<div class=\"empty\"><div class=\"icon\">\\u{1F4ED}</div><p>No memories found</p></div>';\n return;\n }\n items.forEach(m=>{memoryCache[m.id]=m});\n list.innerHTML=items.map(m=>{\n const time=m.created_at?new Date(typeof m.created_at==='number'?m.created_at:m.created_at).toLocaleString('zh-CN'):'';\n const role=m.role||'user';\n const kind=m.kind||'paragraph';\n const summary=esc(m.summary||m.content?.slice(0,120)||'');\n const content=esc(m.content||'');\n const id=m.id;\n const vscore=m._vscore?'<span class=\"vscore-badge\">'+Math.round(m._vscore*100)+'%</span>':'';\n const sid=m.session_key||'';\n const sidShort=sid.length>18?sid.slice(0,6)+'..'+sid.slice(-6):sid;\n return '<div class=\"memory-card\">'+\n '<div class=\"card-header\"><div class=\"meta\"><span class=\"role-tag '+role+'\">'+role+'</span><span class=\"kind-tag\">'+kind+'</span></div><span class=\"card-time\"><span class=\"session-tag\" title=\"'+esc(sid)+'\">'+esc(sidShort)+'</span> '+time+'</span></div>'+\n '<div class=\"card-summary\">'+summary+'</div>'+\n '<div class=\"card-content\" id=\"content-'+id+'\"><pre>'+content+'</pre></div>'+\n '<div class=\"card-actions\">'+\n '<button class=\"btn btn-sm btn-text\" onclick=\"toggleContent(\\''+id+'\\')\">Expand</button>'+\n '<button class=\"btn btn-sm\" onclick=\"openEditModal(\\''+id+'\\')\">Edit</button>'+\n '<button class=\"btn btn-sm btn-danger\" onclick=\"deleteMemory(\\''+id+'\\')\">Delete</button>'+\n vscore+\n '</div></div>';\n }).join('');\n}\n\nfunction renderPagination(){\n const el=document.getElementById('pagination');\n if(totalPages<=1){el.innerHTML='';return}\n let h='';\n h+='<button class=\"pg-btn'+(currentPage<=1?' disabled':'')+'\" onclick=\"goPage('+(currentPage-1)+')\">\u2039</button>';\n const range=[];\n range.push(1);\n for(let i=Math.max(2,currentPage-2);i<=Math.min(totalPages-1,currentPage+2);i++) range.push(i);\n if(totalPages>1) range.push(totalPages);\n const unique=[...new Set(range)].sort((a,b)=>a-b);\n let prev=0;\n for(const p of unique){\n if(p-prev>1) h+='<span class=\"pg-info\">...</span>';\n h+='<button class=\"pg-btn'+(p===currentPage?' active':'')+'\" onclick=\"goPage('+p+')\">'+p+'</button>';\n prev=p;\n }\n h+='<button class=\"pg-btn'+(currentPage>=totalPages?' disabled':'')+'\" onclick=\"goPage('+(currentPage+1)+')\">\u203A</button>';\n h+='<span class=\"pg-info\">'+totalCount+' total</span>';\n el.innerHTML=h;\n}\n\nfunction goPage(p){\n if(p<1||p>totalPages||p===currentPage) return;\n currentPage=p;\n loadMemories();\n document.getElementById('memoryList').scrollIntoView({behavior:'smooth',block:'start'});\n}\n\nfunction toggleContent(id){\n const el=document.getElementById('content-'+id);\n el.classList.toggle('show');\n}\n\nfunction esc(s){\n if(!s)return'';\n return s.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/\"/g,'"');\n}\n\n/* \u2500\u2500\u2500 CRUD \u2500\u2500\u2500 */\nfunction openCreateModal(){\n editingId=null;\n document.getElementById('modalTitle').textContent='New Memory';\n document.getElementById('modalSubmit').textContent='Create';\n document.getElementById('mRole').value='user';\n document.getElementById('mContent').value='';\n document.getElementById('mSummary').value='';\n document.getElementById('mKind').value='paragraph';\n document.getElementById('modalOverlay').classList.add('show');\n}\n\nfunction openEditModal(id){\n const m=memoryCache[id];\n if(!m){toast('Memory not found in cache','error');return}\n editingId=id;\n document.getElementById('modalTitle').textContent='Edit Memory';\n document.getElementById('modalSubmit').textContent='Save';\n document.getElementById('mRole').value=m.role||'user';\n document.getElementById('mContent').value=m.content||'';\n document.getElementById('mSummary').value=m.summary||'';\n document.getElementById('mKind').value=m.kind||'paragraph';\n document.getElementById('modalOverlay').classList.add('show');\n}\n\nfunction closeModal(){\n document.getElementById('modalOverlay').classList.remove('show');\n}\n\nasync function submitModal(){\n const data={\n role:document.getElementById('mRole').value,\n content:document.getElementById('mContent').value,\n summary:document.getElementById('mSummary').value,\n kind:document.getElementById('mKind').value,\n };\n if(!data.content.trim()){toast('Please enter content','error');return}\n let r;\n if(editingId){\n r=await fetch('/api/memory/'+editingId,{method:'PUT',headers:{'Content-Type':'application/json'},body:JSON.stringify(data)});\n } else {\n r=await fetch('/api/memory',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(data)});\n }\n const d=await r.json();\n if(d.ok){toast(editingId?'Memory updated':'Memory created','success');closeModal();loadAll();}\n else{toast(d.error||'Operation failed','error')}\n}\n\nasync function deleteMemory(id){\n if(!confirm('Delete this memory?'))return;\n const r=await fetch('/api/memory/'+id,{method:'DELETE'});\n const d=await r.json();\n if(d.ok){toast('Memory deleted','success');loadAll();}\n else{toast('Delete failed','error')}\n}\n\nasync function clearAll(){\n if(!confirm('Delete ALL memories? This cannot be undone.'))return;\n if(!confirm('Are you absolutely sure?'))return;\n const r=await fetch('/api/memories',{method:'DELETE'});\n const d=await r.json();\n if(d.ok){toast('All memories cleared','success');loadAll();}\n else{toast('Clear failed','error')}\n}\n\n/* \u2500\u2500\u2500 Toast \u2500\u2500\u2500 */\nfunction toast(msg,type='info'){\n const c=document.getElementById('toasts');\n const t=document.createElement('div');\n t.className='toast '+type;\n const icons={success:'\\u2705',error:'\\u274C',info:'\\u2139\\uFE0F'};\n t.innerHTML=(icons[type]||'')+' '+esc(msg);\n c.appendChild(t);\n setTimeout(()=>t.remove(),3500);\n}\n\n/* \u2500\u2500\u2500 Init \u2500\u2500\u2500 */\ndocument.getElementById('modalOverlay').addEventListener('click',e=>{if(e.target.id==='modalOverlay')closeModal()});\ndocument.getElementById('searchInput').addEventListener('keydown',e=>{if(e.key==='Escape'){e.target.value='';loadMemories()}});\ncheckAuth();\n</script>\n</body>\n</html>";
|
|
1
|
+
export declare const viewerHTML = "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>OpenClaw Memory - Powered by MemOS</title>\n<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n<link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n<link href=\"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap\" rel=\"stylesheet\">\n<style>\n*{margin:0;padding:0;box-sizing:border-box}\n:root{\n --bg:#050510;--bg-card:rgba(255,255,255,.04);--bg-card-hover:rgba(255,255,255,.07);\n --border:rgba(255,255,255,.08);--border-glow:rgba(0,187,238,.25);\n --text:#f0f4f8;--text-sec:#8b95a5;--text-muted:#5a6373;\n --pri:#00bbee;--pri-glow:rgba(0,187,238,.15);--pri-dark:#0088aa;\n --pri-grad:linear-gradient(135deg,#00bbee,#00a0cc);\n --accent:#e63946;--accent-glow:rgba(230,57,70,.15);\n --green:#10b981;--green-bg:rgba(16,185,129,.12);\n --amber:#f59e0b;--amber-bg:rgba(245,158,11,.12);\n --violet:#8b5cf6;--rose:#f43f5e;--rose-bg:rgba(244,63,94,.12);\n --shadow-sm:0 1px 2px rgba(0,0,0,.2);--shadow:0 4px 12px rgba(0,0,0,.25);\n --shadow-lg:0 20px 40px rgba(0,0,0,.35);\n --radius:12px;--radius-lg:14px;--radius-xl:18px;\n}\n[data-theme=\"light\"]{\n --bg:#f1f5f9;--bg-card:#fff;--bg-card-hover:#f8fafc;\n --border:rgba(0,0,0,.08);--border-glow:rgba(0,187,238,.4);\n --text:#0f172a;--text-sec:#475569;--text-muted:#64748b;\n --pri:#0891b2;--pri-glow:rgba(8,145,178,.12);--pri-dark:#0e7490;\n --pri-grad:linear-gradient(135deg,#0891b2,#0e7490);\n --accent:#dc2626;--accent-glow:rgba(220,38,38,.1);\n --green:#059669;--green-bg:rgba(5,150,105,.1);\n --amber:#d97706;--amber-bg:rgba(217,119,6,.1);\n --violet:#7c3aed;--rose:#e11d48;--rose-bg:rgba(225,29,72,.1);\n --shadow-sm:0 1px 2px rgba(0,0,0,.06);--shadow:0 4px 12px rgba(0,0,0,.08);\n --shadow-lg:0 20px 40px rgba(0,0,0,.12);\n}\n[data-theme=\"light\"] .auth-screen{background:linear-gradient(135deg,#e0f2fe 0%,#f0f9ff 50%,#e0e7ff 100%)}\n[data-theme=\"light\"] .auth-card{box-shadow:0 25px 50px -12px rgba(0,0,0,.12)}\n[data-theme=\"light\"] .topbar{background:rgba(255,255,255,.95);border-bottom-color:var(--border)}\n[data-theme=\"light\"] .session-item .count,[data-theme=\"light\"] .kind-tag,[data-theme=\"light\"] .session-tag{background:rgba(0,0,0,.06)}\n[data-theme=\"light\"] .card-content pre{background:rgba(0,0,0,.05);border-color:var(--border)}\n[data-theme=\"light\"] .vscore-badge{background:rgba(59,130,246,.1);color:#3b82f6}\n[data-theme=\"light\"] ::-webkit-scrollbar-thumb{background:rgba(0,0,0,.2)}\n[data-theme=\"light\"] .analytics-card{background:linear-gradient(145deg,#fff 0%,#f8fafc 100%);border-color:rgba(0,0,0,.08)}\n[data-theme=\"light\"] .analytics-section{background:#fff;border-color:rgba(0,0,0,.08)}\n[data-theme=\"light\"] .breakdown-item{background:rgba(0,0,0,.04)}\n[data-theme=\"light\"] .metrics-toolbar .range-btn{background:#fff;border-color:rgba(0,0,0,.1)}\n[data-theme=\"light\"] .metrics-toolbar .range-btn.active{background:rgba(0,0,0,.06);color:var(--text);border-color:rgba(0,0,0,.15)}\n[data-theme=\"light\"] .metrics-toolbar .range-btn:hover{border-color:var(--pri);color:var(--pri)}\nbody{font-family:'Inter',-apple-system,BlinkMacSystemFont,sans-serif;background:var(--bg);color:var(--text);line-height:1.6;transition:background .2s,color .2s}\nbutton{cursor:pointer;font-family:inherit;font-size:inherit}\ninput,textarea,select{font-family:inherit;font-size:inherit}\n\n/* \u2500\u2500\u2500 Auth (Linkify \u914D\u8272: globals.css .dark + \u84DD\u7D2B\u6E10\u53D8) \u2500\u2500\u2500 */\n.auth-screen{display:flex;align-items:center;justify-content:center;min-height:100vh;padding:20px;background:linear-gradient(135deg,rgb(36,0,255) 0%,rgb(0,135,255) 35%,rgb(108,39,157) 70%,rgb(105,30,255) 100%);position:relative;overflow:hidden}\n.auth-card{background:hsl(0 0% 100%);border:none;border-radius:8px;padding:48px 40px;width:100%;max-width:420px;box-shadow:0 25px 50px -12px rgba(0,0,0,.25);text-align:center;position:relative;z-index:1}\n.auth-card .logo{width:56px;height:56px;margin:0 auto 20px;display:flex;align-items:center;justify-content:center;font-size:48px;background:none;border-radius:0}\n.auth-card h1{font-size:22px;font-weight:700;margin-bottom:4px;color:hsl(0 0% 3.9%);letter-spacing:-.02em}\n.auth-card p{color:hsl(0 0% 45.1%);margin-bottom:24px;font-size:14px}\n.auth-card input{width:100%;padding:12px 16px;border:1px solid hsl(0 0% 89.8%);border-radius:8px;font-size:14px;transition:all .2s;margin-bottom:10px;outline:none;background:#fff;color:hsl(0 0% 3.9%)}\n.auth-card input::placeholder{color:hsl(0 0% 45.1%)}\n.auth-card input:focus{border-color:#3b82f6;box-shadow:0 0 0 3px rgba(59,130,246,.15)}\n.auth-card .btn-auth{width:100%;padding:12px;border:none;border-radius:8px;background:#3b82f6;color:#fff;font-weight:600;font-size:14px;transition:all .2s}\n.auth-card .btn-auth:hover{background:#2563eb;transform:translateY(-1px);box-shadow:0 8px 25px rgba(59,130,246,.3)}\n.auth-card .error-msg{color:hsl(0 84.2% 60.2%);font-size:13px;margin-top:8px;min-height:20px}\n.auth-card .btn-text{color:hsl(0 0% 45.1%)}\n.auth-card .btn-text:hover{color:#3b82f6}\n\n.reset-guide{text-align:left;margin-bottom:20px}\n.reset-step{display:flex;gap:14px;margin-bottom:16px}\n.step-num{width:28px;height:28px;border-radius:50%;background:hsl(0 0% 9%);color:hsl(0 0% 98%);font-size:12px;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}\n.step-body{flex:1;min-width:0}\n.step-title{font-size:14px;font-weight:600;color:hsl(0 0% 3.9%);margin-bottom:2px}\n.step-desc{font-size:13px;color:hsl(0 0% 45.1%);line-height:1.5}\n.cmd-box{margin-top:8px;background:hsl(0 0% 96.1%);border:1px solid hsl(0 0% 89.8%);border-radius:8px;padding:12px 14px;font-size:12px;font-family:ui-monospace,monospace;cursor:pointer;transition:all .15s;display:flex;align-items:center;justify-content:space-between;gap:8px;word-break:break-all;color:hsl(0 0% 3.9%)}\n.cmd-box:hover{border-color:rgb(168,85,247);background:rgba(168,85,247,.08)}\n.cmd-box code{flex:1}\n.copy-hint{font-size:11px;color:hsl(0 0% 45.1%);white-space:nowrap}\n.cmd-box.copied .copy-hint{color:hsl(142 71% 45%)}\n\n/* \u2500\u2500\u2500 App Layout (dark dashboard, same as www) \u2500\u2500\u2500 */\n.app{display:none;flex-direction:column;min-height:100vh}\n.topbar{background:rgba(5,5,16,.92);border-bottom:1px solid var(--border);padding:0 28px;height:56px;display:flex;align-items:center;position:sticky;top:0;z-index:100;backdrop-filter:blur(16px)}\n.topbar .brand{display:flex;align-items:center;gap:10px;font-weight:700;font-size:15px;color:var(--text);letter-spacing:-.02em;flex-shrink:0}\n.topbar .brand .icon{width:32px;height:32px;display:flex;align-items:center;justify-content:center;font-size:22px;background:none;border-radius:0}\n.topbar .brand .sub{font-weight:400;color:var(--text-muted);font-size:11px}\n.topbar-center{flex:1;display:flex;justify-content:center}\n.topbar .actions{display:flex;align-items:center;gap:6px;flex-shrink:0}\n\n.main-content{display:flex;flex:1;max-width:1400px;margin:0 auto;width:100%;padding:28px 32px;gap:28px}\n\n/* \u2500\u2500\u2500 Sidebar \u2500\u2500\u2500 */\n.sidebar{width:260px;flex-shrink:0}\n.sidebar .stats-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:24px}\n.stat-card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:18px;transition:all .2s}\n.stat-card:hover{border-color:var(--border-glow);background:var(--bg-card-hover)}\n.stat-card .stat-value{font-size:22px;font-weight:700;color:var(--text);letter-spacing:-.02em}\n.stat-card .stat-label{font-size:12px;color:var(--text-sec);margin-top:4px;font-weight:500}\n.stat-card.pri .stat-value{color:var(--pri)}\n.stat-card.green .stat-value{color:var(--green)}\n.stat-card.amber .stat-value{color:var(--amber)}\n.stat-card.rose .stat-value{color:var(--rose)}\n\n.sidebar .section-title{font-size:11px;font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:.08em;margin:24px 0 12px;padding:0 2px}\n.sidebar .session-list{display:flex;flex-direction:column;gap:6px;max-height:280px;overflow-y:auto}\n.session-item{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;background:var(--bg-card);border:1px solid var(--border);border-radius:10px;cursor:pointer;transition:all .15s;font-size:13px;color:var(--text)}\n.session-item:hover{border-color:var(--pri);background:var(--pri-glow)}\n.session-item.active{border-color:var(--pri);background:var(--pri-glow);font-weight:600;color:var(--pri)}\n.session-item .count{color:var(--text-sec);font-size:11px;font-weight:600;background:rgba(0,0,0,.2);padding:3px 8px;border-radius:8px}\n\n.provider-badge{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;background:var(--green-bg);color:var(--green);border-radius:999px;font-size:11px;font-weight:600;margin-top:10px}\n.provider-badge.offline{background:var(--amber-bg);color:var(--amber)}\n\n/* \u2500\u2500\u2500 Feed \u2500\u2500\u2500 */\n.feed{flex:1;min-width:0}\n.search-bar{display:flex;gap:10px;margin-bottom:16px;position:relative;align-items:center}\n.search-bar input{flex:1;padding:10px 16px 10px 40px;border:1px solid var(--border);border-radius:10px;font-size:14px;outline:none;background:var(--bg-card);color:var(--text);transition:all .2s}\n.search-bar input::placeholder{color:var(--text-muted)}\n.search-bar input:focus{border-color:var(--pri);box-shadow:0 0 0 3px var(--pri-glow)}\n.search-bar .search-icon{position:absolute;left:14px;top:50%;transform:translateY(-50%);color:var(--text-muted);font-size:14px;pointer-events:none}\n.search-meta{font-size:12px;color:var(--text-sec);margin-bottom:14px;padding:0 2px}\n\n.filter-bar{display:flex;gap:8px;margin-bottom:16px;flex-wrap:wrap}\n.filter-chip{padding:6px 14px;border:1px solid var(--border);border-radius:999px;background:var(--bg-card);color:var(--text-sec);font-size:13px;font-weight:500;transition:all .15s}\n.filter-chip:hover{border-color:var(--pri);color:var(--pri)}\n.filter-chip.active{background:var(--pri);color:#000;border-color:var(--pri)}\n\n.memory-list{display:flex;flex-direction:column;gap:16px}\n.memory-card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:20px 24px;transition:all .2s}\n.memory-card:hover{border-color:var(--border-glow);background:var(--bg-card-hover)}\n.memory-card .card-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;flex-wrap:wrap;gap:8px}\n.memory-card .meta{display:flex;align-items:center;gap:8px}\n.role-tag{padding:4px 10px;border-radius:8px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.03em}\n.role-tag.user{background:var(--pri-glow);color:var(--pri);border:1px solid rgba(0,187,238,.2)}\n.role-tag.assistant{background:var(--accent-glow);color:var(--accent);border:1px solid rgba(230,57,70,.2)}\n.role-tag.system{background:var(--amber-bg);color:var(--amber);border:1px solid rgba(245,158,11,.2)}\n.kind-tag{padding:4px 10px;border-radius:8px;font-size:11px;color:var(--text-sec);background:rgba(0,0,0,.2);font-weight:500}\n.card-time{font-size:12px;color:var(--text-sec);display:flex;align-items:center;gap:8px}\n.session-tag{font-size:11px;font-family:ui-monospace,monospace;color:var(--text-muted);background:rgba(0,0,0,.2);padding:3px 8px;border-radius:6px;cursor:default}\n.card-summary{font-size:15px;font-weight:600;color:var(--text);margin-bottom:10px;line-height:1.5;letter-spacing:-.01em}\n.card-content{font-size:13px;color:var(--text-sec);line-height:1.65;max-height:0;overflow:hidden;transition:max-height .3s ease}\n.card-content.show{max-height:600px;overflow-y:auto}\n.card-content pre{white-space:pre-wrap;word-break:break-all;background:rgba(0,0,0,.25);padding:14px;border-radius:10px;font-size:12px;font-family:ui-monospace,monospace;margin-top:10px;border:1px solid var(--border);color:var(--text-sec)}\n.card-actions{display:flex;align-items:center;gap:8px;margin-top:14px}\n.vscore-badge{display:inline-flex;align-items:center;background:rgba(59,130,246,.15);color:#60a5fa;font-size:10px;font-weight:700;padding:4px 10px;border-radius:8px;margin-left:auto}\n\n/* \u2500\u2500\u2500 Buttons \u2500\u2500\u2500 */\n.btn{padding:7px 14px;border-radius:8px;border:1px solid var(--border);background:var(--bg-card);color:var(--text);font-size:13px;font-weight:500;transition:all .18s ease;display:inline-flex;align-items:center;gap:5px;white-space:nowrap}\n.btn:hover{border-color:var(--pri);color:var(--pri)}\n.btn-primary{background:rgba(255,255,255,.08);color:var(--text);border:1px solid var(--border);font-weight:600}\n.btn-primary:hover{background:rgba(255,255,255,.14);transform:translateY(-1px);border-color:var(--pri);color:var(--pri)}\n.btn-ghost{border-color:transparent;background:transparent;color:var(--text-sec)}\n.btn-ghost:hover{background:rgba(255,255,255,.06);color:var(--text)}\n.btn-danger{color:var(--accent);border-color:rgba(230,57,70,.25)}\n.btn-danger:hover{background:rgba(230,57,70,.1);color:var(--accent)}\n.btn-sm{padding:5px 12px;font-size:12px}\n.btn-icon{padding:5px 7px;font-size:15px;border-radius:8px}\n.btn-text{border:none;background:none;color:var(--text-muted);font-size:12px;padding:4px 8px}\n.btn-text:hover{color:var(--pri)}\n[data-theme=\"light\"] .btn-primary{background:rgba(0,0,0,.05);color:var(--text);border-color:rgba(0,0,0,.12)}\n[data-theme=\"light\"] .btn-primary:hover{background:rgba(0,0,0,.08);border-color:var(--pri);color:var(--pri)}\n[data-theme=\"light\"] .btn-ghost{color:var(--text-sec)}\n[data-theme=\"light\"] .btn-ghost:hover{background:rgba(0,0,0,.04);color:var(--text)}\n\n/* \u2500\u2500\u2500 Modal \u2500\u2500\u2500 */\n.modal-overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:500;align-items:center;justify-content:center;backdrop-filter:blur(8px)}\n.modal-overlay.show{display:flex}\n.modal{background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-xl);padding:32px;width:100%;max-width:520px;box-shadow:var(--shadow-lg);max-height:85vh;overflow-y:auto}\n.modal h2{font-size:20px;font-weight:700;margin-bottom:24px;color:var(--text);letter-spacing:-.02em}\n.form-group{margin-bottom:18px}\n.form-group label{display:block;font-size:13px;font-weight:600;color:var(--text-sec);margin-bottom:6px}\n.form-group input,.form-group textarea,.form-group select{width:100%;padding:10px 14px;border:1px solid var(--border);border-radius:10px;font-size:14px;outline:none;transition:all .2s;background:var(--bg-card);color:var(--text)}\n.form-group input::placeholder,.form-group textarea::placeholder{color:var(--text-muted)}\n.form-group input:focus,.form-group textarea:focus,.form-group select:focus{border-color:var(--pri);box-shadow:0 0 0 3px var(--pri-glow)}\n.form-group textarea{min-height:100px;resize:vertical}\n.modal-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:28px}\n\n/* \u2500\u2500\u2500 Toast \u2500\u2500\u2500 */\n.toast-container{position:fixed;top:80px;right:24px;z-index:1000;display:flex;flex-direction:column;gap:8px}\n.toast{padding:14px 20px;border-radius:10px;font-size:13px;font-weight:500;box-shadow:var(--shadow-lg);animation:slideIn .3s ease;display:flex;align-items:center;gap:10px;max-width:360px;border:1px solid}\n.toast.success{background:var(--green-bg);color:var(--green);border-color:rgba(16,185,129,.3)}\n.toast.error{background:var(--rose-bg);color:var(--rose);border-color:rgba(244,63,94,.3)}\n.toast.info{background:var(--pri-glow);color:var(--pri);border-color:rgba(0,187,238,.3)}\n@keyframes slideIn{from{transform:translateX(100px);opacity:0}to{transform:translateX(0);opacity:1}}\n\n.empty{text-align:center;padding:64px 20px;color:var(--text-sec)}\n.empty .icon{font-size:52px;margin-bottom:16px;opacity:.5}\n.empty p{font-size:15px;font-weight:500}\n\n.spinner{width:40px;height:40px;border:3px solid var(--border);border-top-color:var(--pri);border-radius:50%;animation:spin .8s linear infinite;margin:48px auto}\n@keyframes spin{to{transform:rotate(360deg)}}\n\n::-webkit-scrollbar{width:6px;height:6px}\n::-webkit-scrollbar-track{background:transparent}\n::-webkit-scrollbar-thumb{background:rgba(255,255,255,.15);border-radius:3px}\n::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.25)}\n\n.filter-sep{width:1px;height:20px;background:var(--border);margin:0 4px}\n.filter-select{padding:6px 12px;border:1px solid var(--border);border-radius:999px;background:var(--bg-card);color:var(--text-sec);font-size:13px;outline:none;cursor:pointer}\n.filter-select:focus{border-color:var(--pri)}\n.date-filter{display:flex;align-items:center;gap:10px;margin-bottom:18px;font-size:13px;color:var(--text-sec)}\n.date-filter input[type=\"datetime-local\"]{padding:6px 10px;border:1px solid var(--border);border-radius:8px;font-size:12px;outline:none;background:var(--bg-card);color:var(--text)}\n.date-filter input[type=\"datetime-local\"]:focus{border-color:var(--pri)}\n.date-filter label{font-weight:500}\n\n.pagination{display:flex;align-items:center;justify-content:center;gap:6px;padding:28px 0;flex-wrap:wrap}\n.pagination .pg-btn{min-width:38px;height:38px;display:flex;align-items:center;justify-content:center;border:1px solid var(--border);border-radius:10px;background:var(--bg-card);color:var(--text-sec);font-size:13px;font-weight:500;cursor:pointer;transition:all .15s}\n.pagination .pg-btn:hover{border-color:var(--pri);color:var(--pri)}\n.pagination .pg-btn.active{background:var(--pri);color:#000;border-color:var(--pri)}\n.pagination .pg-btn.disabled{opacity:.4;pointer-events:none}\n.pagination .pg-info{font-size:12px;color:var(--text-sec);padding:0 12px}\n\n/* \u2500\u2500\u2500 Tasks \u89C6\u56FE \u2500\u2500\u2500 */\n.tasks-view{display:none;flex:1;min-width:0;flex-direction:column;gap:16px}\n.tasks-view.show{display:flex}\n.tasks-header{display:flex;flex-direction:column;gap:14px}\n.tasks-stats{display:flex;gap:16px}\n.tasks-stat{display:flex;align-items:center;gap:8px;background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:12px 18px;flex:1;transition:all .2s}\n.tasks-stat:hover{border-color:var(--border-glow)}\n.tasks-stat-value{font-size:22px;font-weight:700;color:var(--text)}\n.tasks-stat-label{font-size:12px;color:var(--text-sec);font-weight:500}\n.tasks-filters{display:flex;align-items:center;gap:6px;flex-wrap:wrap}\n.tasks-list{display:flex;flex-direction:column;gap:10px}\n.task-card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:18px 20px;cursor:pointer;transition:all .25s;position:relative;overflow:hidden}\n.task-card:hover{border-color:var(--border-glow);background:var(--bg-card-hover);transform:translateY(-1px);box-shadow:var(--shadow)}\n.task-card::before{content:'';position:absolute;top:0;left:0;bottom:0;width:3px;border-radius:3px 0 0 3px}\n.task-card.status-active::before{background:var(--green)}\n.task-card.status-completed::before{background:var(--pri)}\n.task-card.status-skipped::before{background:var(--text-muted)}\n.task-card.status-skipped{opacity:.6}\n.task-card-top{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:8px}\n.task-card-title{font-size:14px;font-weight:600;color:var(--text);line-height:1.4;flex:1;word-break:break-word}\n.task-card-title:empty::after{content:'Untitled Task';color:var(--text-muted);font-style:italic}\n.task-status-badge{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;padding:3px 10px;border-radius:20px;flex-shrink:0}\n.task-status-badge.active{color:var(--green);background:var(--green-bg)}\n.task-status-badge.completed{color:var(--pri);background:var(--pri-glow)}\n.task-status-badge.skipped{color:var(--text-muted);background:rgba(128,128,128,.15)}\n.task-card-summary{font-size:13px;color:var(--text-sec);line-height:1.5;margin-bottom:10px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}\n.task-card-summary:empty{display:none}\n.task-card-bottom{display:flex;align-items:center;gap:14px;font-size:11px;color:var(--text-muted)}\n.task-card-bottom .tag{display:flex;align-items:center;gap:4px}\n.task-card-bottom .tag .icon{font-size:12px}\n\n/* \u2500\u2500\u2500 Task Detail Overlay \u2500\u2500\u2500 */\n.task-detail-overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:200;align-items:center;justify-content:center;padding:24px;backdrop-filter:blur(4px)}\n.task-detail-overlay.show{display:flex}\n.task-detail-panel{background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-xl);width:100%;max-width:780px;max-height:85vh;overflow-y:auto;box-shadow:var(--shadow-lg);padding:28px 32px}\n.task-detail-header{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;margin-bottom:16px}\n.task-detail-header h2{font-size:18px;font-weight:700;color:var(--text);line-height:1.4;flex:1}\n.task-detail-meta{display:flex;flex-wrap:wrap;gap:12px;margin-bottom:20px;font-size:12px;color:var(--text-sec)}\n.task-detail-meta .meta-item{display:flex;align-items:center;gap:5px;background:var(--bg-card);border:1px solid var(--border);border-radius:8px;padding:5px 12px}\n.task-detail-summary{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:20px;margin-bottom:20px;font-size:13px;line-height:1.7;color:var(--text);word-break:break-word}\n.task-detail-summary:empty::after{content:'Summary not yet generated (task still active)';color:var(--text-muted);font-style:italic}\n.task-detail-summary .summary-section-title{font-size:14px;font-weight:700;color:var(--text);margin:14px 0 6px 0;padding-bottom:4px;border-bottom:1px solid var(--border)}\n.task-detail-summary .summary-section-title:first-child{margin-top:0}\n.task-detail-summary ul{margin:4px 0 8px 0;padding-left:20px}\n.task-detail-summary li{margin:3px 0;color:var(--text-sec);line-height:1.6}\n.task-detail-chunks-title{font-size:12px;font-weight:700;color:var(--text-muted);text-transform:uppercase;letter-spacing:.06em;margin-bottom:12px}\n.task-detail-chunks{display:flex;flex-direction:column;gap:14px;padding:8px 0}\n.task-chunk-item{display:flex;flex-direction:column;max-width:82%;font-size:13px;line-height:1.6}\n.task-chunk-item.role-user{align-self:flex-end;align-items:flex-end}\n.task-chunk-item.role-assistant,.task-chunk-item.role-tool{align-self:flex-start;align-items:flex-start}\n.task-chunk-role{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;margin-bottom:3px;padding:0 4px}\n.task-chunk-role.user{color:var(--pri)}\n.task-chunk-role.assistant{color:var(--green)}\n.task-chunk-role.tool{color:var(--amber)}\n.task-chunk-bubble{padding:12px 16px;border-radius:16px;white-space:pre-wrap;word-break:break-word;max-height:200px;overflow:hidden;position:relative;transition:all .2s}\n.task-chunk-bubble.expanded{max-height:none}\n.role-user .task-chunk-bubble{background:var(--pri);color:#000;border-bottom-right-radius:4px}\n.role-assistant .task-chunk-bubble{background:var(--bg-card);border:1px solid var(--border);color:var(--text-sec);border-bottom-left-radius:4px}\n.role-tool .task-chunk-bubble{background:rgba(245,158,11,.08);border:1px solid rgba(245,158,11,.2);color:var(--text-sec);border-bottom-left-radius:4px;font-family:'SF Mono',Monaco,Consolas,monospace;font-size:12px}\n.task-chunk-bubble:hover{filter:brightness(1.05)}\n.task-chunk-time{font-size:10px;color:var(--text-muted);margin-top:3px;padding:0 4px}\n[data-theme=\"light\"] .role-user .task-chunk-bubble{background:var(--pri);color:#fff}\n[data-theme=\"light\"] .role-assistant .task-chunk-bubble{background:#f0f0f0;border:none;color:#333}\n[data-theme=\"light\"] .task-detail-panel{background:#fff}\n[data-theme=\"light\"] .task-card{background:#fff}\n[data-theme=\"light\"] .tasks-stat{background:#fff}\n\n/* \u2500\u2500\u2500 Analytics / \u7EDF\u8BA1 \u2500\u2500\u2500 */\n.nav-tabs{display:flex;align-items:center;gap:2px;background:rgba(255,255,255,.06);border-radius:10px;padding:3px}\n.nav-tabs .tab{padding:6px 20px;border-radius:8px;font-size:13px;font-weight:600;color:var(--text-sec);background:transparent;border:1px solid transparent;cursor:pointer;transition:all .2s;white-space:nowrap}\n.nav-tabs .tab:hover{color:var(--text)}\n.nav-tabs .tab.active{color:var(--text);background:rgba(255,255,255,.1);border-color:var(--border);box-shadow:0 1px 4px rgba(0,0,0,.15)}\n[data-theme=\"light\"] .nav-tabs{background:rgba(0,0,0,.05)}\n[data-theme=\"light\"] .nav-tabs .tab.active{background:#fff;border-color:rgba(0,0,0,.1);box-shadow:0 1px 3px rgba(0,0,0,.08);color:var(--text)}\n.analytics-view{display:none;flex:1;min-width:0;flex-direction:column;gap:20px}\n.analytics-view.show{display:flex}\n.feed-wrap{flex:1;min-width:0;display:flex;flex-direction:column}\n.feed-wrap.hide{display:none}\n.analytics-cards{display:grid;grid-template-columns:repeat(5,1fr);gap:14px}\n.analytics-card{background:linear-gradient(145deg,var(--bg-card) 0%,rgba(255,255,255,.02) 100%);border:1px solid var(--border);border-radius:var(--radius-lg);padding:20px 18px;position:relative;overflow:hidden;transition:all .25s}\n.analytics-card:hover{border-color:var(--border-glow);transform:translateY(-2px);box-shadow:0 8px 20px rgba(0,0,0,.15)}\n.analytics-card::before{content:'';position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,#3b82f6,#60a5fa);opacity:.85}\n.analytics-card.green::before{background:linear-gradient(90deg,var(--green),#34d399)}\n.analytics-card.amber::before{background:linear-gradient(90deg,var(--amber),#fbbf24)}\n.analytics-card.violet::before{background:linear-gradient(90deg,var(--violet),#a78bfa)}\n.analytics-card .ac-value{font-size:26px;font-weight:800;letter-spacing:-.03em;color:var(--text);line-height:1.1}\n.analytics-card .ac-label{font-size:11px;color:var(--text-muted);margin-top:5px;font-weight:500;text-transform:uppercase;letter-spacing:.04em}\n.analytics-section{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:22px 24px}\n.analytics-section h3{font-size:12px;font-weight:700;color:var(--text-muted);text-transform:uppercase;letter-spacing:.06em;margin-bottom:16px;display:flex;align-items:center;gap:8px}\n.analytics-section h3 .icon{font-size:14px;opacity:.7}\n.chart-bars{display:flex;align-items:flex-end;gap:4px;padding:8px 0;overflow-x:auto}\n.chart-bar-wrap{flex:1;min-width:18px;max-width:60px;display:flex;flex-direction:column;align-items:center;gap:4px;position:relative}\n.chart-bar-col{width:100%;height:160px;display:flex;flex-direction:column;justify-content:flex-end;align-items:stretch}\n.chart-bar-wrap:hover .chart-bar{filter:brightness(1.25)}\n.chart-bar-wrap:hover .chart-bar-label{color:var(--pri)}\n.chart-bar-wrap:hover .chart-tip{opacity:1;transform:translateX(-50%) translateY(0)}\n.chart-tip{position:absolute;top:-6px;left:50%;transform:translateX(-50%) translateY(4px);background:var(--bg);border:1px solid var(--border);color:var(--text);padding:2px 8px;border-radius:6px;font-size:10px;font-weight:700;white-space:nowrap;z-index:5;pointer-events:none;box-shadow:var(--shadow);opacity:0;transition:all .15s ease}\n.chart-bar{width:100%;border-radius:4px 4px 0 0;background:linear-gradient(180deg,#60a5fa,#3b82f6);transition:all .3s ease}\n.chart-bar.violet{background:linear-gradient(180deg,var(--violet),#7c3aed)}\n.chart-bar.green{background:linear-gradient(180deg,var(--green),#059669)}\n.chart-bar.zero{background:var(--border);opacity:.4;border-radius:2px}\n.chart-bar-label{font-size:9px;color:var(--text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%;text-align:center;transition:color .15s}\n.chart-legend{display:flex;gap:16px;margin-top:12px;flex-wrap:wrap;font-size:12px;color:var(--text-sec)}\n.chart-legend span{display:inline-flex;align-items:center;gap:6px}\n.chart-legend .dot{width:8px;height:8px;border-radius:50%}\n.chart-legend .dot.pri{background:var(--pri)}\n.chart-legend .dot.violet{background:var(--violet)}\n.chart-legend .dot.green{background:var(--green)}\n.breakdown-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:20px}\n.breakdown-item{display:flex;flex-direction:column;gap:6px;padding:12px 14px;background:rgba(0,0,0,.12);border-radius:10px;border:1px solid var(--border);transition:border-color .15s}\n.breakdown-item:hover{border-color:var(--border-glow)}\n.breakdown-item .bd-top{display:flex;align-items:center;justify-content:space-between}\n.breakdown-item .label{font-size:13px;color:var(--text-sec);font-weight:500;text-transform:capitalize}\n.breakdown-item .value{font-size:14px;font-weight:700;color:var(--text)}\n.breakdown-bar-wrap{height:4px;background:rgba(0,0,0,.15);border-radius:2px;overflow:hidden}\n.breakdown-bar{height:100%;border-radius:2px;background:linear-gradient(90deg,#3b82f6,#60a5fa);transition:width .5s ease}\n.metrics-toolbar{display:flex;align-items:center;gap:12px;margin-bottom:16px;flex-wrap:wrap}\n.metrics-toolbar .range-btn{padding:6px 14px;border-radius:8px;border:1px solid var(--border);background:var(--bg-card);color:var(--text-sec);font-size:12px;font-weight:600;cursor:pointer;transition:all .15s}\n.metrics-toolbar .range-btn:hover{border-color:var(--pri);color:var(--pri)}\n.metrics-toolbar .range-btn.active{background:rgba(255,255,255,.1);color:var(--text);border-color:var(--border)}\n\n.theme-toggle{position:relative;width:28px;height:28px;padding:0;display:flex;align-items:center;justify-content:center;font-size:14px;border:none;background:transparent}\n.theme-toggle .theme-icon-light{display:none}\n.theme-toggle .theme-icon-dark{display:inline}\n[data-theme=\"light\"] .theme-toggle .theme-icon-light{display:inline}\n[data-theme=\"light\"] .theme-toggle .theme-icon-dark{display:none}\n\n.auth-top-actions{position:absolute;top:16px;right:16px;z-index:10;display:flex;align-items:center;gap:2px;background:rgba(255,255,255,.18);backdrop-filter:blur(10px);border-radius:20px;padding:3px}\n.auth-theme-toggle{width:30px;height:30px;border:none;border-radius:50%;background:transparent;color:rgba(255,255,255,.7);cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:13px;transition:all .2s}\n.auth-theme-toggle:hover{background:rgba(255,255,255,.2);color:#fff}\n.auth-theme-toggle .theme-icon-light{display:none}\n.auth-theme-toggle .theme-icon-dark{display:inline}\n[data-theme=\"light\"] .auth-theme-toggle{color:rgba(0,0,0,.45)}\n[data-theme=\"light\"] .auth-theme-toggle:hover{background:rgba(0,0,0,.08);color:#0f172a}\n[data-theme=\"light\"] .auth-top-actions{background:rgba(0,0,0,.06)}\n[data-theme=\"light\"] .auth-theme-toggle .theme-icon-light{display:inline}\n[data-theme=\"light\"] .auth-theme-toggle .theme-icon-dark{display:none}\n\n@media(max-width:1100px){.analytics-cards{grid-template-columns:repeat(3,1fr)}}\n@media(max-width:900px){.main-content{flex-direction:column;padding:20px}.sidebar{width:100%}.sidebar .stats-grid{grid-template-columns:repeat(4,1fr)}.analytics-cards{grid-template-columns:repeat(2,1fr)}.topbar{padding:0 16px;gap:8px}.topbar .brand span{display:none}.topbar-center{justify-content:flex-start}}\n</style>\n</head>\n<body>\n\n<!-- \u2500\u2500\u2500 Auth: Setup Password \u2500\u2500\u2500 -->\n<div id=\"setupScreen\" class=\"auth-screen\" style=\"display:none\">\n <div class=\"auth-top-actions\">\n <button class=\"auth-theme-toggle\" onclick=\"toggleViewerTheme()\" title=\"Toggle light/dark\" aria-label=\"Toggle theme\"><span class=\"theme-icon-dark\">\uD83C\uDF19</span><span class=\"theme-icon-light\">\u2600</span></button>\n <button class=\"auth-theme-toggle\" onclick=\"toggleLang()\" aria-label=\"Switch language\"><span data-i18n=\"lang.switch\">EN</span></button>\n </div>\n <div class=\"auth-card\">\n <div class=\"logo\">\uD83E\uDD9E</div>\n <h1 data-i18n=\"title\">OpenClaw Memory</h1>\n <p style=\"font-size:12px;color:var(--text-sec);margin-bottom:6px\" data-i18n=\"subtitle\">Powered by MemOS</p>\n <p data-i18n=\"setup.desc\">Set a password to protect your memories</p>\n <input type=\"password\" id=\"setupPw\" data-i18n-ph=\"setup.pw\" placeholder=\"Enter a password (4+ characters)\" autofocus>\n <input type=\"password\" id=\"setupPw2\" data-i18n-ph=\"setup.pw2\" placeholder=\"Confirm password\">\n <button class=\"btn-auth\" onclick=\"doSetup()\" data-i18n=\"setup.btn\">Set Password & Enter</button>\n <div class=\"error-msg\" id=\"setupErr\"></div>\n </div>\n</div>\n\n<!-- \u2500\u2500\u2500 Auth: Login \u2500\u2500\u2500 -->\n<div id=\"loginScreen\" class=\"auth-screen\" style=\"display:none\">\n <div class=\"auth-top-actions\">\n <button class=\"auth-theme-toggle\" onclick=\"toggleViewerTheme()\" title=\"Toggle light/dark\" aria-label=\"Toggle theme\"><span class=\"theme-icon-dark\">\uD83C\uDF19</span><span class=\"theme-icon-light\">\u2600</span></button>\n <button class=\"auth-theme-toggle\" onclick=\"toggleLang()\" aria-label=\"Switch language\"><span data-i18n=\"lang.switch\">EN</span></button>\n </div>\n <div class=\"auth-card\">\n <div class=\"logo\">\uD83E\uDD9E</div>\n <h1 data-i18n=\"title\">OpenClaw Memory</h1>\n <p style=\"font-size:12px;color:var(--text-sec);margin-bottom:6px\" data-i18n=\"subtitle\">Powered by MemOS</p>\n <p data-i18n=\"login.desc\">Enter your password to access memories</p>\n <div id=\"loginForm\">\n <input type=\"password\" id=\"loginPw\" data-i18n-ph=\"login.pw\" placeholder=\"Password\" autofocus>\n <button class=\"btn-auth\" onclick=\"doLogin()\" data-i18n=\"login.btn\">Unlock</button>\n <div class=\"error-msg\" id=\"loginErr\"></div>\n <button class=\"btn-text\" style=\"margin-top:12px;font-size:13px;color:var(--text-sec)\" onclick=\"showResetForm()\" data-i18n=\"login.forgot\">Forgot password?</button>\n </div>\n <div id=\"resetForm\" style=\"display:none\">\n <div class=\"reset-guide\">\n <div class=\"reset-step\">\n <div class=\"step-num\">1</div>\n <div class=\"step-body\">\n <div class=\"step-title\" data-i18n=\"reset.step1.title\">Open Terminal</div>\n <div class=\"step-desc\" data-i18n=\"reset.step1.desc\">Run the following command to get your reset token (use the pattern below so you get the line that contains the token):</div>\n <div class=\"cmd-box\" onclick=\"copyCmd(this)\">\n <code>grep \"password reset token:\" /tmp/openclaw/openclaw-*.log ~/.openclaw/logs/gateway.log 2>/dev/null | tail -1</code>\n <span class=\"copy-hint\" data-i18n=\"copy.hint\">Click to copy</span>\n </div>\n </div>\n </div>\n <div class=\"reset-step\">\n <div class=\"step-num\">2</div>\n <div class=\"step-body\">\n <div class=\"step-title\" data-i18n=\"reset.step2.title\">Find the token</div>\n <div class=\"step-desc\" id=\"resetStep2Desc\">In the output, find <span style=\"font-family:monospace;font-size:12px;color:var(--pri)\">password reset token: <strong>a1b2c3d4e5f6...</strong></span> (plain line or inside JSON). Copy the 32-character hex string after the colon.</div>\n </div>\n </div>\n <div class=\"reset-step\">\n <div class=\"step-num\">3</div>\n <div class=\"step-body\">\n <div class=\"step-title\" data-i18n=\"reset.step3.title\">Paste & reset</div>\n <div class=\"step-desc\" data-i18n=\"reset.step3.desc\">Paste the token below and set your new password.</div>\n </div>\n </div>\n </div>\n <input type=\"text\" id=\"resetToken\" data-i18n-ph=\"reset.token\" placeholder=\"Paste reset token here\" style=\"margin-bottom:8px;font-family:monospace\">\n <input type=\"password\" id=\"resetNewPw\" data-i18n-ph=\"reset.newpw\" placeholder=\"New password (4+ characters)\">\n <input type=\"password\" id=\"resetNewPw2\" data-i18n-ph=\"reset.newpw2\" placeholder=\"Confirm new password\">\n <button class=\"btn-auth\" onclick=\"doReset()\" data-i18n=\"reset.btn\">Reset Password</button>\n <div class=\"error-msg\" id=\"resetErr\"></div>\n <button class=\"btn-text\" style=\"margin-top:12px;font-size:13px;color:var(--text-sec)\" onclick=\"showLoginForm()\" data-i18n=\"reset.back\">\u2190 Back to login</button>\n </div>\n </div>\n</div>\n\n<!-- \u2500\u2500\u2500 Main App \u2500\u2500\u2500 -->\n<div class=\"app\" id=\"app\">\n <div class=\"topbar\">\n <div class=\"brand\">\n <div class=\"icon\">\uD83E\uDD9E</div>\n <span data-i18n=\"title\">OpenClaw Memory</span>\n </div>\n <div class=\"topbar-center\">\n <nav class=\"nav-tabs\">\n <button class=\"tab active\" data-view=\"memories\" onclick=\"switchView('memories')\" data-i18n=\"tab.memories\">\uD83D\uDCDA Memories</button>\n <button class=\"tab\" data-view=\"tasks\" onclick=\"switchView('tasks')\" data-i18n=\"tab.tasks\">\uD83D\uDCCB Tasks</button>\n <button class=\"tab\" data-view=\"analytics\" onclick=\"switchView('analytics')\" data-i18n=\"tab.analytics\">\uD83D\uDCCA Analytics</button>\n </nav>\n </div>\n <div class=\"actions\">\n <button class=\"btn btn-icon\" onclick=\"toggleLang()\" aria-label=\"Switch language\" style=\"font-size:12px;font-weight:700;padding:4px 8px\"><span data-i18n=\"lang.switch\">EN</span></button>\n <button class=\"btn btn-icon theme-toggle\" onclick=\"toggleViewerTheme()\" title=\"Toggle light/dark\" aria-label=\"Toggle theme\"><span class=\"theme-icon-dark\">\uD83C\uDF19</span><span class=\"theme-icon-light\">\u2600</span></button>\n <button class=\"btn btn-ghost btn-sm\" onclick=\"loadAll()\" data-i18n=\"refresh\">\u21BB Refresh</button>\n <button class=\"btn btn-ghost btn-sm\" onclick=\"doLogout()\" data-i18n=\"logout\">Logout</button>\n </div>\n </div>\n\n <div class=\"main-content\">\n <div class=\"sidebar\" id=\"sidebar\">\n <div class=\"stats-grid\" id=\"statsGrid\">\n <div class=\"stat-card pri\"><div class=\"stat-value\" id=\"statTotal\">-</div><div class=\"stat-label\" data-i18n=\"stat.memories\">Memories</div></div>\n <div class=\"stat-card green\"><div class=\"stat-value\" id=\"statSessions\">-</div><div class=\"stat-label\" data-i18n=\"stat.sessions\">Sessions</div></div>\n <div class=\"stat-card amber\"><div class=\"stat-value\" id=\"statEmbeddings\">-</div><div class=\"stat-label\" data-i18n=\"stat.embeddings\">Embeddings</div></div>\n <div class=\"stat-card rose\"><div class=\"stat-value\" id=\"statTimeSpan\">-</div><div class=\"stat-label\" data-i18n=\"stat.days\">Days</div></div>\n </div>\n <div id=\"embeddingStatus\"></div>\n <div class=\"section-title\" data-i18n=\"sidebar.sessions\">Sessions</div>\n <div class=\"session-list\" id=\"sessionList\"></div>\n <button class=\"btn btn-sm btn-ghost\" style=\"width:100%;margin-top:20px;justify-content:center;color:var(--text-muted);font-size:11px\" onclick=\"clearAll()\" data-i18n=\"sidebar.clear\">\uD83D\uDDD1 Clear All Data</button>\n </div>\n\n <div class=\"feed-wrap\" id=\"feedWrap\">\n <div class=\"feed\">\n <div class=\"search-bar\">\n <span class=\"search-icon\">\uD83D\uDD0D</span>\n <input type=\"text\" id=\"searchInput\" data-i18n-ph=\"search.placeholder\" placeholder=\"Search memories (supports semantic search)...\" oninput=\"debounceSearch()\">\n </div>\n <div class=\"search-meta\" id=\"searchMeta\"></div>\n <div class=\"filter-bar\" id=\"filterBar\">\n <button class=\"filter-chip active\" data-role=\"\" onclick=\"setRoleFilter(this,'')\" data-i18n=\"filter.all\">All</button>\n <button class=\"filter-chip\" data-role=\"user\" onclick=\"setRoleFilter(this,'user')\">User</button>\n <button class=\"filter-chip\" data-role=\"assistant\" onclick=\"setRoleFilter(this,'assistant')\">Assistant</button>\n <button class=\"filter-chip\" data-role=\"system\" onclick=\"setRoleFilter(this,'system')\">System</button>\n <span class=\"filter-sep\"></span>\n <select id=\"filterKind\" class=\"filter-select\" onchange=\"applyFilters()\">\n <option value=\"\" data-i18n=\"filter.allkinds\">All kinds</option>\n <option value=\"paragraph\" data-i18n=\"filter.paragraph\">Paragraph</option>\n <option value=\"code_block\" data-i18n=\"filter.code\">Code</option>\n <option value=\"dialog\" data-i18n=\"filter.dialog\">Dialog</option>\n <option value=\"list\" data-i18n=\"filter.list\">List</option>\n <option value=\"error_stack\" data-i18n=\"filter.error\">Error</option>\n <option value=\"command\" data-i18n=\"filter.command\">Command</option>\n </select>\n <select id=\"filterSort\" class=\"filter-select\" onchange=\"applyFilters()\">\n <option value=\"newest\" data-i18n=\"filter.newest\">Newest first</option>\n <option value=\"oldest\" data-i18n=\"filter.oldest\">Oldest first</option>\n </select>\n </div>\n <div class=\"date-filter\">\n <label data-i18n=\"filter.from\">From</label><input type=\"datetime-local\" id=\"dateFrom\" step=\"1\" onchange=\"applyFilters()\">\n <label data-i18n=\"filter.to\">To</label><input type=\"datetime-local\" id=\"dateTo\" step=\"1\" onchange=\"applyFilters()\">\n <button class=\"btn btn-sm btn-text\" onclick=\"clearDateFilter()\" data-i18n=\"filter.clear\">Clear</button>\n </div>\n <div class=\"memory-list\" id=\"memoryList\"><div class=\"spinner\"></div></div>\n <div class=\"pagination\" id=\"pagination\"></div>\n </div>\n </div>\n <div class=\"tasks-view\" id=\"tasksView\">\n <div class=\"tasks-header\">\n <div class=\"tasks-stats\">\n <div class=\"tasks-stat\"><span class=\"tasks-stat-value\" id=\"tasksTotalCount\">-</span><span class=\"tasks-stat-label\" data-i18n=\"tasks.total\">Total Tasks</span></div>\n <div class=\"tasks-stat\"><span class=\"tasks-stat-value\" id=\"tasksActiveCount\">-</span><span class=\"tasks-stat-label\" data-i18n=\"tasks.active\">Active</span></div>\n <div class=\"tasks-stat\"><span class=\"tasks-stat-value\" id=\"tasksCompletedCount\">-</span><span class=\"tasks-stat-label\" data-i18n=\"tasks.completed\">Completed</span></div>\n <div class=\"tasks-stat\"><span class=\"tasks-stat-value\" id=\"tasksSkippedCount\">-</span><span class=\"tasks-stat-label\" data-i18n=\"tasks.status.skipped\">Skipped</span></div>\n </div>\n <div class=\"tasks-filters\">\n <button class=\"filter-chip active\" data-task-status=\"\" onclick=\"setTaskStatusFilter(this,'')\" data-i18n=\"filter.all\">All</button>\n <button class=\"filter-chip\" data-task-status=\"active\" onclick=\"setTaskStatusFilter(this,'active')\" data-i18n=\"tasks.status.active\">Active</button>\n <button class=\"filter-chip\" data-task-status=\"completed\" onclick=\"setTaskStatusFilter(this,'completed')\" data-i18n=\"tasks.status.completed\">Completed</button>\n <button class=\"filter-chip\" data-task-status=\"skipped\" onclick=\"setTaskStatusFilter(this,'skipped')\" data-i18n=\"tasks.status.skipped\">Skipped</button>\n <button class=\"btn btn-sm btn-ghost\" onclick=\"loadTasks()\" style=\"margin-left:auto\" data-i18n=\"refresh\">\u21BB Refresh</button>\n </div>\n </div>\n <div class=\"tasks-list\" id=\"tasksList\"><div class=\"spinner\"></div></div>\n <div class=\"pagination\" id=\"tasksPagination\"></div>\n <div class=\"task-detail-overlay\" id=\"taskDetailOverlay\" onclick=\"closeTaskDetail(event)\">\n <div class=\"task-detail-panel\" onclick=\"event.stopPropagation()\">\n <div class=\"task-detail-header\">\n <h2 id=\"taskDetailTitle\"></h2>\n <button class=\"btn btn-icon\" onclick=\"closeTaskDetail()\" title=\"Close\">\u2715</button>\n </div>\n <div class=\"task-detail-meta\" id=\"taskDetailMeta\"></div>\n <div class=\"task-detail-summary\" id=\"taskDetailSummary\"></div>\n <div class=\"task-detail-chunks-title\" data-i18n=\"tasks.chunks\">Related Memories</div>\n <div class=\"task-detail-chunks\" id=\"taskDetailChunks\"></div>\n </div>\n </div>\n </div>\n <div class=\"analytics-view\" id=\"analyticsView\">\n <div class=\"metrics-toolbar\">\n <span style=\"font-size:12px;color:var(--text-sec);font-weight:600\" data-i18n=\"range\">Range</span>\n <button class=\"range-btn\" data-days=\"7\" onclick=\"setMetricsDays(7)\">7 <span data-i18n=\"range.days\">days</span></button>\n <button class=\"range-btn active\" data-days=\"30\" onclick=\"setMetricsDays(30)\">30 <span data-i18n=\"range.days\">days</span></button>\n <button class=\"range-btn\" data-days=\"90\" onclick=\"setMetricsDays(90)\">90 <span data-i18n=\"range.days\">days</span></button>\n <button class=\"btn btn-sm\" onclick=\"loadMetrics()\" style=\"margin-left:auto\" data-i18n=\"refresh\">\u21BB Refresh</button>\n </div>\n <div class=\"analytics-cards\" id=\"analyticsCards\">\n <div class=\"analytics-card\"><div class=\"ac-value\" id=\"mTotal\">-</div><div class=\"ac-label\" data-i18n=\"analytics.total\">Total Memories</div></div>\n <div class=\"analytics-card green\"><div class=\"ac-value\" id=\"mTodayWrites\">-</div><div class=\"ac-label\" data-i18n=\"analytics.writes\">Writes Today</div></div>\n <div class=\"analytics-card violet\"><div class=\"ac-value\" id=\"mTodayCalls\">-</div><div class=\"ac-label\" data-i18n=\"analytics.calls\">Viewer Calls Today</div></div>\n <div class=\"analytics-card\"><div class=\"ac-value\" id=\"mSessions\">-</div><div class=\"ac-label\" data-i18n=\"analytics.sessions\">Sessions</div></div>\n <div class=\"analytics-card amber\"><div class=\"ac-value\" id=\"mEmbeddings\">-</div><div class=\"ac-label\" data-i18n=\"analytics.embeddings\">Embeddings</div></div>\n </div>\n <div class=\"analytics-section\">\n <h3><span class=\"icon\">\uD83D\uDCCA</span> <span data-i18n=\"chart.writes\">Memory Writes per Day</span></h3>\n <div class=\"chart-bars\" id=\"chartWrites\"></div>\n </div>\n <div class=\"analytics-section\">\n <h3><span class=\"icon\">\uD83D\uDD0D</span> <span data-i18n=\"chart.calls\">Viewer API Calls per Day (List / Search)</span></h3>\n <div class=\"chart-bars\" id=\"chartCalls\"></div>\n <div class=\"chart-legend\"><span><span class=\"dot pri\"></span> <span data-i18n=\"chart.list\">List</span></span><span><span class=\"dot violet\"></span> <span data-i18n=\"chart.search\">Search</span></span></div>\n </div>\n <div class=\"breakdown-grid\" style=\"display:grid;grid-template-columns:1fr 1fr;gap:24px\">\n <div class=\"analytics-section\">\n <h3><span class=\"icon\">\uD83D\uDC64</span> <span data-i18n=\"breakdown.role\">By Role</span></h3>\n <div id=\"breakdownRole\"></div>\n </div>\n <div class=\"analytics-section\">\n <h3><span class=\"icon\">\uD83D\uDCDD</span> <span data-i18n=\"breakdown.kind\">By Kind</span></h3>\n <div id=\"breakdownKind\"></div>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n<!-- \u2500\u2500\u2500 Memory Modal \u2500\u2500\u2500 -->\n<div class=\"modal-overlay\" id=\"modalOverlay\">\n <div class=\"modal\">\n <h2 id=\"modalTitle\" data-i18n=\"modal.new\">New Memory</h2>\n <div class=\"form-group\"><label data-i18n=\"modal.role\">Role</label><select id=\"mRole\"><option value=\"user\">User</option><option value=\"assistant\">Assistant</option><option value=\"system\">System</option></select></div>\n <div class=\"form-group\"><label data-i18n=\"modal.content\">Content</label><textarea id=\"mContent\" rows=\"4\" data-i18n-ph=\"modal.content.ph\" placeholder=\"Memory content...\"></textarea></div>\n <div class=\"form-group\"><label data-i18n=\"modal.summary\">Summary</label><input type=\"text\" id=\"mSummary\" data-i18n-ph=\"modal.summary.ph\" placeholder=\"Brief summary (optional)\"></div>\n <div class=\"form-group\"><label data-i18n=\"modal.kind\">Kind</label><select id=\"mKind\"><option value=\"paragraph\" data-i18n=\"filter.paragraph\">Paragraph</option><option value=\"code\" data-i18n=\"filter.code\">Code</option><option value=\"dialog\" data-i18n=\"filter.dialog\">Dialog</option></select></div>\n <div class=\"modal-actions\">\n <button class=\"btn btn-ghost\" onclick=\"closeModal()\" data-i18n=\"modal.cancel\">Cancel</button>\n <button class=\"btn btn-primary\" id=\"modalSubmit\" onclick=\"submitModal()\" data-i18n=\"modal.create\">Create</button>\n </div>\n </div>\n</div>\n\n<!-- \u2500\u2500\u2500 Toast \u2500\u2500\u2500 -->\n<div class=\"toast-container\" id=\"toasts\"></div>\n\n<script>\nlet activeSession=null,activeRole='',editingId=null,searchTimer=null,memoryCache={},currentPage=1,totalPages=1,totalCount=0,PAGE_SIZE=30,metricsDays=30;\n\n/* \u2500\u2500\u2500 i18n \u2500\u2500\u2500 */\nconst I18N={\n en:{\n 'title':'OpenClaw Memory',\n 'subtitle':'Powered by MemOS',\n 'setup.desc':'Set a password to protect your memories',\n 'setup.pw':'Enter a password (4+ characters)',\n 'setup.pw2':'Confirm password',\n 'setup.btn':'Set Password & Enter',\n 'setup.err.short':'Password must be at least 4 characters',\n 'setup.err.mismatch':'Passwords do not match',\n 'setup.err.fail':'Setup failed',\n 'login.desc':'Enter your password to access memories',\n 'login.pw':'Password',\n 'login.btn':'Unlock',\n 'login.err':'Incorrect password',\n 'login.forgot':'Forgot password?',\n 'reset.step1.title':'Open Terminal',\n 'reset.step1.desc':'Run the following command to get your reset token (use the pattern below so you get the line that contains the token):',\n 'reset.step2.title':'Find the token',\n 'reset.step2.desc.pre':'In the output, find ',\n 'reset.step2.desc.post':' (plain line or inside JSON). Copy the 32-character hex string after the colon.',\n 'reset.step3.title':'Paste & reset',\n 'reset.step3.desc':'Paste the token below and set your new password.',\n 'reset.token':'Paste reset token here',\n 'reset.newpw':'New password (4+ characters)',\n 'reset.newpw2':'Confirm new password',\n 'reset.btn':'Reset Password',\n 'reset.err.token':'Please enter the reset token',\n 'reset.err.short':'Password must be at least 4 characters',\n 'reset.err.mismatch':'Passwords do not match',\n 'reset.err.fail':'Reset failed',\n 'reset.back':'\\u2190 Back to login',\n 'copy.hint':'Click to copy',\n 'copy.done':'Copied!',\n 'tab.memories':'\\u{1F4DA} Memories',\n 'tab.tasks':'\\u{1F4CB} Tasks',\n 'tab.analytics':'\\u{1F4CA} Analytics',\n 'tasks.total':'Total Tasks',\n 'tasks.active':'Active',\n 'tasks.completed':'Completed',\n 'tasks.status.active':'Active',\n 'tasks.status.completed':'Completed',\n 'tasks.status.skipped':'Skipped',\n 'tasks.empty':'No tasks yet. Tasks are automatically created as you converse.',\n 'tasks.loading':'Loading...',\n 'tasks.untitled':'Untitled Task',\n 'tasks.chunks':'Related Memories',\n 'tasks.nochunks':'No memories in this task yet.',\n 'tasks.skipped.default':'This conversation was too brief to generate a summary. It will not appear in search results.',\n 'refresh':'\\u21BB Refresh',\n 'logout':'Logout',\n 'stat.memories':'Memories',\n 'stat.sessions':'Sessions',\n 'stat.embeddings':'Embeddings',\n 'stat.days':'Days',\n 'sidebar.sessions':'Sessions',\n 'sidebar.allsessions':'All Sessions',\n 'sidebar.clear':'\\u{1F5D1} Clear All Data',\n 'search.placeholder':'Search memories (supports semantic search)...',\n 'search.meta.total':' memories total',\n 'search.meta.semantic':' semantic',\n 'search.meta.text':' text',\n 'search.meta.results':' results',\n 'filter.all':'All',\n 'filter.allkinds':'All kinds',\n 'filter.paragraph':'Paragraph',\n 'filter.code':'Code',\n 'filter.dialog':'Dialog',\n 'filter.list':'List',\n 'filter.error':'Error',\n 'filter.command':'Command',\n 'filter.newest':'Newest first',\n 'filter.oldest':'Oldest first',\n 'filter.from':'From',\n 'filter.to':'To',\n 'filter.clear':'Clear',\n 'empty.text':'No memories found',\n 'card.expand':'Expand',\n 'card.edit':'Edit',\n 'card.delete':'Delete',\n 'pagination.total':' total',\n 'range':'Range',\n 'range.days':'days',\n 'analytics.total':'Total Memories',\n 'analytics.writes':'Writes Today',\n 'analytics.calls':'Viewer Calls Today',\n 'analytics.sessions':'Sessions',\n 'analytics.embeddings':'Embeddings',\n 'chart.writes':'Memory Writes per Day',\n 'chart.calls':'Viewer API Calls per Day (List / Search)',\n 'chart.nodata':'No data in this range',\n 'chart.nocalls':'No viewer calls in this range',\n 'chart.list':'List',\n 'chart.search':'Search',\n 'breakdown.role':'By Role',\n 'breakdown.kind':'By Kind',\n 'modal.new':'New Memory',\n 'modal.edit':'Edit Memory',\n 'modal.role':'Role',\n 'modal.content':'Content',\n 'modal.content.ph':'Memory content...',\n 'modal.summary':'Summary',\n 'modal.summary.ph':'Brief summary (optional)',\n 'modal.kind':'Kind',\n 'modal.cancel':'Cancel',\n 'modal.create':'Create',\n 'modal.save':'Save',\n 'modal.err.empty':'Please enter content',\n 'toast.created':'Memory created',\n 'toast.updated':'Memory updated',\n 'toast.deleted':'Memory deleted',\n 'toast.opfail':'Operation failed',\n 'toast.delfail':'Delete failed',\n 'toast.cleared':'All memories cleared',\n 'toast.clearfail':'Clear failed',\n 'toast.notfound':'Memory not found in cache',\n 'confirm.delete':'Delete this memory?',\n 'confirm.clearall':'Delete ALL memories? This cannot be undone.',\n 'confirm.clearall2':'Are you absolutely sure?',\n 'embed.on':'Embedding: ',\n 'embed.off':'No embedding model',\n 'lang.switch':'\u4E2D'\n },\n zh:{\n 'title':'OpenClaw \u8BB0\u5FC6',\n 'subtitle':'\u7531 MemOS \u9A71\u52A8',\n 'setup.desc':'\u8BBE\u7F6E\u5BC6\u7801\u4EE5\u4FDD\u62A4\u4F60\u7684\u8BB0\u5FC6\u6570\u636E',\n 'setup.pw':'\u8F93\u5165\u5BC6\u7801\uFF08\u81F3\u5C114\u4F4D\uFF09',\n 'setup.pw2':'\u786E\u8BA4\u5BC6\u7801',\n 'setup.btn':'\u8BBE\u7F6E\u5BC6\u7801\u5E76\u8FDB\u5165',\n 'setup.err.short':'\u5BC6\u7801\u81F3\u5C11\u9700\u89814\u4E2A\u5B57\u7B26',\n 'setup.err.mismatch':'\u4E24\u6B21\u5BC6\u7801\u4E0D\u4E00\u81F4',\n 'setup.err.fail':'\u8BBE\u7F6E\u5931\u8D25',\n 'login.desc':'\u8F93\u5165\u5BC6\u7801\u4EE5\u8BBF\u95EE\u8BB0\u5FC6',\n 'login.pw':'\u5BC6\u7801',\n 'login.btn':'\u89E3\u9501',\n 'login.err':'\u5BC6\u7801\u9519\u8BEF',\n 'login.forgot':'\u5FD8\u8BB0\u5BC6\u7801\uFF1F',\n 'reset.step1.title':'\u6253\u5F00\u7EC8\u7AEF',\n 'reset.step1.desc':'\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u83B7\u53D6\u91CD\u7F6E\u4EE4\u724C\uFF1A',\n 'reset.step2.title':'\u627E\u5230\u4EE4\u724C',\n 'reset.step2.desc.pre':'\u5728\u8F93\u51FA\u4E2D\u627E\u5230 ',\n 'reset.step2.desc.post':'\uFF08\u7EAF\u6587\u672C\u884C\u6216 JSON \u5185\uFF09\u3002\u590D\u5236\u5192\u53F7\u540E\u768432\u4F4D\u5341\u516D\u8FDB\u5236\u5B57\u7B26\u4E32\u3002',\n 'reset.step3.title':'\u7C98\u8D34\u5E76\u91CD\u7F6E',\n 'reset.step3.desc':'\u5C06\u4EE4\u724C\u7C98\u8D34\u5230\u4E0B\u65B9\u5E76\u8BBE\u7F6E\u65B0\u5BC6\u7801\u3002',\n 'reset.token':'\u5728\u6B64\u7C98\u8D34\u91CD\u7F6E\u4EE4\u724C',\n 'reset.newpw':'\u65B0\u5BC6\u7801\uFF08\u81F3\u5C114\u4F4D\uFF09',\n 'reset.newpw2':'\u786E\u8BA4\u65B0\u5BC6\u7801',\n 'reset.btn':'\u91CD\u7F6E\u5BC6\u7801',\n 'reset.err.token':'\u8BF7\u8F93\u5165\u91CD\u7F6E\u4EE4\u724C',\n 'reset.err.short':'\u5BC6\u7801\u81F3\u5C11\u9700\u89814\u4E2A\u5B57\u7B26',\n 'reset.err.mismatch':'\u4E24\u6B21\u5BC6\u7801\u4E0D\u4E00\u81F4',\n 'reset.err.fail':'\u91CD\u7F6E\u5931\u8D25',\n 'reset.back':'\\u2190 \u8FD4\u56DE\u767B\u5F55',\n 'copy.hint':'\u70B9\u51FB\u590D\u5236',\n 'copy.done':'\u5DF2\u590D\u5236\uFF01',\n 'tab.memories':'\\u{1F4DA} \u8BB0\u5FC6',\n 'tab.tasks':'\\u{1F4CB} \u4EFB\u52A1',\n 'tab.analytics':'\\u{1F4CA} \u5206\u6790',\n 'tasks.total':'\u4EFB\u52A1\u603B\u6570',\n 'tasks.active':'\u8FDB\u884C\u4E2D',\n 'tasks.completed':'\u5DF2\u5B8C\u6210',\n 'tasks.status.active':'\u8FDB\u884C\u4E2D',\n 'tasks.status.completed':'\u5DF2\u5B8C\u6210',\n 'tasks.status.skipped':'\u5DF2\u8DF3\u8FC7',\n 'tasks.empty':'\u6682\u65E0\u4EFB\u52A1\u3002\u4EFB\u52A1\u4F1A\u968F\u7740\u5BF9\u8BDD\u81EA\u52A8\u521B\u5EFA\u3002',\n 'tasks.loading':'\u52A0\u8F7D\u4E2D...',\n 'tasks.untitled':'\u672A\u547D\u540D\u4EFB\u52A1',\n 'tasks.chunks':'\u5173\u8054\u8BB0\u5FC6',\n 'tasks.nochunks':'\u6B64\u4EFB\u52A1\u6682\u65E0\u5173\u8054\u8BB0\u5FC6\u3002',\n 'tasks.skipped.default':'\u5BF9\u8BDD\u5185\u5BB9\u8FC7\u5C11\uFF0C\u672A\u751F\u6210\u6458\u8981\u3002\u8BE5\u4EFB\u52A1\u4E0D\u4F1A\u51FA\u73B0\u5728\u68C0\u7D22\u7ED3\u679C\u4E2D\u3002',\n 'refresh':'\\u21BB \u5237\u65B0',\n 'logout':'\u9000\u51FA',\n 'stat.memories':'\u8BB0\u5FC6',\n 'stat.sessions':'\u4F1A\u8BDD',\n 'stat.embeddings':'\u5D4C\u5165',\n 'stat.days':'\u5929\u6570',\n 'sidebar.sessions':'\u4F1A\u8BDD\u5217\u8868',\n 'sidebar.allsessions':'\u5168\u90E8\u4F1A\u8BDD',\n 'sidebar.clear':'\\u{1F5D1} \u6E05\u9664\u6240\u6709\u6570\u636E',\n 'search.placeholder':'\u641C\u7D22\u8BB0\u5FC6\uFF08\u652F\u6301\u8BED\u4E49\u641C\u7D22\uFF09...',\n 'search.meta.total':' \u6761\u8BB0\u5FC6',\n 'search.meta.semantic':' \u8BED\u4E49',\n 'search.meta.text':' \u6587\u672C',\n 'search.meta.results':' \u6761\u7ED3\u679C',\n 'filter.all':'\u5168\u90E8',\n 'filter.allkinds':'\u6240\u6709\u7C7B\u578B',\n 'filter.paragraph':'\u6BB5\u843D',\n 'filter.code':'\u4EE3\u7801',\n 'filter.dialog':'\u5BF9\u8BDD',\n 'filter.list':'\u5217\u8868',\n 'filter.error':'\u9519\u8BEF',\n 'filter.command':'\u547D\u4EE4',\n 'filter.newest':'\u6700\u65B0\u4F18\u5148',\n 'filter.oldest':'\u6700\u65E9\u4F18\u5148',\n 'filter.from':'\u8D77\u59CB',\n 'filter.to':'\u622A\u6B62',\n 'filter.clear':'\u6E05\u9664',\n 'empty.text':'\u6682\u65E0\u8BB0\u5FC6',\n 'card.expand':'\u5C55\u5F00',\n 'card.edit':'\u7F16\u8F91',\n 'card.delete':'\u5220\u9664',\n 'pagination.total':' \u6761',\n 'range':'\u8303\u56F4',\n 'range.days':'\u5929',\n 'analytics.total':'\u603B\u8BB0\u5FC6\u6570',\n 'analytics.writes':'\u4ECA\u65E5\u5199\u5165',\n 'analytics.calls':'\u4ECA\u65E5\u67E5\u770B\u5668\u8C03\u7528',\n 'analytics.sessions':'\u4F1A\u8BDD\u6570',\n 'analytics.embeddings':'\u5D4C\u5165\u6570',\n 'chart.writes':'\u6BCF\u65E5\u8BB0\u5FC6\u5199\u5165',\n 'chart.calls':'\u6BCF\u65E5\u67E5\u770B\u5668 API \u8C03\u7528\uFF08\u5217\u8868 / \u641C\u7D22\uFF09',\n 'chart.nodata':'\u6B64\u8303\u56F4\u5185\u6682\u65E0\u6570\u636E',\n 'chart.nocalls':'\u6B64\u8303\u56F4\u5185\u6682\u65E0\u67E5\u770B\u5668\u8C03\u7528',\n 'chart.list':'\u5217\u8868',\n 'chart.search':'\u641C\u7D22',\n 'breakdown.role':'\u6309\u89D2\u8272',\n 'breakdown.kind':'\u6309\u7C7B\u578B',\n 'modal.new':'\u65B0\u5EFA\u8BB0\u5FC6',\n 'modal.edit':'\u7F16\u8F91\u8BB0\u5FC6',\n 'modal.role':'\u89D2\u8272',\n 'modal.content':'\u5185\u5BB9',\n 'modal.content.ph':'\u8BB0\u5FC6\u5185\u5BB9...',\n 'modal.summary':'\u6458\u8981',\n 'modal.summary.ph':'\u7B80\u8981\u6458\u8981\uFF08\u53EF\u9009\uFF09',\n 'modal.kind':'\u7C7B\u578B',\n 'modal.cancel':'\u53D6\u6D88',\n 'modal.create':'\u521B\u5EFA',\n 'modal.save':'\u4FDD\u5B58',\n 'modal.err.empty':'\u8BF7\u8F93\u5165\u5185\u5BB9',\n 'toast.created':'\u8BB0\u5FC6\u5DF2\u521B\u5EFA',\n 'toast.updated':'\u8BB0\u5FC6\u5DF2\u66F4\u65B0',\n 'toast.deleted':'\u8BB0\u5FC6\u5DF2\u5220\u9664',\n 'toast.opfail':'\u64CD\u4F5C\u5931\u8D25',\n 'toast.delfail':'\u5220\u9664\u5931\u8D25',\n 'toast.cleared':'\u6240\u6709\u8BB0\u5FC6\u5DF2\u6E05\u9664',\n 'toast.clearfail':'\u6E05\u9664\u5931\u8D25',\n 'toast.notfound':'\u7F13\u5B58\u4E2D\u672A\u627E\u5230\u6B64\u8BB0\u5FC6',\n 'confirm.delete':'\u786E\u5B9A\u8981\u5220\u9664\u8FD9\u6761\u8BB0\u5FC6\u5417\uFF1F',\n 'confirm.clearall':'\u786E\u5B9A\u8981\u5220\u9664\u6240\u6709\u8BB0\u5FC6\uFF1F\u6B64\u64CD\u4F5C\u4E0D\u53EF\u64A4\u9500\u3002',\n 'confirm.clearall2':'\u4F60\u771F\u7684\u786E\u5B9A\u5417\uFF1F',\n 'embed.on':'\u5D4C\u5165\u6A21\u578B\uFF1A',\n 'embed.off':'\u65E0\u5D4C\u5165\u6A21\u578B',\n 'lang.switch':'EN'\n }\n};\nconst LANG_KEY='memos-viewer-lang';\nlet curLang=localStorage.getItem(LANG_KEY)||(navigator.language.startsWith('zh')?'zh':'en');\nfunction t(key){return (I18N[curLang]||I18N.en)[key]||key;}\nfunction setLang(lang){curLang=lang;localStorage.setItem(LANG_KEY,lang);applyI18n();}\nfunction toggleLang(){setLang(curLang==='zh'?'en':'zh');}\n\nfunction applyI18n(){\n document.querySelectorAll('[data-i18n]').forEach(el=>{\n const key=el.getAttribute('data-i18n');\n if(key) el.textContent=t(key);\n });\n document.querySelectorAll('[data-i18n-ph]').forEach(el=>{\n const key=el.getAttribute('data-i18n-ph');\n if(key) el.placeholder=t(key);\n });\n const step2=document.getElementById('resetStep2Desc');\n if(step2) step2.innerHTML=t('reset.step2.desc.pre')+'<span style=\"font-family:monospace;font-size:12px;color:var(--pri)\">password reset token: <strong>a1b2c3d4e5f6...</strong></span>'+t('reset.step2.desc.post');\n document.title=t('title')+' - MemOS';\n if(typeof loadStats==='function' && document.getElementById('app').style.display==='flex'){loadStats();}\n if(document.querySelector('.analytics-view.show') && typeof loadMetrics==='function'){loadMetrics();}\n}\n\n/* \u2500\u2500\u2500 Auth flow \u2500\u2500\u2500 */\nasync function checkAuth(){\n const r=await fetch('/api/auth/status');\n const d=await r.json();\n if(d.needsSetup){\n document.getElementById('setupScreen').style.display='flex';\n document.getElementById('setupPw').addEventListener('keydown',e=>{if(e.key==='Enter')document.getElementById('setupPw2').focus()});\n document.getElementById('setupPw2').addEventListener('keydown',e=>{if(e.key==='Enter')doSetup()});\n } else if(!d.loggedIn){\n document.getElementById('loginScreen').style.display='flex';\n document.getElementById('loginPw').addEventListener('keydown',e=>{if(e.key==='Enter')doLogin()});\n } else {\n enterApp();\n }\n}\n\nasync function doSetup(){\n const pw=document.getElementById('setupPw').value;\n const pw2=document.getElementById('setupPw2').value;\n const err=document.getElementById('setupErr');\n if(pw.length<4){err.textContent=t('setup.err.short');return}\n if(pw!==pw2){err.textContent=t('setup.err.mismatch');return}\n const r=await fetch('/api/auth/setup',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({password:pw})});\n const d=await r.json();\n if(d.ok){document.getElementById('setupScreen').style.display='none';enterApp();}\n else{err.textContent=d.error||t('setup.err.fail')}\n}\n\nasync function doLogin(){\n const pw=document.getElementById('loginPw').value;\n const err=document.getElementById('loginErr');\n const r=await fetch('/api/auth/login',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({password:pw})});\n const d=await r.json();\n if(d.ok){document.getElementById('loginScreen').style.display='none';enterApp();}\n else{err.textContent=t('login.err');document.getElementById('loginPw').value='';document.getElementById('loginPw').focus();}\n}\n\nasync function doLogout(){\n await fetch('/api/auth/logout',{method:'POST'});\n location.reload();\n}\n\nfunction showResetForm(){\n document.getElementById('loginForm').style.display='none';\n document.getElementById('resetForm').style.display='block';\n document.getElementById('resetToken').focus();\n}\n\nfunction showLoginForm(){\n document.getElementById('resetForm').style.display='none';\n document.getElementById('loginForm').style.display='block';\n document.getElementById('loginPw').focus();\n}\n\nfunction copyCmd(el){\n const code=el.querySelector('code').textContent;\n navigator.clipboard.writeText(code).then(()=>{\n el.classList.add('copied');\n el.querySelector('.copy-hint').textContent=t('copy.done');\n setTimeout(()=>{el.classList.remove('copied');el.querySelector('.copy-hint').textContent=t('copy.hint')},2000);\n });\n}\n\nasync function doReset(){\n const token=document.getElementById('resetToken').value.trim();\n const pw=document.getElementById('resetNewPw').value;\n const pw2=document.getElementById('resetNewPw2').value;\n const err=document.getElementById('resetErr');\n if(!token){err.textContent=t('reset.err.token');return}\n if(pw.length<4){err.textContent=t('reset.err.short');return}\n if(pw!==pw2){err.textContent=t('reset.err.mismatch');return}\n const r=await fetch('/api/auth/reset',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({token,newPassword:pw})});\n const d=await r.json();\n if(d.ok){document.getElementById('loginScreen').style.display='none';enterApp();}\n else{err.textContent=d.error||t('reset.err.fail')}\n}\n\nfunction enterApp(){\n document.getElementById('app').style.display='flex';\n loadAll();\n}\n\nfunction switchView(view){\n document.querySelectorAll('.nav-tabs .tab').forEach(t=>t.classList.toggle('active',t.dataset.view===view));\n const feedWrap=document.getElementById('feedWrap');\n const analyticsView=document.getElementById('analyticsView');\n const tasksView=document.getElementById('tasksView');\n feedWrap.classList.add('hide');\n analyticsView.classList.remove('show');\n tasksView.classList.remove('show');\n if(view==='analytics'){\n analyticsView.classList.add('show');\n loadMetrics();\n } else if(view==='tasks'){\n tasksView.classList.add('show');\n loadTasks();\n } else {\n feedWrap.classList.remove('hide');\n }\n}\n\nfunction setMetricsDays(d){\n metricsDays=d;\n document.querySelectorAll('.metrics-toolbar .range-btn').forEach(btn=>btn.classList.toggle('active',Number(btn.dataset.days)===d));\n loadMetrics();\n}\n\nasync function loadMetrics(){\n const r=await fetch('/api/metrics?days='+metricsDays);\n const d=await r.json();\n document.getElementById('mTotal').textContent=formatNum(d.totals.memories);\n document.getElementById('mTodayWrites').textContent=formatNum(d.totals.todayWrites);\n document.getElementById('mTodayCalls').textContent=formatNum(d.totals.todayViewerCalls);\n document.getElementById('mSessions').textContent=formatNum(d.totals.sessions);\n document.getElementById('mEmbeddings').textContent=formatNum(d.totals.embeddings);\n renderChartWrites(d.writesPerDay);\n renderChartCalls(d.viewerCallsPerDay);\n renderBreakdown(d.roleBreakdown,'breakdownRole');\n renderBreakdown(d.kindBreakdown,'breakdownKind');\n}\n\nfunction formatNum(n){return n>=1e6?(n/1e6).toFixed(1)+'M':n>=1e3?(n/1e3).toFixed(1)+'k':String(n);}\n\n/* \u2500\u2500\u2500 Tasks View Logic \u2500\u2500\u2500 */\nlet tasksStatusFilter='';\nlet tasksPage=0;\nconst TASKS_PER_PAGE=20;\n\nfunction setTaskStatusFilter(btn,status){\n document.querySelectorAll('.tasks-filters .filter-chip').forEach(c=>c.classList.remove('active'));\n btn.classList.add('active');\n tasksStatusFilter=status;\n tasksPage=0;\n loadTasks();\n}\n\nasync function loadTasks(){\n const list=document.getElementById('tasksList');\n list.innerHTML='<div class=\"spinner\"></div>';\n try{\n const params=new URLSearchParams({limit:String(TASKS_PER_PAGE),offset:String(tasksPage*TASKS_PER_PAGE)});\n if(tasksStatusFilter) params.set('status',tasksStatusFilter);\n const r=await fetch('/api/tasks?'+params);\n const data=await r.json();\n\n // stats\n const allR=await fetch('/api/tasks?limit=1&offset=0');\n const allD=await allR.json();\n document.getElementById('tasksTotalCount').textContent=formatNum(allD.total);\n\n const activeR=await fetch('/api/tasks?status=active&limit=1&offset=0');\n const activeD=await activeR.json();\n document.getElementById('tasksActiveCount').textContent=formatNum(activeD.total);\n\n const compR=await fetch('/api/tasks?status=completed&limit=1&offset=0');\n const compD=await compR.json();\n document.getElementById('tasksCompletedCount').textContent=formatNum(compD.total);\n\n const skipR=await fetch('/api/tasks?status=skipped&limit=1&offset=0');\n const skipD=await skipR.json();\n document.getElementById('tasksSkippedCount').textContent=formatNum(skipD.total);\n\n if(!data.tasks||data.tasks.length===0){\n list.innerHTML='<div style=\"text-align:center;padding:48px;color:var(--text-muted);font-size:14px\" data-i18n=\"tasks.empty\">'+t('tasks.empty')+'</div>';\n document.getElementById('tasksPagination').innerHTML='';\n return;\n }\n\n list.innerHTML=data.tasks.map(task=>{\n const timeStr=formatTime(task.startedAt);\n const endStr=task.endedAt?formatTime(task.endedAt):'';\n const durationStr=task.endedAt?formatDuration(task.endedAt-task.startedAt):'';\n return '<div class=\"task-card status-'+task.status+'\" onclick=\"openTaskDetail(\\''+task.id+'\\')\">'+\n '<div class=\"task-card-top\">'+\n '<div class=\"task-card-title\">'+esc(task.title)+'</div>'+\n '<span class=\"task-status-badge '+task.status+'\">'+task.status+'</span>'+\n '</div>'+\n (task.summary?'<div class=\"task-card-summary\">'+esc(task.summary)+'</div>':'')+\n '<div class=\"task-card-bottom\">'+\n '<span class=\"tag\"><span class=\"icon\">\\u{1F4C5}</span> '+timeStr+'</span>'+\n (durationStr?'<span class=\"tag\"><span class=\"icon\">\\u23F1</span> '+durationStr+'</span>':'')+\n '<span class=\"tag\"><span class=\"icon\">\\u{1F4DD}</span> '+task.chunkCount+' '+(task.chunkCount===1?'chunk':'chunks')+'</span>'+\n '<span class=\"tag\"><span class=\"icon\">\\u{1F4C2}</span> '+task.sessionKey.slice(0,12)+'</span>'+\n '</div>'+\n '</div>';\n }).join('');\n\n renderTasksPagination(data.total);\n }catch(e){\n list.innerHTML='<div style=\"text-align:center;padding:24px;color:var(--rose)\">Failed to load tasks</div>';\n }\n}\n\nfunction renderTasksPagination(total){\n const el=document.getElementById('tasksPagination');\n const pages=Math.ceil(total/TASKS_PER_PAGE);\n if(pages<=1){el.innerHTML='';return;}\n let html='<button class=\"pg-btn'+(tasksPage===0?' disabled':'')+'\" onclick=\"tasksPage=Math.max(0,tasksPage-1);loadTasks()\">\\u2190</button>';\n const start=Math.max(0,tasksPage-2),end=Math.min(pages,tasksPage+3);\n for(let i=start;i<end;i++){\n html+='<button class=\"pg-btn'+(i===tasksPage?' active':'')+'\" onclick=\"tasksPage='+i+';loadTasks()\">'+(i+1)+'</button>';\n }\n html+='<button class=\"pg-btn'+(tasksPage>=pages-1?' disabled':'')+'\" onclick=\"tasksPage=Math.min('+(pages-1)+',tasksPage+1);loadTasks()\">\\u2192</button>';\n html+='<span class=\"pg-info\">'+total+' '+t('pagination.total')+'</span>';\n el.innerHTML=html;\n}\n\nasync function openTaskDetail(taskId){\n const overlay=document.getElementById('taskDetailOverlay');\n overlay.classList.add('show');\n document.getElementById('taskDetailTitle').textContent=t('tasks.loading');\n document.getElementById('taskDetailMeta').innerHTML='';\n document.getElementById('taskDetailSummary').textContent='';\n document.getElementById('taskDetailChunks').innerHTML='<div class=\"spinner\"></div>';\n\n try{\n const r=await fetch('/api/task/'+taskId);\n const task=await r.json();\n\n document.getElementById('taskDetailTitle').textContent=task.title||t('tasks.untitled');\n\n const meta=[\n '<span class=\"meta-item\"><span class=\"task-status-badge '+task.status+'\">'+task.status+'</span></span>',\n '<span class=\"meta-item\">\\u{1F4C5} '+formatTime(task.startedAt)+'</span>',\n ];\n if(task.endedAt) meta.push('<span class=\"meta-item\">\\u2192 '+formatTime(task.endedAt)+'</span>');\n meta.push('<span class=\"meta-item\">\\u{1F4C2} '+task.sessionKey+'</span>');\n meta.push('<span class=\"meta-item\">\\u{1F4DD} '+task.chunks.length+' chunks</span>');\n document.getElementById('taskDetailMeta').innerHTML=meta.join('');\n\n var summaryEl=document.getElementById('taskDetailSummary');\n if(task.status==='skipped'){\n summaryEl.innerHTML='<div style=\"color:var(--text-muted);font-style:italic;display:flex;align-items:flex-start;gap:8px\"><span style=\"font-size:18px\">\\u26A0\\uFE0F</span><span>'+esc(task.summary||t('tasks.skipped.default'))+'</span></div>';\n }else{\n summaryEl.innerHTML=renderSummaryHtml(task.summary);\n }\n\n if(task.chunks.length===0){\n document.getElementById('taskDetailChunks').innerHTML='<div style=\"color:var(--text-muted);padding:12px;font-size:13px\">'+t('tasks.nochunks')+'</div>';\n }else{\n document.getElementById('taskDetailChunks').innerHTML=task.chunks.map(c=>{\n var roleLabel=c.role==='user'?'You':c.role==='assistant'?'Assistant':c.role.toUpperCase();\n return '<div class=\"task-chunk-item role-'+c.role+'\">'+\n '<div class=\"task-chunk-role '+c.role+'\">'+roleLabel+'</div>'+\n '<div class=\"task-chunk-bubble\" onclick=\"this.classList.toggle(\\'expanded\\')\">'+esc(c.content)+'</div>'+\n '<div class=\"task-chunk-time\">'+formatTime(c.createdAt)+'</div>'+\n '</div>';\n }).join('');\n }\n }catch(e){\n document.getElementById('taskDetailTitle').textContent='Error';\n document.getElementById('taskDetailChunks').innerHTML='<div style=\"color:var(--rose)\">Failed to load task details</div>';\n }\n}\n\nfunction closeTaskDetail(event){\n if(event && event.target!==document.getElementById('taskDetailOverlay')) return;\n document.getElementById('taskDetailOverlay').classList.remove('show');\n}\n\nfunction formatDuration(ms){\n const s=Math.floor(ms/1000);\n if(s<60) return s+'s';\n const m=Math.floor(s/60);\n if(m<60) return m+'min';\n const h=Math.floor(m/60);\n if(h<24) return h+'h '+((m%60)>0?(m%60)+'min':'');\n const d=Math.floor(h/24);\n return d+'d '+((h%24)>0?(h%24)+'h':'');\n}\n\nfunction formatTime(ts){\n if(!ts) return '-';\n return new Date(ts).toLocaleString('zh-CN',{month:'2-digit',day:'2-digit',hour:'2-digit',minute:'2-digit'});\n}\n\nfunction fillDays(rows,days){\n const map=new Map((rows||[]).map(r=>[r.date,{...r}]));\n const out=[];const now=new Date();\n for(let i=days-1;i>=0;i--){\n const d=new Date(now);d.setDate(d.getDate()-i);\n const dateStr=d.toISOString().slice(0,10);\n const row=map.get(dateStr)||{};\n out.push({date:dateStr,count:row.count??0,list:row.list??0,search:row.search??0,total:(row.list??0)+(row.search??0)});\n }\n if(days>21){\n const weeks=[];let i=0;\n while(i<out.length){\n const chunk=out.slice(i,i+7);\n const first=chunk[0].date,last=chunk[chunk.length-1].date;\n const c=chunk.reduce((s,r)=>s+r.count,0);\n const l=chunk.reduce((s,r)=>s+r.list,0);\n const se=chunk.reduce((s,r)=>s+r.search,0);\n const label=first.slice(5,10)+'~'+last.slice(8,10);\n weeks.push({date:label,count:c,list:l,search:se,total:l+se});\n i+=7;\n }\n return weeks;\n }\n return out;\n}\n\nfunction renderBars(el,data,valueKey,H){\n const vals=data.map(d=>d[valueKey]??0);\n if(vals.every(v=>v===0)){el.innerHTML='<div style=\"color:var(--text-muted);font-size:13px;padding:20px;text-align:center\">'+t('chart.nodata')+'</div>';return;}\n const max=Math.max(1,...vals);\n el.innerHTML=data.map(r=>{\n const v=r[valueKey]??0;\n const label=r.date.includes('~')?r.date:(r.date.length>5?r.date.slice(5):r.date);\n if(v===0){\n return '<div class=\"chart-bar-wrap\"><div class=\"chart-tip\">0</div><div class=\"chart-bar-col\"><div class=\"chart-bar zero\" style=\"height:2px\"></div></div><div class=\"chart-bar-label\">'+label+'</div></div>';\n }\n const h=Math.max(8,Math.round((v/max)*H));\n return '<div class=\"chart-bar-wrap\"><div class=\"chart-tip\">'+v+'</div><div class=\"chart-bar-col\"><div class=\"chart-bar\" style=\"height:'+h+'px\"></div></div><div class=\"chart-bar-label\">'+label+'</div></div>';\n }).join('');\n}\n\nfunction renderChartWrites(rows){\n const el=document.getElementById('chartWrites');\n const filled=fillDays(rows?.map(r=>({date:r.date,count:r.count})),metricsDays);\n renderBars(el,filled,'count',160);\n}\n\nfunction renderChartCalls(rows){\n const el=document.getElementById('chartCalls');\n const filled=fillDays(rows?.map(r=>({date:r.date,list:r.list,search:r.search})),metricsDays);\n const vals=filled.map(f=>f.total);\n if(vals.every(v=>v===0)){el.innerHTML='<div style=\"color:var(--text-muted);font-size:13px;padding:20px;text-align:center\">'+t('chart.nocalls')+'</div>';return;}\n const max=Math.max(1,...vals);\n const H=160;\n el.innerHTML=filled.map(r=>{\n const label=r.date.includes('~')?r.date:(r.date.length>5?r.date.slice(5):r.date);\n if(r.total===0){\n return '<div class=\"chart-bar-wrap\"><div class=\"chart-tip\">0</div><div class=\"chart-bar-col\"><div class=\"chart-bar zero\" style=\"height:2px\"></div></div><div class=\"chart-bar-label\">'+label+'</div></div>';\n }\n const totalH=Math.max(8,Math.round((r.total/max)*H));\n const listH=r.list?Math.max(3,Math.round((r.list/r.total)*totalH)):0;\n const searchH=r.search?totalH-listH:0;\n const tip='List: '+r.list+', Search: '+r.search;\n let bars='';\n if(searchH>0) bars+='<div class=\"chart-bar violet\" style=\"height:'+searchH+'px\"></div>';\n if(listH>0) bars+='<div class=\"chart-bar\" style=\"height:'+listH+'px\"></div>';\n return '<div class=\"chart-bar-wrap\"><div class=\"chart-tip\">'+tip+'</div><div class=\"chart-bar-col\"><div style=\"display:flex;flex-direction:column;gap:1px\">'+bars+'</div></div><div class=\"chart-bar-label\">'+label+'</div></div>';\n }).join('');\n}\n\nfunction renderBreakdown(obj,containerId){\n const el=document.getElementById(containerId);\n if(!el)return;\n const entries=Object.entries(obj||{}).sort((a,b)=>b[1]-a[1]);\n const total=entries.reduce((s,[,v])=>s+v,0)||1;\n el.innerHTML=entries.map(([label,value])=>{\n const pct=Math.round((value/total)*100);\n return '<div class=\"breakdown-item\"><div class=\"bd-top\"><span class=\"label\">'+esc(label)+'</span><span class=\"value\">'+value+' <span style=\"font-size:11px;font-weight:500;color:var(--text-muted)\">('+pct+'%)</span></span></div><div class=\"breakdown-bar-wrap\"><div class=\"breakdown-bar\" style=\"width:'+pct+'%\"></div></div></div>';\n }).join('');\n}\n\n/* \u2500\u2500\u2500 Data loading \u2500\u2500\u2500 */\nasync function loadAll(){\n await Promise.all([loadStats(),loadMemories()]);\n}\n\nasync function loadStats(){\n const r=await fetch('/api/stats');\n const d=await r.json();\n document.getElementById('statTotal').textContent=d.totalMemories;\n document.getElementById('statSessions').textContent=d.totalSessions;\n document.getElementById('statEmbeddings').textContent=d.totalEmbeddings;\n const days=d.timeRange.earliest?Math.max(1,Math.round((new Date(d.timeRange.latest)-new Date(d.timeRange.earliest))/(86400000))):0;\n document.getElementById('statTimeSpan').textContent=days;\n\n const provEl=document.getElementById('embeddingStatus');\n if(d.embeddingProvider && d.embeddingProvider!=='none'){\n provEl.innerHTML='<div class=\"provider-badge\"><span>\\u2713</span> '+t('embed.on')+d.embeddingProvider+'</div>';\n } else {\n provEl.innerHTML='<div class=\"provider-badge offline\"><span>\\u26A0</span> '+t('embed.off')+'</div>';\n }\n\n const sl=document.getElementById('sessionList');\n sl.innerHTML='<div class=\"session-item'+(activeSession===null?' active':'')+'\" onclick=\"filterSession(null)\"><span>'+t('sidebar.allsessions')+'</span><span class=\"count\">'+d.totalMemories+'</span></div>';\n (d.sessions||[]).forEach(s=>{\n const isActive=activeSession===s.session_key;\n const name=s.session_key.length>20?s.session_key.slice(0,8)+'...'+s.session_key.slice(-8):s.session_key;\n sl.innerHTML+='<div class=\"session-item'+(isActive?' active':'')+'\" onclick=\"filterSession(\\''+s.session_key.replace(/'/g,\"\\\\'\")+'\\')\"><span title=\"'+s.session_key+'\">'+name+'</span><span class=\"count\">'+s.count+'</span></div>';\n });\n}\n\nfunction getFilterParams(){\n const p=new URLSearchParams();\n if(activeSession) p.set('session',activeSession);\n if(activeRole) p.set('role',activeRole);\n const kind=document.getElementById('filterKind').value;\n if(kind) p.set('kind',kind);\n const df=document.getElementById('dateFrom').value;\n if(df) p.set('dateFrom',df);\n const dt=document.getElementById('dateTo').value;\n if(dt) p.set('dateTo',dt);\n const sort=document.getElementById('filterSort').value;\n if(sort==='oldest') p.set('sort','oldest');\n return p;\n}\n\nasync function loadMemories(page){\n if(page) currentPage=page;\n const list=document.getElementById('memoryList');\n list.innerHTML='<div class=\"spinner\"></div>';\n const p=getFilterParams();\n p.set('limit',PAGE_SIZE);\n p.set('page',currentPage);\n const r=await fetch('/api/memories?'+p.toString());\n const d=await r.json();\n totalPages=d.totalPages||1;\n totalCount=d.total||0;\n document.getElementById('searchMeta').textContent=totalCount+t('search.meta.total');\n renderMemories(d.memories||[]);\n renderPagination();\n}\n\nasync function doSearch(q){\n if(!q.trim()){currentPage=1;loadMemories();return}\n const list=document.getElementById('memoryList');\n list.innerHTML='<div class=\"spinner\"></div>';\n const p=getFilterParams();\n p.set('q',q);\n const r=await fetch('/api/search?'+p.toString());\n const d=await r.json();\n const meta=[];\n if(d.vectorCount>0) meta.push(d.vectorCount+t('search.meta.semantic'));\n if(d.ftsCount>0) meta.push(d.ftsCount+t('search.meta.text'));\n meta.push(d.total+t('search.meta.results'));\n document.getElementById('searchMeta').textContent=meta.join(' \\u00B7 ');\n renderMemories(d.results||[]);\n document.getElementById('pagination').innerHTML='';\n}\n\nfunction debounceSearch(){\n clearTimeout(searchTimer);\n searchTimer=setTimeout(()=>doSearch(document.getElementById('searchInput').value),350);\n}\n\nfunction filterSession(key){\n activeSession=key;\n currentPage=1;\n loadAll();\n}\n\nfunction setRoleFilter(btn,role){\n activeRole=role;\n currentPage=1;\n document.querySelectorAll('.filter-chip').forEach(c=>c.classList.remove('active'));\n btn.classList.add('active');\n applyFilters();\n}\n\nfunction applyFilters(){\n currentPage=1;\n if(document.getElementById('searchInput').value.trim()){\n doSearch(document.getElementById('searchInput').value);\n } else {\n loadMemories();\n }\n}\n\nfunction clearDateFilter(){\n document.getElementById('dateFrom').value='';\n document.getElementById('dateTo').value='';\n applyFilters();\n}\n\n/* \u2500\u2500\u2500 Rendering \u2500\u2500\u2500 */\nfunction renderMemories(items){\n const list=document.getElementById('memoryList');\n if(!items.length){\n list.innerHTML='<div class=\"empty\"><div class=\"icon\">\\u{1F4ED}</div><p>'+t('empty.text')+'</p></div>';\n return;\n }\n items.forEach(m=>{memoryCache[m.id]=m});\n list.innerHTML=items.map(m=>{\n const time=m.created_at?new Date(typeof m.created_at==='number'?m.created_at:m.created_at).toLocaleString('zh-CN'):'';\n const role=m.role||'user';\n const kind=m.kind||'paragraph';\n const summary=esc(m.summary||m.content?.slice(0,120)||'');\n const content=esc(m.content||'');\n const id=m.id;\n const vscore=m._vscore?'<span class=\"vscore-badge\">'+Math.round(m._vscore*100)+'%</span>':'';\n const sid=m.session_key||'';\n const sidShort=sid.length>18?sid.slice(0,6)+'..'+sid.slice(-6):sid;\n return '<div class=\"memory-card\">'+\n '<div class=\"card-header\"><div class=\"meta\"><span class=\"role-tag '+role+'\">'+role+'</span><span class=\"kind-tag\">'+kind+'</span></div><span class=\"card-time\"><span class=\"session-tag\" title=\"'+esc(sid)+'\">'+esc(sidShort)+'</span> '+time+'</span></div>'+\n '<div class=\"card-summary\">'+summary+'</div>'+\n '<div class=\"card-content\" id=\"content-'+id+'\"><pre>'+content+'</pre></div>'+\n '<div class=\"card-actions\">'+\n '<button class=\"btn btn-sm btn-ghost\" onclick=\"toggleContent(\\''+id+'\\')\">'+t('card.expand')+'</button>'+\n '<button class=\"btn btn-sm btn-ghost\" onclick=\"openEditModal(\\''+id+'\\')\">'+t('card.edit')+'</button>'+\n '<button class=\"btn btn-sm btn-ghost\" style=\"color:var(--accent)\" onclick=\"deleteMemory(\\''+id+'\\')\">'+t('card.delete')+'</button>'+\n vscore+\n '</div></div>';\n }).join('');\n}\n\nfunction renderPagination(){\n const el=document.getElementById('pagination');\n if(totalPages<=1){el.innerHTML='';return}\n let h='';\n h+='<button class=\"pg-btn'+(currentPage<=1?' disabled':'')+'\" onclick=\"goPage('+(currentPage-1)+')\">\u2039</button>';\n const range=[];\n range.push(1);\n for(let i=Math.max(2,currentPage-2);i<=Math.min(totalPages-1,currentPage+2);i++) range.push(i);\n if(totalPages>1) range.push(totalPages);\n const unique=[...new Set(range)].sort((a,b)=>a-b);\n let prev=0;\n for(const p of unique){\n if(p-prev>1) h+='<span class=\"pg-info\">...</span>';\n h+='<button class=\"pg-btn'+(p===currentPage?' active':'')+'\" onclick=\"goPage('+p+')\">'+p+'</button>';\n prev=p;\n }\n h+='<button class=\"pg-btn'+(currentPage>=totalPages?' disabled':'')+'\" onclick=\"goPage('+(currentPage+1)+')\">\u203A</button>';\n h+='<span class=\"pg-info\">'+totalCount+t('pagination.total')+'</span>';\n el.innerHTML=h;\n}\n\nfunction goPage(p){\n if(p<1||p>totalPages||p===currentPage) return;\n currentPage=p;\n loadMemories();\n document.getElementById('memoryList').scrollIntoView({behavior:'smooth',block:'start'});\n}\n\nfunction toggleContent(id){\n const el=document.getElementById('content-'+id);\n el.classList.toggle('show');\n}\n\nfunction esc(s){\n if(!s)return'';\n return s.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/\"/g,'"');\n}\n\nfunction renderSummaryHtml(raw){\n if(!raw)return'';\n var lines=raw.split('\\n');\n var html=[];\n var inList=false;\n var sectionRe=new RegExp('^(\uD83C\uDFAF|\uD83D\uDCCB|\u2705|\uD83D\uDCA1)\\\\s+(.+)$');\n var listRe=new RegExp('^- (.+)$');\n for(var i=0;i<lines.length;i++){\n var line=lines[i];\n var hm=line.match(sectionRe);\n if(hm){\n if(inList){html.push('</ul>');inList=false;}\n html.push('<div class=\"summary-section-title\">'+esc(line)+'</div>');\n continue;\n }\n var lm=line.match(listRe);\n if(lm){\n if(!inList){html.push('<ul>');inList=true;}\n html.push('<li>'+esc(lm[1])+'</li>');\n continue;\n }\n if(line.trim()===''){\n if(inList){html.push('</ul>');inList=false;}\n continue;\n }\n if(inList){html.push('</ul>');inList=false;}\n html.push('<p style=\"margin:4px 0\">'+esc(line)+'</p>');\n }\n if(inList)html.push('</ul>');\n return html.join('');\n}\n\n/* \u2500\u2500\u2500 CRUD \u2500\u2500\u2500 */\nfunction openCreateModal(){\n editingId=null;\n document.getElementById('modalTitle').textContent=t('modal.new');\n document.getElementById('modalSubmit').textContent=t('modal.create');\n document.getElementById('mRole').value='user';\n document.getElementById('mContent').value='';\n document.getElementById('mSummary').value='';\n document.getElementById('mKind').value='paragraph';\n document.getElementById('modalOverlay').classList.add('show');\n}\n\nfunction openEditModal(id){\n const m=memoryCache[id];\n if(!m){toast(t('toast.notfound'),'error');return}\n editingId=id;\n document.getElementById('modalTitle').textContent=t('modal.edit');\n document.getElementById('modalSubmit').textContent=t('modal.save');\n document.getElementById('mRole').value=m.role||'user';\n document.getElementById('mContent').value=m.content||'';\n document.getElementById('mSummary').value=m.summary||'';\n document.getElementById('mKind').value=m.kind||'paragraph';\n document.getElementById('modalOverlay').classList.add('show');\n}\n\nfunction closeModal(){\n document.getElementById('modalOverlay').classList.remove('show');\n}\n\nasync function submitModal(){\n const data={\n role:document.getElementById('mRole').value,\n content:document.getElementById('mContent').value,\n summary:document.getElementById('mSummary').value,\n kind:document.getElementById('mKind').value,\n };\n if(!data.content.trim()){toast(t('modal.err.empty'),'error');return}\n let r;\n if(editingId){\n r=await fetch('/api/memory/'+editingId,{method:'PUT',headers:{'Content-Type':'application/json'},body:JSON.stringify(data)});\n } else {\n r=await fetch('/api/memory',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(data)});\n }\n const d=await r.json();\n if(d.ok){toast(editingId?t('toast.updated'):t('toast.created'),'success');closeModal();loadAll();}\n else{toast(d.error||t('toast.opfail'),'error')}\n}\n\nasync function deleteMemory(id){\n if(!confirm(t('confirm.delete')))return;\n const r=await fetch('/api/memory/'+id,{method:'DELETE'});\n const d=await r.json();\n if(d.ok){toast(t('toast.deleted'),'success');loadAll();}\n else{toast(t('toast.delfail'),'error')}\n}\n\nasync function clearAll(){\n if(!confirm(t('confirm.clearall')))return;\n if(!confirm(t('confirm.clearall2')))return;\n const r=await fetch('/api/memories',{method:'DELETE'});\n const d=await r.json();\n if(d.ok){toast(t('toast.cleared'),'success');loadAll();}\n else{toast(t('toast.clearfail'),'error')}\n}\n\n/* \u2500\u2500\u2500 Toast \u2500\u2500\u2500 */\nfunction toast(msg,type='info'){\n const c=document.getElementById('toasts');\n const t=document.createElement('div');\n t.className='toast '+type;\n const icons={success:'\\u2705',error:'\\u274C',info:'\\u2139\\uFE0F'};\n t.innerHTML=(icons[type]||'')+' '+esc(msg);\n c.appendChild(t);\n setTimeout(()=>t.remove(),3500);\n}\n\n/* \u2500\u2500\u2500 Theme \u2500\u2500\u2500 */\nconst VIEWER_THEME_KEY='memos-viewer-theme';\nfunction initViewerTheme(){const s=localStorage.getItem(VIEWER_THEME_KEY);const theme=(s==='light'||s==='dark')?s:'dark';document.documentElement.setAttribute('data-theme',theme);}\nfunction toggleViewerTheme(){const el=document.documentElement;const cur=el.getAttribute('data-theme')||'dark';const next=cur==='dark'?'light':'dark';el.setAttribute('data-theme',next);localStorage.setItem(VIEWER_THEME_KEY,next);}\ninitViewerTheme();\n\n/* \u2500\u2500\u2500 Init \u2500\u2500\u2500 */\ndocument.getElementById('modalOverlay').addEventListener('click',e=>{if(e.target.id==='modalOverlay')closeModal()});\ndocument.getElementById('searchInput').addEventListener('keydown',e=>{if(e.key==='Escape'){e.target.value='';loadMemories()}});\napplyI18n();\ncheckAuth();\n</script>\n</body>\n</html>";
|
|
2
2
|
//# sourceMappingURL=html.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/viewer/html.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/viewer/html.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,utzFAi/Cf,CAAC"}
|