@evomap/evolver 1.91.0 → 1.91.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +1 -1
- package/package.json +1 -1
- package/src/atp/hubClient.js +13 -1
- package/src/evolve/guards.js +1 -1
- package/src/evolve/pipeline/collect.js +1 -1
- package/src/evolve/pipeline/dispatch.js +1 -1
- package/src/evolve/pipeline/enrich.js +1 -1
- package/src/evolve/pipeline/hub.js +1 -1
- package/src/evolve/pipeline/select.js +1 -1
- package/src/evolve/pipeline/signals.js +1 -1
- package/src/evolve/utils.js +1 -1
- package/src/evolve.js +1 -1
- package/src/gep/a2aProtocol.js +5175 -1
- package/src/gep/antiAbuseTelemetry.js +233 -1
- package/src/gep/assetStore.js +3 -2
- package/src/gep/autoDistillConv.js +205 -1
- package/src/gep/autoDistillLlm.js +315 -1
- package/src/gep/candidateEval.js +92 -1
- package/src/gep/candidates.js +1 -1
- package/src/gep/contentHash.js +30 -1
- package/src/gep/conversationDistiller.js +270 -1
- package/src/gep/conversationSniffer.js +266 -1
- package/src/gep/crypto.js +93 -1
- package/src/gep/curriculum.js +1 -1
- package/src/gep/deviceId.js +218 -1
- package/src/gep/envFingerprint.js +118 -1
- package/src/gep/epigenetics.js +31 -1
- package/src/gep/execBridge.js +712 -1
- package/src/gep/explore.js +289 -1
- package/src/gep/hash.js +15 -1
- package/src/gep/hubFetch.js +672 -1
- package/src/gep/hubReview.js +212 -1
- package/src/gep/hubSearch.js +544 -1
- package/src/gep/hubVerify.js +306 -1
- package/src/gep/learningSignals.js +1 -1
- package/src/gep/memoryGraph.js +1449 -1
- package/src/gep/memoryGraphAdapter.js +203 -1
- package/src/gep/mutation.js +1 -1
- package/src/gep/narrativeMemory.js +1 -1
- package/src/gep/openPRRegistry.js +205 -1
- package/src/gep/personality.js +1 -1
- package/src/gep/policyCheck.js +599 -1
- package/src/gep/prompt.js +1 -1
- package/src/gep/recallInject.js +409 -1
- package/src/gep/recallVerifier.js +318 -1
- package/src/gep/reflection.js +1 -1
- package/src/gep/savingsCore.js +1 -1
- package/src/gep/selector.js +1 -1
- package/src/gep/skillDistiller.js +1294 -1
- package/src/gep/solidify.js +1 -1
- package/src/gep/strategy.js +136 -1
- package/src/gep/tokenSavings.js +1 -1
- package/src/gep/trajectoryExport.js +3841 -1
- package/src/gep/workspaceKeychain.js +174 -1
- package/src/proxy/extensions/sessionHandler.js +123 -53
- package/src/proxy/extensions/traceControl.js +123 -1
- package/src/proxy/index.js +57 -2
- package/src/proxy/inject.js +52 -1
- package/src/proxy/router/messages_route.js +6 -0
- package/src/proxy/server/routes.js +40 -62
- package/src/proxy/trace/extractor.js +2355 -1
- package/src/proxy/trace/usage.js +105 -1
- package/src/webui/client/clientJs/bootstrap.js +6 -0
- package/src/webui/client/clientJs/github.js +225 -0
- package/src/webui/client/clientJs/i18n.js +14 -0
- package/src/webui/client/clientJs/index.js +3 -0
- package/src/webui/client/clientJs/pipelines.js +3 -1
- package/src/webui/client/indexHtml.js +10 -0
- package/src/webui/client/stylesCss.js +61 -0
- package/src/webui/observer/github.js +340 -0
- package/src/webui/observer/index.js +4 -0
- package/src/webui/server/routes.js +11 -0
package/src/proxy/trace/usage.js
CHANGED
|
@@ -1 +1,105 @@
|
|
|
1
|
-
const _0x1727ea=_0x47a9;function _0x8b35(){const _0x1d2210=['\x78\x58\x5a\x64\x55\x43\x6b\x43\x41\x4a\x33\x63\x55\x4e\x47','\x57\x35\x68\x63\x55\x6d\x6f\x4a\x57\x36\x43','\x57\x51\x4e\x64\x51\x6d\x6b\x4d\x57\x51\x61','\x57\x35\x78\x63\x4e\x6d\x6f\x6b\x66\x33\x4b\x4e\x79\x43\x6b\x67\x69\x53\x6f\x48\x57\x37\x34','\x6a\x62\x43\x55\x57\x37\x4e\x64\x52\x43\x6b\x6b\x63\x38\x6b\x55','\x57\x51\x79\x69\x57\x35\x53\x31\x57\x37\x38','\x57\x4f\x5a\x64\x4d\x43\x6b\x6d\x76\x4a\x75\x49\x73\x43\x6b\x63','\x57\x35\x72\x5a\x41\x61','\x57\x35\x72\x5a\x73\x71\x53\x36\x57\x50\x78\x63\x49\x31\x4b','\x57\x35\x46\x64\x4e\x6d\x6b\x78\x69\x6d\x6f\x72','\x57\x36\x46\x63\x52\x67\x52\x63\x51\x43\x6f\x6f','\x6f\x4e\x46\x64\x4a\x53\x6b\x69\x78\x57\x42\x64\x52\x43\x6f\x57','\x45\x65\x61\x47\x57\x34\x78\x64\x4d\x43\x6b\x5a\x67\x53\x6b\x38','\x6c\x78\x5a\x64\x4a\x6d\x6b\x45\x79\x62\x2f\x64\x54\x43\x6f\x57','\x57\x50\x4a\x63\x4b\x74\x37\x64\x50\x57\x57','\x57\x50\x52\x63\x4b\x59\x56\x64\x51\x47\x68\x63\x53\x43\x6f\x6b\x77\x57','\x6a\x30\x4f\x47\x61\x4e\x65','\x69\x6d\x6f\x37\x65\x38\x6f\x49\x57\x37\x37\x63\x54\x53\x6b\x35\x57\x52\x64\x63\x4c\x53\x6f\x6e\x6e\x38\x6b\x57','\x57\x35\x68\x64\x49\x77\x42\x63\x50\x76\x37\x64\x56\x43\x6b\x66\x6d\x57','\x57\x52\x78\x64\x48\x31\x37\x64\x49\x53\x6f\x51\x75\x66\x75\x61','\x57\x50\x56\x64\x4c\x63\x65','\x64\x6d\x6f\x42\x72\x6d\x6b\x71\x57\x36\x34','\x57\x34\x4a\x64\x4b\x4e\x4e\x63\x56\x4b\x6c\x64\x4f\x6d\x6b\x42\x76\x6d\x6b\x55\x57\x34\x37\x63\x4b\x43\x6f\x4f\x71\x61','\x71\x6d\x6b\x49\x57\x52\x5a\x64\x52\x53\x6f\x51\x57\x4f\x6c\x64\x4d\x6d\x6b\x50','\x57\x4f\x42\x64\x4c\x47\x62\x78\x57\x37\x75','\x57\x34\x5a\x63\x53\x6d\x6f\x46\x70\x77\x75\x4a\x57\x50\x6c\x64\x4b\x61','\x41\x61\x31\x43\x64\x72\x65','\x45\x71\x4c\x4e\x79\x62\x66\x32\x57\x51\x71\x75\x57\x52\x4e\x63\x51\x75\x4c\x50','\x57\x35\x61\x7a\x66\x38\x6f\x52\x44\x30\x47','\x57\x34\x33\x63\x4d\x64\x52\x64\x53\x68\x69','\x46\x49\x79\x6d\x57\x50\x64\x64\x47\x43\x6b\x74\x57\x34\x33\x63\x4e\x61','\x57\x50\x6a\x6c\x57\x37\x64\x64\x51\x43\x6f\x42','\x7a\x63\x58\x51\x70\x47\x33\x63\x4c\x31\x2f\x63\x4a\x47','\x67\x30\x5a\x63\x4c\x48\x52\x64\x50\x5a\x53\x74\x57\x51\x6c\x64\x54\x33\x42\x64\x4b\x53\x6f\x6f','\x62\x66\x68\x63\x49\x47\x34','\x57\x35\x42\x63\x49\x58\x4e\x64\x4a\x32\x38','\x41\x43\x6b\x4e\x57\x51\x5a\x63\x4c\x43\x6f\x49','\x7a\x38\x6b\x65\x57\x52\x56\x63\x4d\x53\x6f\x76','\x44\x43\x6b\x76\x57\x52\x4f\x6e\x67\x57','\x69\x43\x6b\x38\x57\x52\x34\x37\x68\x63\x72\x30','\x57\x4f\x75\x6e\x57\x34\x31\x5a\x57\x36\x38','\x72\x6d\x6b\x4b\x57\x52\x57\x2b\x64\x43\x6f\x50','\x73\x53\x6b\x4a\x57\x50\x2f\x64\x50\x53\x6f\x57\x57\x4f\x37\x64\x49\x6d\x6b\x6e','\x57\x52\x74\x63\x50\x53\x6b\x78\x6d\x53\x6b\x48\x57\x37\x72\x49\x75\x47','\x74\x58\x74\x64\x55\x38\x6b\x74\x46\x61','\x57\x51\x78\x63\x54\x49\x4e\x64\x54\x65\x37\x64\x48\x38\x6f\x5a\x46\x5a\x56\x63\x4f\x43\x6f\x49\x63\x57','\x7a\x75\x71\x5a\x57\x34\x78\x64\x49\x71','\x57\x35\x50\x4e\x68\x73\x74\x63\x4d\x76\x42\x64\x55\x64\x2f\x63\x50\x53\x6b\x5a\x62\x65\x38','\x41\x48\x33\x63\x54\x30\x79\x73\x57\x51\x56\x63\x49\x61\x31\x59\x69\x38\x6f\x37\x57\x34\x43','\x57\x34\x70\x63\x49\x32\x71\x5a\x57\x51\x42\x64\x4a\x43\x6f\x75\x62\x49\x4a\x64\x54\x6d\x6b\x65','\x68\x53\x6f\x7a\x79\x6d\x6b\x2b\x57\x34\x37\x63\x52\x47','\x57\x4f\x64\x64\x4c\x73\x6a\x52\x57\x37\x70\x64\x54\x43\x6f\x71\x67\x71','\x57\x4f\x35\x70\x73\x43\x6b\x33\x6a\x57\x2f\x64\x4b\x53\x6f\x49\x6b\x38\x6b\x6f\x68\x61\x69','\x57\x50\x50\x35\x71\x75\x53\x47','\x57\x37\x2f\x64\x54\x76\x5a\x63\x52\x72\x70\x63\x4e\x6d\x6f\x31\x43\x71','\x62\x53\x6f\x5a\x57\x52\x69\x64\x6c\x38\x6f\x6b\x78\x43\x6f\x4d','\x6f\x31\x43\x35\x6d\x66\x79\x57\x57\x51\x38\x6b','\x75\x6d\x6b\x67\x57\x50\x5a\x64\x48\x6d\x6f\x79','\x57\x37\x4e\x64\x50\x78\x4a\x63\x53\x64\x4f','\x57\x35\x56\x63\x4e\x6d\x6b\x39\x74\x48\x6d\x44\x42\x6d\x6b\x73','\x68\x59\x58\x7a\x57\x52\x74\x63\x4e\x67\x39\x31\x42\x61','\x57\x51\x76\x45\x7a\x4c\x47\x4e\x6b\x71\x6c\x64\x4a\x61','\x43\x49\x64\x64\x49\x33\x69\x6d\x57\x50\x5a\x64\x54\x62\x61','\x71\x30\x72\x73\x45\x74\x64\x64\x53\x63\x33\x63\x4f\x61','\x57\x34\x42\x63\x4a\x30\x4e\x63\x51\x53\x6f\x77\x57\x50\x74\x64\x47\x43\x6b\x53','\x57\x37\x56\x64\x55\x6d\x6b\x73','\x44\x43\x6b\x53\x57\x50\x70\x63\x4f\x71','\x57\x52\x4b\x5a\x77\x32\x47\x74\x57\x50\x31\x58\x57\x35\x65\x79\x69\x4e\x56\x64\x4f\x38\x6f\x4a','\x71\x4a\x4e\x64\x55\x53\x6b\x44\x42\x61','\x78\x33\x35\x6e\x57\x37\x72\x64','\x57\x51\x69\x67\x57\x37\x4f\x59\x57\x36\x48\x37\x57\x52\x4a\x63\x52\x47','\x45\x59\x7a\x57\x6c\x61','\x57\x34\x4e\x63\x4e\x4a\x42\x64\x54\x57','\x66\x74\x39\x76\x57\x51\x4e\x63\x4d\x57','\x57\x50\x33\x63\x52\x38\x6f\x62\x57\x37\x66\x36','\x57\x50\x46\x64\x50\x43\x6b\x6c\x73\x71','\x57\x51\x79\x51\x57\x37\x6e\x63\x57\x36\x48\x79\x6c\x72\x47','\x57\x50\x38\x31\x74\x32\x70\x64\x4a\x47\x57','\x71\x4d\x72\x31\x57\x51\x2f\x63\x55\x31\x44\x43\x43\x71','\x57\x37\x31\x49\x6f\x49\x39\x66','\x57\x4f\x57\x34\x57\x37\x66\x4e\x57\x36\x75','\x61\x47\x54\x58\x6a\x62\x4b','\x71\x57\x69\x4d\x57\x51\x37\x64\x48\x47','\x6f\x58\x62\x34\x57\x4f\x64\x63\x52\x71','\x66\x30\x2f\x64\x4d\x38\x6f\x53\x42\x49\x46\x63\x49\x43\x6f\x4a\x41\x31\x57\x74\x57\x51\x57','\x57\x36\x78\x63\x55\x76\x46\x63\x53\x38\x6f\x30','\x6a\x48\x58\x58\x57\x4f\x78\x63\x4e\x43\x6f\x5a\x74\x38\x6b\x46\x57\x35\x48\x54\x57\x34\x56\x64\x48\x4a\x65','\x63\x58\x72\x5a\x6b\x62\x34','\x6b\x38\x6b\x56\x57\x51\x53\x36\x68\x71','\x6a\x48\x44\x6e\x65\x64\x79','\x74\x72\x37\x63\x47\x43\x6b\x4d','\x75\x43\x6b\x67\x57\x4f\x70\x64\x51\x53\x6f\x74','\x70\x65\x34\x34\x70\x66\x65','\x57\x34\x74\x63\x49\x67\x65\x33\x57\x51\x4a\x63\x49\x6d\x6b\x77\x6f\x61\x2f\x64\x55\x53\x6b\x41\x57\x34\x37\x64\x4e\x61','\x57\x52\x68\x64\x54\x6d\x6f\x63\x57\x35\x30\x46\x65\x43\x6b\x54\x67\x61','\x57\x50\x53\x42\x57\x34\x71\x35\x57\x37\x34','\x57\x51\x33\x64\x4c\x4c\x4e\x63\x47\x71','\x57\x36\x70\x64\x4c\x4b\x35\x68\x46\x66\x4a\x63\x55\x4e\x75','\x57\x51\x50\x56\x57\x34\x33\x64\x56\x61','\x65\x43\x6f\x66\x44\x43\x6b\x55\x57\x34\x64\x63\x4c\x61\x42\x63\x4f\x71','\x76\x38\x6b\x35\x57\x52\x74\x64\x51\x53\x6f\x54\x57\x50\x70\x64\x4e\x43\x6b\x66','\x57\x4f\x68\x64\x4b\x32\x52\x63\x55\x38\x6f\x6d\x57\x4f\x2f\x64\x4c\x6d\x6b\x51','\x57\x51\x54\x69\x57\x34\x52\x64\x55\x4d\x6a\x6b\x57\x36\x62\x71','\x72\x38\x6b\x47\x57\x51\x38\x2f\x63\x57','\x57\x34\x39\x50\x42\x47\x38\x39\x57\x4f\x4a\x63\x55\x4b\x4f','\x74\x62\x46\x64\x4a\x31\x4e\x63\x50\x33\x47\x4f\x57\x4f\x57','\x57\x37\x34\x4d\x46\x71\x56\x64\x4c\x57','\x65\x74\x66\x45\x57\x52\x71'];_0x8b35=function(){return _0x1d2210;};return _0x8b35();}(function(_0xc70060,_0x475483){const _0x250276=_0x47a9,_0xb806c7=_0xc70060();while(!![]){try{const _0x4a8960=-parseInt(_0x250276(0x211,'\x39\x6e\x59\x49'))/(-0x5*-0x2dd+-0x11*-0x224+-0x32b4)+-parseInt(_0x250276(0x227,'\x61\x58\x48\x24'))/(-0x2*-0xbd2+0x26d8+0x5ae*-0xb)*(-parseInt(_0x250276(0x1d8,'\x33\x78\x37\x71'))/(-0x3*0x1eb+-0x1d*-0xad+-0x1*0xdd5))+-parseInt(_0x250276(0x201,'\x70\x65\x68\x26'))/(0x35a+0x1363+-0x16b9)+-parseInt(_0x250276(0x1e1,'\x66\x49\x35\x35'))/(-0x9f7*-0x3+-0x13f5+-0x9eb)+-parseInt(_0x250276(0x20b,'\x5b\x34\x54\x76'))/(-0xc83+0x1db3+0x1*-0x112a)*(-parseInt(_0x250276(0x1e2,'\x58\x53\x41\x64'))/(0x4a*0x4a+-0xf89+-0x5d4*0x1))+parseInt(_0x250276(0x22b,'\x39\x45\x56\x35'))/(0x1766+0x1*0x19af+-0x310d)*(parseInt(_0x250276(0x221,'\x66\x49\x35\x35'))/(0x1*0x1cf+0x1859+-0x1a1f))+parseInt(_0x250276(0x1da,'\x77\x66\x5d\x34'))/(-0x224+-0x1e85+0x1*0x20b3);if(_0x4a8960===_0x475483)break;else _0xb806c7['push'](_0xb806c7['shift']());}catch(_0x328acf){_0xb806c7['push'](_0xb806c7['shift']());}}}(_0x8b35,-0x20aa0*0x3+0xa9374+0x35645));const _0x5027ea=(function(){let _0x52ef4c=!![];return function(_0x4d9609,_0x58f944){const _0x394652=_0x52ef4c?function(){const _0x31c827=_0x47a9;if(_0x58f944){const _0x31491e=_0x58f944[_0x31c827(0x1fe,'\x6a\x65\x73\x6d')](_0x4d9609,arguments);return _0x58f944=null,_0x31491e;}}:function(){};return _0x52ef4c=![],_0x394652;};}()),_0xcfabf9=_0x5027ea(this,function(){const _0x5663c5=_0x47a9,_0x56dd00={};_0x56dd00[_0x5663c5(0x225,'\x2a\x4a\x64\x6e')]=_0x5663c5(0x209,'\x49\x29\x66\x39')+_0x5663c5(0x1f2,'\x58\x53\x41\x64');const _0x473d65=_0x56dd00;return _0xcfabf9[_0x5663c5(0x1f8,'\x4d\x78\x28\x53')]()[_0x5663c5(0x219,'\x61\x58\x48\x24')](_0x473d65[_0x5663c5(0x218,'\x67\x73\x51\x32')])[_0x5663c5(0x236,'\x2a\x75\x5b\x77')]()[_0x5663c5(0x1ed,'\x39\x6e\x59\x49')+_0x5663c5(0x1f7,'\x4d\x78\x28\x53')](_0xcfabf9)[_0x5663c5(0x23d,'\x36\x25\x6a\x4c')](_0x5663c5(0x202,'\x6a\x65\x73\x6d')+_0x5663c5(0x212,'\x39\x6e\x59\x49'));});_0xcfabf9();'use strict';const _0x29b9aa=require('\x66\x73'),{resolveTraceFile:_0x1dc77c,resolveEvomapNodeSecret:_0x256249,decryptTraceEnvelope:_0x28470c}=require(_0x1727ea(0x1e9,'\x65\x4a\x25\x4d')+_0x1727ea(0x231,'\x5d\x36\x41\x59')),_0x13b1d2={};_0x13b1d2[_0x1727ea(0x1e7,'\x31\x74\x4d\x63')+_0x1727ea(0x1ef,'\x4e\x75\x35\x23')]=0x0,_0x13b1d2[_0x1727ea(0x1f6,'\x39\x45\x56\x35')+_0x1727ea(0x1dc,'\x34\x48\x46\x4b')]=0x0,_0x13b1d2['\x74\x6f\x74\x61\x6c\x5f\x74\x6f'+_0x1727ea(0x232,'\x57\x43\x5e\x50')]=0x0,_0x13b1d2['\x63\x61\x6c\x6c\x73']=0x0,_0x13b1d2[_0x1727ea(0x203,'\x64\x32\x4b\x52')]=![];const _0x2694e4=Object[_0x1727ea(0x222,'\x31\x74\x4d\x63')](_0x13b1d2);function _0x47a9(_0x4ea43c,_0x34a9fc){_0x4ea43c=_0x4ea43c-(-0x127b*0x2+0xb22+0x1ba7);const _0x49621b=_0x8b35();let _0x51f292=_0x49621b[_0x4ea43c];if(_0x47a9['\x43\x49\x70\x4e\x42\x6d']===undefined){var _0x5e5d8e=function(_0x18550a){const _0x4e6c03='\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x2b\x2f\x3d';let _0x3bb28d='',_0x186645='',_0x3dd6ae=_0x3bb28d+_0x5e5d8e,_0x95c8d2=(''+function(){return 0x13a5+0x1a43+-0x71*0x68;})['\x69\x6e\x64\x65\x78\x4f\x66']('\x0a')!==-(0xe3*-0x29+0xb09+0x3*0x871);for(let _0x4fcd2b=0x1*0xaa9+0xa28+-0x14d1*0x1,_0x16a239,_0x1be235,_0xb6e432=-0x296*0x8+0x209c+-0xbec;_0x1be235=_0x18550a['\x63\x68\x61\x72\x41\x74'](_0xb6e432++);~_0x1be235&&(_0x16a239=_0x4fcd2b%(0x777+-0x2*0xdea+-0x8d*-0x25)?_0x16a239*(0x1*-0x71f+0x1*0x163e+0xedf*-0x1)+_0x1be235:_0x1be235,_0x4fcd2b++%(-0x1cd*-0xb+0x1c4f+-0x106*0x2f))?_0x3bb28d+=_0x95c8d2||_0x3dd6ae['\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74'](_0xb6e432+(-0x105c+0x97b+0x7*0xfd))-(-0x4+-0x10ae+-0x7*-0x264)!==0xad*0x11+0x18ce+-0x244b?String['\x66\x72\x6f\x6d\x43\x68\x61\x72\x43\x6f\x64\x65'](0x226f+0x2*0x7c9+-0x3102&_0x16a239>>(-(-0x4*-0x1e1+-0x15ef+0x1*0xe6d)*_0x4fcd2b&-0xecb*-0x2+-0x1*-0xd32+-0x2ac2)):_0x4fcd2b:0x3f5*-0x2+0x12df*0x2+-0x1dd4){_0x1be235=_0x4e6c03['\x69\x6e\x64\x65\x78\x4f\x66'](_0x1be235);}for(let _0x24a438=0x3*-0x851+0xf*-0x7c+0x2037*0x1,_0x33b8aa=_0x3bb28d['\x6c\x65\x6e\x67\x74\x68'];_0x24a438<_0x33b8aa;_0x24a438++){_0x186645+='\x25'+('\x30\x30'+_0x3bb28d['\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74'](_0x24a438)['\x74\x6f\x53\x74\x72\x69\x6e\x67'](0x149c+-0x153f+0xb3))['\x73\x6c\x69\x63\x65'](-(-0xd4f*0x1+0x3*0xab3+-0x12c8));}return decodeURIComponent(_0x186645);};const _0x286b41=function(_0x3b1eb3,_0x4138be){let _0x96afc9=[],_0x105baa=-0x72e+0x25*0xd6+-0x17c0,_0x1b2e16,_0x4e4bd7='';_0x3b1eb3=_0x5e5d8e(_0x3b1eb3);let _0xd5f1b8;for(_0xd5f1b8=0x2515*0x1+-0x368*0x7+-0xd3d;_0xd5f1b8<0x1c5a+0x56*-0x3c+0x133*-0x6;_0xd5f1b8++){_0x96afc9[_0xd5f1b8]=_0xd5f1b8;}for(_0xd5f1b8=-0x2587+-0x2278+-0xa49*-0x7;_0xd5f1b8<0x165e+-0x2271+0xd13;_0xd5f1b8++){_0x105baa=(_0x105baa+_0x96afc9[_0xd5f1b8]+_0x4138be['\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74'](_0xd5f1b8%_0x4138be['\x6c\x65\x6e\x67\x74\x68']))%(0xc2c+-0x1dd7+0x12ab),_0x1b2e16=_0x96afc9[_0xd5f1b8],_0x96afc9[_0xd5f1b8]=_0x96afc9[_0x105baa],_0x96afc9[_0x105baa]=_0x1b2e16;}_0xd5f1b8=0x1*0x11cc+0x1a58+0xb09*-0x4,_0x105baa=0x1*-0xadb+-0x2*0xd27+0x2529;for(let _0x818686=-0x1a1*0x17+0xe5f+0x2*0xb8c;_0x818686<_0x3b1eb3['\x6c\x65\x6e\x67\x74\x68'];_0x818686++){_0xd5f1b8=(_0xd5f1b8+(0x7*-0x1c3+0x1*-0xb8f+0x17e5))%(0x1*-0xcc8+-0x6*0xa6+-0x46b*-0x4),_0x105baa=(_0x105baa+_0x96afc9[_0xd5f1b8])%(0x4fd+-0x9*-0x241+0xc23*-0x2),_0x1b2e16=_0x96afc9[_0xd5f1b8],_0x96afc9[_0xd5f1b8]=_0x96afc9[_0x105baa],_0x96afc9[_0x105baa]=_0x1b2e16,_0x4e4bd7+=String['\x66\x72\x6f\x6d\x43\x68\x61\x72\x43\x6f\x64\x65'](_0x3b1eb3['\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74'](_0x818686)^_0x96afc9[(_0x96afc9[_0xd5f1b8]+_0x96afc9[_0x105baa])%(0x480+-0x90d+0x1*0x58d)]);}return _0x4e4bd7;};_0x47a9['\x6a\x48\x78\x6f\x44\x47']=_0x286b41,_0x47a9['\x53\x53\x57\x78\x73\x46']={},_0x47a9['\x43\x49\x70\x4e\x42\x6d']=!![];}const _0x436905=_0x49621b[0x2*-0xb56+-0x813+0x1ebf],_0x1c1545=_0x4ea43c+_0x436905,_0x1441c1=_0x47a9['\x53\x53\x57\x78\x73\x46'][_0x1c1545];if(!_0x1441c1){if(_0x47a9['\x6d\x7a\x49\x45\x47\x73']===undefined){const _0x1932ce=function(_0x4ccb49){this['\x50\x66\x7a\x4e\x6a\x78']=_0x4ccb49,this['\x6e\x70\x46\x4e\x64\x53']=[0x313+0xcc*0x26+-0x3*0xb1e,0xe9*0x1+-0x1d7a+0x1c91,-0x25f7*0x1+-0x1308+0x38ff],this['\x75\x53\x41\x67\x46\x4a']=function(){return'\x6e\x65\x77\x53\x74\x61\x74\x65';},this['\x75\x45\x43\x74\x6a\x43']='\x5c\x77\x2b\x20\x2a\x5c\x28\x5c\x29\x20\x2a\x7b\x5c\x77\x2b\x20\x2a',this['\x44\x71\x79\x59\x48\x58']='\x5b\x27\x7c\x22\x5d\x2e\x2b\x5b\x27\x7c\x22\x5d\x3b\x3f\x20\x2a\x7d';};_0x1932ce['\x70\x72\x6f\x74\x6f\x74\x79\x70\x65']['\x57\x61\x51\x6f\x67\x58']=function(){const _0x22734a=new RegExp(this['\x75\x45\x43\x74\x6a\x43']+this['\x44\x71\x79\x59\x48\x58']),_0x4987be=_0x22734a['\x74\x65\x73\x74'](this['\x75\x53\x41\x67\x46\x4a']['\x74\x6f\x53\x74\x72\x69\x6e\x67']())?--this['\x6e\x70\x46\x4e\x64\x53'][0x1713+-0x17*0x12f+0x427*0x1]:--this['\x6e\x70\x46\x4e\x64\x53'][-0x3*0x1be+-0x266c+0x2ba6];return this['\x51\x64\x5a\x5a\x6d\x66'](_0x4987be);},_0x1932ce['\x70\x72\x6f\x74\x6f\x74\x79\x70\x65']['\x51\x64\x5a\x5a\x6d\x66']=function(_0x4a6d03){if(!Boolean(~_0x4a6d03))return _0x4a6d03;return this['\x5a\x45\x70\x41\x49\x51'](this['\x50\x66\x7a\x4e\x6a\x78']);},_0x1932ce['\x70\x72\x6f\x74\x6f\x74\x79\x70\x65']['\x5a\x45\x70\x41\x49\x51']=function(_0x1e0712){for(let _0x3a8bbc=-0x2382+-0x242e*0x1+0x47b0,_0x4144de=this['\x6e\x70\x46\x4e\x64\x53']['\x6c\x65\x6e\x67\x74\x68'];_0x3a8bbc<_0x4144de;_0x3a8bbc++){this['\x6e\x70\x46\x4e\x64\x53']['\x70\x75\x73\x68'](Math['\x72\x6f\x75\x6e\x64'](Math['\x72\x61\x6e\x64\x6f\x6d']())),_0x4144de=this['\x6e\x70\x46\x4e\x64\x53']['\x6c\x65\x6e\x67\x74\x68'];}return _0x1e0712(this['\x6e\x70\x46\x4e\x64\x53'][0xf*-0x76+-0x638+-0xd22*-0x1]);},(''+function(){return 0xf*-0xf0+0x13*0x15c+-0xbc4;})['\x69\x6e\x64\x65\x78\x4f\x66']('\x0a')===-(0xf36*-0x1+-0x3a*-0x4+0xe4f)&&new _0x1932ce(_0x47a9)['\x57\x61\x51\x6f\x67\x58'](),_0x47a9['\x6d\x7a\x49\x45\x47\x73']=!![];}_0x51f292=_0x47a9['\x6a\x48\x78\x6f\x44\x47'](_0x51f292,_0x34a9fc),_0x47a9['\x53\x53\x57\x78\x73\x46'][_0x1c1545]=_0x51f292;}else _0x51f292=_0x1441c1;return _0x51f292;}function _0x60126c(_0x52f002){const _0x3a57fb=_0x1727ea,_0x2427c2={'\x73\x56\x45\x4b\x46':function(_0x27e945,_0x175445){return _0x27e945(_0x175445);},'\x78\x4e\x42\x52\x70':function(_0xe2ce84,_0x9b00b9){return _0xe2ce84*_0x9b00b9;}},_0x47534e=_0x52f002&&(_0x52f002[_0x3a57fb(0x1e8,'\x26\x26\x68\x68')+'\x70']||_0x52f002[_0x3a57fb(0x1ff,'\x6a\x65\x73\x6d')+_0x3a57fb(0x23b,'\x39\x45\x56\x35')]);if(_0x47534e){const _0x34797a=Date[_0x3a57fb(0x1f5,'\x2a\x75\x5b\x77')](_0x47534e);if(Number['\x69\x73\x46\x69\x6e\x69\x74\x65'](_0x34797a))return _0x34797a;}if(_0x52f002&&Number[_0x3a57fb(0x226,'\x79\x76\x33\x47')](_0x2427c2[_0x3a57fb(0x229,'\x26\x26\x68\x68')](Number,_0x52f002['\x63\x72\x65\x61\x74\x65\x64\x41'+'\x74'])))return _0x2427c2[_0x3a57fb(0x20a,'\x47\x6d\x55\x6e')](Number(_0x52f002['\x63\x72\x65\x61\x74\x65\x64\x41'+'\x74']),-0x4b5+-0x15c1+-0xf2f*-0x2);return null;}function _0x3d33a9(_0x45adf4={}){const _0x10715f=_0x1727ea,_0x739390={'\x6e\x4c\x6d\x62\x63':function(_0x3a71d7,_0x13d94b){return _0x3a71d7(_0x13d94b);},'\x6f\x63\x62\x74\x47':function(_0x243d5e,_0x1c05f2){return _0x243d5e!=_0x1c05f2;},'\x74\x70\x41\x4b\x5a':function(_0x4549b1){return _0x4549b1();},'\x43\x4f\x53\x5a\x4b':_0x10715f(0x1e4,'\x64\x32\x4b\x52'),'\x77\x6e\x51\x47\x6e':function(_0x294d37,_0xcf8eff){return _0x294d37===_0xcf8eff;},'\x52\x6d\x70\x67\x62':_0x10715f(0x1fa,'\x65\x4a\x25\x4d'),'\x4a\x45\x58\x70\x4c':_0x10715f(0x1df,'\x26\x26\x68\x68'),'\x41\x44\x48\x47\x45':_0x10715f(0x1d4,'\x67\x73\x51\x32'),'\x58\x4b\x77\x6b\x76':function(_0x5c7532,_0x5de8b9,_0x5b767b){return _0x5c7532(_0x5de8b9,_0x5b767b);},'\x61\x61\x47\x45\x56':_0x10715f(0x20c,'\x66\x57\x64\x78'),'\x4a\x50\x51\x56\x4c':function(_0x4a587c,_0x131cc5){return _0x4a587c==_0x131cc5;},'\x6d\x75\x58\x49\x6b':function(_0x144f72,_0x2d797c){return _0x144f72<_0x2d797c;},'\x68\x74\x74\x57\x54':function(_0x1a3eff,_0x2a7f06){return _0x1a3eff>_0x2a7f06;},'\x54\x4a\x5a\x4b\x73':function(_0x57457c,_0x5350d1){return _0x57457c(_0x5350d1);},'\x42\x54\x67\x41\x75':function(_0x57f3b8,_0x25878b){return _0x57f3b8(_0x25878b);},'\x73\x6d\x56\x55\x6a':function(_0x3871a2,_0x13210e){return _0x3871a2>_0x13210e;},'\x77\x68\x51\x74\x67':function(_0x3c854e,_0x517501){return _0x3c854e||_0x517501;},'\x79\x4d\x46\x48\x59':function(_0x3f99ca,_0x5e8191){return _0x3f99ca===_0x5e8191;}},_0x3d50b5=_0x45adf4&&_0x739390[_0x10715f(0x22a,'\x79\x76\x33\x47')](_0x45adf4[_0x10715f(0x1f0,'\x4c\x4b\x44\x76')],null)?Date['\x70\x61\x72\x73\x65'](_0x45adf4['\x73\x69\x6e\x63\x65\x49\x73\x6f']):NaN,_0x441d8f={..._0x2694e4};if(!Number['\x69\x73\x46\x69\x6e\x69\x74\x65'](_0x3d50b5))return _0x441d8f;const _0x2eb4fe=_0x45adf4&&_0x739390[_0x10715f(0x20d,'\x71\x34\x46\x4d')](_0x45adf4[_0x10715f(0x1ea,'\x76\x64\x34\x30')],null)&&Number['\x69\x73\x46\x69\x6e\x69\x74\x65'](Date[_0x10715f(0x1ee,'\x38\x4f\x6f\x54')](_0x45adf4[_0x10715f(0x22f,'\x46\x42\x48\x4f')]))?Date[_0x10715f(0x21e,'\x77\x66\x5d\x34')](_0x45adf4[_0x10715f(0x223,'\x66\x49\x35\x35')]):Date[_0x10715f(0x204,'\x66\x49\x35\x35')]();let _0x51aa02;try{const _0x3feb86=_0x739390[_0x10715f(0x205,'\x31\x74\x4d\x63')](_0x1dc77c),_0x2b5e26={..._0x2694e4};if(!_0x29b9aa[_0x10715f(0x22c,'\x4e\x75\x35\x23')+'\x6e\x63'](_0x3feb86))return _0x2b5e26;_0x51aa02=_0x29b9aa[_0x10715f(0x1fb,'\x6a\x57\x72\x78')+_0x10715f(0x1f1,'\x58\x53\x41\x64')](_0x3feb86,_0x739390[_0x10715f(0x1db,'\x50\x21\x6a\x72')]);}catch(_0x5ce3aa){if(_0x739390[_0x10715f(0x214,'\x57\x43\x5e\x50')](_0x739390['\x52\x6d\x70\x67\x62'],_0x739390[_0x10715f(0x1e3,'\x72\x61\x6e\x40')])){const _0x460913={..._0x2694e4};return _0x460913;}else _0x14eb6e=_0x541503(_0x24d2a5,_0x1ebd31);}let _0x30131f=null;try{_0x30131f=_0x739390[_0x10715f(0x213,'\x71\x34\x46\x4d')](_0x256249);}catch(_0x3883cb){_0x30131f=null;}let _0x2aad6e=-0x1a1d+0x8b*0x4+-0xe3*-0x1b,_0xef3810=0x177a+0x12a*0xd+-0x584*0x7,_0x13c359=-0x1*0x18d9+0x87*-0x2+-0x13*-0x15d;for(const _0x394a81 of _0x51aa02[_0x10715f(0x1e0,'\x5b\x34\x54\x76')]('\x0a')){if(_0x739390[_0x10715f(0x1d9,'\x65\x4a\x25\x4d')]!==_0x739390[_0x10715f(0x1d7,'\x4e\x75\x35\x23')]){const _0x24470a=_0x394a81['\x74\x72\x69\x6d']();if(!_0x24470a)continue;let _0x15fc2c;try{_0x15fc2c=JSON['\x70\x61\x72\x73\x65'](_0x24470a);}catch(_0x4636b7){continue;}if(_0x15fc2c&&_0x15fc2c[_0x10715f(0x1fd,'\x6a\x57\x72\x78')+'\x64']){if(!_0x30131f)continue;try{_0x15fc2c=_0x739390[_0x10715f(0x1f9,'\x5d\x36\x41\x59')](_0x28470c,_0x15fc2c,_0x30131f);}catch(_0x500285){continue;}}if(!_0x15fc2c||typeof _0x15fc2c!==_0x739390[_0x10715f(0x23a,'\x57\x23\x44\x6b')])continue;const _0x56cd0a=_0x60126c(_0x15fc2c);if(_0x739390[_0x10715f(0x1d5,'\x50\x21\x6a\x72')](_0x56cd0a,null)||_0x739390[_0x10715f(0x235,'\x49\x21\x73\x51')](_0x56cd0a,_0x3d50b5)||_0x739390[_0x10715f(0x200,'\x5b\x34\x54\x76')](_0x56cd0a,_0x2eb4fe))continue;const _0xef2c8e=_0x739390[_0x10715f(0x1d6,'\x68\x79\x4a\x4e')](Number,_0x15fc2c[_0x10715f(0x20e,'\x68\x79\x4a\x4e')+_0x10715f(0x1de,'\x33\x78\x37\x71')]),_0x5610f3=_0x739390[_0x10715f(0x216,'\x61\x58\x48\x24')](Number,_0x15fc2c[_0x10715f(0x1ec,'\x4d\x78\x28\x53')+_0x10715f(0x20f,'\x79\x68\x32\x40')]),_0x1901dd=Number['\x69\x73\x46\x69\x6e\x69\x74\x65'](_0xef2c8e)&&_0xef2c8e>0x1c28+-0x1e6e+0x246,_0x3d48cd=Number[_0x10715f(0x230,'\x65\x4a\x25\x4d')](_0x5610f3)&&_0x739390[_0x10715f(0x208,'\x66\x49\x35\x35')](_0x5610f3,0xe2b*0x1+0x24b5+-0x4a0*0xb);if(_0x1901dd)_0x2aad6e+=_0xef2c8e;if(_0x3d48cd)_0xef3810+=_0x5610f3;if(_0x739390[_0x10715f(0x1d3,'\x4e\x40\x55\x40')](_0x1901dd,_0x3d48cd))_0x13c359+=0x1*0x1612+0x1*0x101+-0x1712;}else{const _0x4420dc=_0x429b24&&(_0x126463[_0x10715f(0x228,'\x5b\x34\x54\x76')+'\x70']||_0x345b90['\x63\x72\x65\x61\x74\x65\x64\x41'+_0x10715f(0x1e6,'\x76\x64\x34\x30')]);if(_0x4420dc){const _0x130d6d=_0x26fef4[_0x10715f(0x1eb,'\x61\x58\x48\x24')](_0x4420dc);if(_0x4ad61d[_0x10715f(0x21a,'\x26\x26\x68\x68')](_0x130d6d))return _0x130d6d;}if(_0xdb94e2&&_0x231aa9[_0x10715f(0x1e5,'\x5e\x35\x5b\x5d')](IWCtzy[_0x10715f(0x234,'\x4c\x4b\x44\x76')](_0x5ba44e,_0x27efc0[_0x10715f(0x207,'\x26\x26\x68\x68')+'\x74'])))return IWCtzy[_0x10715f(0x1dd,'\x50\x21\x6a\x72')](_0x3772ba,_0x10cd0a[_0x10715f(0x22e,'\x6f\x48\x30\x70')+'\x74'])*(-0x12c8+-0x13*-0x65+0xf31);return null;}}const _0x20a0d3={..._0x2694e4};if(_0x739390[_0x10715f(0x215,'\x57\x43\x5e\x50')](_0x13c359,0x94*0x2c+0x1a22+0x23e*-0x17))return _0x20a0d3;const _0x546f8e={};return _0x546f8e[_0x10715f(0x1e7,'\x31\x74\x4d\x63')+_0x10715f(0x238,'\x71\x34\x46\x4d')]=_0x2aad6e,_0x546f8e[_0x10715f(0x23c,'\x67\x73\x51\x32')+_0x10715f(0x239,'\x4e\x75\x35\x23')]=_0xef3810,_0x546f8e[_0x10715f(0x210,'\x47\x6d\x55\x6e')+_0x10715f(0x237,'\x47\x6d\x55\x6e')]=_0x2aad6e+_0xef3810,_0x546f8e[_0x10715f(0x21c,'\x4c\x4b\x44\x76')]=_0x13c359,_0x546f8e[_0x10715f(0x1fc,'\x77\x66\x5d\x34')]=!![],_0x546f8e;}const _0x2aba5b={};_0x2aba5b[_0x1727ea(0x22d,'\x2a\x4a\x64\x6e')+'\x61\x67\x65']=_0x3d33a9,module[_0x1727ea(0x217,'\x34\x48\x46\x4b')]=_0x2aba5b;
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Per-run token-usage rollup over the proxy trace log.
|
|
4
|
+
//
|
|
5
|
+
// The local proxy (src/proxy) meters real Anthropic input/output tokens for
|
|
6
|
+
// every Hand /v1/messages call into proxy-traces.jsonl. This reads that log
|
|
7
|
+
// back -- decrypting encrypted rows with the local EvoMap node secret -- and
|
|
8
|
+
// sums the real tokens spent within a time window, giving solidify the
|
|
9
|
+
// MEASURED cost of a derive loop.
|
|
10
|
+
//
|
|
11
|
+
// Best-effort by design: returns measured:false (and never throws) when the
|
|
12
|
+
// proxy was inactive, the node secret is missing, no rows fall in the window,
|
|
13
|
+
// or the in-window rows carried no usage (e.g. streamed-but-unobserved calls).
|
|
14
|
+
// Callers fall back to a grounded estimate in that case.
|
|
15
|
+
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const {
|
|
18
|
+
resolveTraceFile,
|
|
19
|
+
resolveEvomapNodeSecret,
|
|
20
|
+
decryptTraceEnvelope,
|
|
21
|
+
} = require('./extractor');
|
|
22
|
+
|
|
23
|
+
const EMPTY = Object.freeze({
|
|
24
|
+
input_tokens: 0,
|
|
25
|
+
output_tokens: 0,
|
|
26
|
+
total_tokens: 0,
|
|
27
|
+
calls: 0,
|
|
28
|
+
measured: false,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
function _rowTimestampMs(row) {
|
|
32
|
+
const iso = row && (row.timestamp || row.createdAtIso);
|
|
33
|
+
if (iso) {
|
|
34
|
+
const ms = Date.parse(iso);
|
|
35
|
+
if (Number.isFinite(ms)) return ms;
|
|
36
|
+
}
|
|
37
|
+
// createdAt is unix seconds in the Prism trace shape.
|
|
38
|
+
if (row && Number.isFinite(Number(row.createdAt))) return Number(row.createdAt) * 1000;
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Sum the real token usage the proxy recorded within a run's time window.
|
|
44
|
+
*
|
|
45
|
+
* @param {object} opts
|
|
46
|
+
* @param {string} opts.sinceIso - REQUIRED lower bound (e.g. last_run.created_at).
|
|
47
|
+
* Without a window we cannot attribute traces to this run, so we report
|
|
48
|
+
* unmeasured rather than summing unrelated calls.
|
|
49
|
+
* @param {string} [opts.untilIso] - upper bound; defaults to now.
|
|
50
|
+
* @returns {{input_tokens:number,output_tokens:number,total_tokens:number,calls:number,measured:boolean}}
|
|
51
|
+
*/
|
|
52
|
+
function sumRunUsage(opts = {}) {
|
|
53
|
+
const sinceMs = opts && opts.sinceIso != null ? Date.parse(opts.sinceIso) : NaN;
|
|
54
|
+
if (!Number.isFinite(sinceMs)) return { ...EMPTY };
|
|
55
|
+
const untilMs = opts && opts.untilIso != null && Number.isFinite(Date.parse(opts.untilIso))
|
|
56
|
+
? Date.parse(opts.untilIso)
|
|
57
|
+
: Date.now();
|
|
58
|
+
|
|
59
|
+
let raw;
|
|
60
|
+
try {
|
|
61
|
+
const file = resolveTraceFile();
|
|
62
|
+
if (!fs.existsSync(file)) return { ...EMPTY };
|
|
63
|
+
raw = fs.readFileSync(file, 'utf8');
|
|
64
|
+
} catch (_) {
|
|
65
|
+
return { ...EMPTY };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let secret = null;
|
|
69
|
+
try { secret = resolveEvomapNodeSecret(); } catch (_) { secret = null; }
|
|
70
|
+
|
|
71
|
+
let input = 0;
|
|
72
|
+
let output = 0;
|
|
73
|
+
let calls = 0;
|
|
74
|
+
for (const line of raw.split('\n')) {
|
|
75
|
+
const s = line.trim();
|
|
76
|
+
if (!s) continue;
|
|
77
|
+
let row;
|
|
78
|
+
try { row = JSON.parse(s); } catch (_) { continue; }
|
|
79
|
+
if (row && row.encrypted) {
|
|
80
|
+
if (!secret) continue; // cannot decrypt -> treat as unobserved
|
|
81
|
+
try { row = decryptTraceEnvelope(row, secret); } catch (_) { continue; }
|
|
82
|
+
}
|
|
83
|
+
if (!row || typeof row !== 'object') continue;
|
|
84
|
+
const ms = _rowTimestampMs(row);
|
|
85
|
+
if (ms == null || ms < sinceMs || ms > untilMs) continue;
|
|
86
|
+
const i = Number(row.input_tokens);
|
|
87
|
+
const o = Number(row.output_tokens);
|
|
88
|
+
const hasI = Number.isFinite(i) && i > 0;
|
|
89
|
+
const hasO = Number.isFinite(o) && o > 0;
|
|
90
|
+
if (hasI) input += i;
|
|
91
|
+
if (hasO) output += o;
|
|
92
|
+
if (hasI || hasO) calls += 1;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (calls === 0) return { ...EMPTY };
|
|
96
|
+
return {
|
|
97
|
+
input_tokens: input,
|
|
98
|
+
output_tokens: output,
|
|
99
|
+
total_tokens: input + output,
|
|
100
|
+
calls,
|
|
101
|
+
measured: true,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
module.exports = { sumRunUsage };
|
|
@@ -7,6 +7,7 @@ const TAB_TITLE_KEYS = {
|
|
|
7
7
|
assets: 'nav.assets',
|
|
8
8
|
interactions: 'nav.interactions',
|
|
9
9
|
personality: 'nav.personality',
|
|
10
|
+
pullrequests: 'nav.pullRequests',
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
function activateTab(tab) {
|
|
@@ -27,6 +28,7 @@ function activateTab(tab) {
|
|
|
27
28
|
if (tab === 'assets') loadAsset(state.currentAsset);
|
|
28
29
|
if (tab === 'interactions') loadInteractions();
|
|
29
30
|
if (tab === 'personality') loadPersonality();
|
|
31
|
+
if (tab === 'pullrequests') loadPullRequests();
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
async function refresh() {
|
|
@@ -35,6 +37,7 @@ async function refresh() {
|
|
|
35
37
|
if (state.currentTab === 'assets') return loadAsset(state.currentAsset);
|
|
36
38
|
if (state.currentTab === 'interactions') return loadInteractions();
|
|
37
39
|
if (state.currentTab === 'personality') return loadPersonality();
|
|
40
|
+
if (state.currentTab === 'pullrequests') return loadPullRequests();
|
|
38
41
|
}
|
|
39
42
|
|
|
40
43
|
function disposeAllCharts() {
|
|
@@ -88,5 +91,8 @@ const localeBtn = $('locale-toggle');
|
|
|
88
91
|
if (localeBtn) localeBtn.addEventListener('click', toggleLocale);
|
|
89
92
|
window.addEventListener('resize', () => Object.values(state.charts).forEach((c) => c.resize && c.resize()));
|
|
90
93
|
window.loadRun = loadRun;
|
|
94
|
+
// GitHub PR hovercards: install the delegated hover listener + prefetch repo
|
|
95
|
+
// info once, so #N references become live cards on every tab.
|
|
96
|
+
initGithub();
|
|
91
97
|
loadOverview();
|
|
92
98
|
`;
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// ---- GitHub PR hovercard + Pull Requests panel ----
|
|
4
|
+
// Replicates Claude Code's "hover a #123 → floating PR status card" behaviour.
|
|
5
|
+
// linkifyPRRefs() turns escaped #N text into <a class="pr-ref">; a single
|
|
6
|
+
// document-level delegated hover then fetches /webui/github/pr/N and renders a
|
|
7
|
+
// floating card (state badge, title, author, +add/-del, N files, relative
|
|
8
|
+
// time). A dedicated Pull Requests tab lists the repo's open PRs, each row
|
|
9
|
+
// itself hoverable.
|
|
10
|
+
exports.githubJs = `
|
|
11
|
+
// Repo info (prUrlBase) for building hrefs. Prefetched at init; linkify falls
|
|
12
|
+
// back to '#' until it resolves (the hovercard fetch works regardless).
|
|
13
|
+
let GITHUB_REPO_INFO = { prUrlBase: null, slug: null, available: false };
|
|
14
|
+
const PR_CARD_CACHE = {}; // number -> normalized PR data (client-side memo)
|
|
15
|
+
|
|
16
|
+
function prUrlFor(n) {
|
|
17
|
+
return GITHUB_REPO_INFO.prUrlBase ? (GITHUB_REPO_INFO.prUrlBase + '/' + n) : '#';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Turn '#123' references inside ALREADY-ESCAPED text into anchor chips.
|
|
21
|
+
// Input MUST be esc()'d first: we only ever linkify plain text, never raw
|
|
22
|
+
// HTML, so we can't corrupt existing markup or attributes. The prefix class
|
|
23
|
+
// [^\\w\\/&] refuses matches after a word char (abc#1), a slash (URL paths)
|
|
24
|
+
// or an ampersand (numeric entities like '), so only free-standing #N
|
|
25
|
+
// becomes a link. The number is [1-9]\\d* — a real PR number is never 0 or
|
|
26
|
+
// zero-padded, so '#0' / '#007' are left as plain text rather than dead chips.
|
|
27
|
+
function linkifyPRRefs(escapedText) {
|
|
28
|
+
if (escapedText == null) return '';
|
|
29
|
+
const s = String(escapedText);
|
|
30
|
+
if (s.indexOf('#') === -1) return s;
|
|
31
|
+
return s.replace(/(^|[^\\w\\/&])#([1-9]\\d*)\\b/g, function (m, pre, num) {
|
|
32
|
+
return pre + '<a class="pr-ref" data-pr="' + num + '" href="' + prUrlFor(num) +
|
|
33
|
+
'" target="_blank" rel="noopener noreferrer">#' + num + '</a>';
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Compact relative time — mirrors the '14m ago' line in the reference card.
|
|
38
|
+
function relativeTime(iso) {
|
|
39
|
+
if (!iso) return '';
|
|
40
|
+
const then = new Date(iso).getTime();
|
|
41
|
+
if (isNaN(then)) return '';
|
|
42
|
+
let secs = Math.floor((Date.now() - then) / 1000);
|
|
43
|
+
const future = secs < 0;
|
|
44
|
+
secs = Math.abs(secs);
|
|
45
|
+
let out;
|
|
46
|
+
if (secs < 45) out = 'just now';
|
|
47
|
+
else if (secs < 5400) { const m = Math.max(1, Math.round(secs / 60)); out = m + 'm'; }
|
|
48
|
+
else if (secs < 86400) { out = Math.round(secs / 3600) + 'h'; }
|
|
49
|
+
else if (secs < 2592000) { out = Math.round(secs / 86400) + 'd'; }
|
|
50
|
+
else if (secs < 31536000) { out = Math.round(secs / 2592000) + 'mo'; }
|
|
51
|
+
else { out = Math.round(secs / 31536000) + 'y'; }
|
|
52
|
+
if (out === 'just now') return out;
|
|
53
|
+
return future ? ('in ' + out) : (out + ' ago');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function prStateLabel(state) {
|
|
57
|
+
const key = 'pr.state.' + state;
|
|
58
|
+
const label = t(key);
|
|
59
|
+
return label === key ? state : label;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// --- Floating hovercard (single instance) ---
|
|
63
|
+
let _prCardEl = null;
|
|
64
|
+
let _prShowTimer = null;
|
|
65
|
+
let _prHideTimer = null;
|
|
66
|
+
let _prActiveNum = null;
|
|
67
|
+
|
|
68
|
+
function ensurePrCard() {
|
|
69
|
+
if (_prCardEl) return _prCardEl;
|
|
70
|
+
_prCardEl = document.createElement('div');
|
|
71
|
+
_prCardEl.id = 'pr-hovercard';
|
|
72
|
+
_prCardEl.className = 'pr-hovercard';
|
|
73
|
+
_prCardEl.style.display = 'none';
|
|
74
|
+
// Keep the card open while the pointer is on it (enterable), so users can
|
|
75
|
+
// click the GitHub link inside.
|
|
76
|
+
_prCardEl.addEventListener('mouseenter', function () { clearTimeout(_prHideTimer); });
|
|
77
|
+
_prCardEl.addEventListener('mouseleave', hidePrCard);
|
|
78
|
+
document.body.appendChild(_prCardEl);
|
|
79
|
+
return _prCardEl;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function prCardLoadingHtml(n) {
|
|
83
|
+
return '<div class="pr-card-head"><span class="pr-badge loading">·</span>' +
|
|
84
|
+
'<span class="pr-card-ref">#' + esc(n) + '</span></div>' +
|
|
85
|
+
'<div class="pr-card-title muted">' + esc(t('pr.loading')) + '</div>';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function prCardUnavailableHtml(n, data) {
|
|
89
|
+
const reason = data && data.reason ? data.reason : 'unavailable';
|
|
90
|
+
return '<div class="pr-card-head"><span class="pr-badge unknown">?</span>' +
|
|
91
|
+
'<a class="pr-card-ref" href="' + prUrlFor(n) + '" target="_blank" rel="noopener noreferrer">#' + esc(n) + '</a></div>' +
|
|
92
|
+
'<div class="pr-card-title muted">' + esc(t('pr.unavailable')) + '</div>' +
|
|
93
|
+
'<div class="pr-card-meta muted small">' + esc(reason) + '</div>';
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function prCardSuccessHtml(d) {
|
|
97
|
+
const state = d.state || 'open';
|
|
98
|
+
const badge = '<span class="pr-badge ' + esc(state) + '">' + esc(prStateLabel(state)) + '</span>';
|
|
99
|
+
const when = d.mergedAt || d.closedAt || d.updatedAt || d.createdAt;
|
|
100
|
+
const rel = relativeTime(when);
|
|
101
|
+
const author = d.author ? ('<span class="pr-card-author">' + esc(d.author) + '</span>') : '';
|
|
102
|
+
const diff = '<span class="pr-diff"><span class="pr-add">+' + esc(d.additions || 0) + '</span> ' +
|
|
103
|
+
'<span class="pr-del">\\u2212' + esc(d.deletions || 0) + '</span></span>';
|
|
104
|
+
const files = '<span class="pr-files">' + esc(d.changedFiles || 0) + ' ' + esc(t('pr.files')) + '</span>';
|
|
105
|
+
return '<div class="pr-card-head">' + badge +
|
|
106
|
+
'<a class="pr-card-ref" href="' + esc(d.url || prUrlFor(d.number)) + '" target="_blank" rel="noopener noreferrer">#' + esc(d.number) + '</a>' +
|
|
107
|
+
(rel ? '<span class="pr-card-time muted">' + esc(rel) + '</span>' : '') +
|
|
108
|
+
'</div>' +
|
|
109
|
+
'<div class="pr-card-title">' + esc(d.title || '') + '</div>' +
|
|
110
|
+
'<div class="pr-card-meta">' + author + diff + files + '</div>';
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function renderPrCard(n, data) {
|
|
114
|
+
const el = ensurePrCard();
|
|
115
|
+
if (!data) el.innerHTML = prCardLoadingHtml(n);
|
|
116
|
+
else if (!data.available) el.innerHTML = prCardUnavailableHtml(n, data);
|
|
117
|
+
else el.innerHTML = prCardSuccessHtml(data);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Position the card above the anchor (as in the reference), flipping below
|
|
121
|
+
// when it would overflow the top of the viewport. Uses fixed positioning so
|
|
122
|
+
// getBoundingClientRect (viewport-relative) maps directly.
|
|
123
|
+
function positionPrCard(anchor) {
|
|
124
|
+
const el = _prCardEl;
|
|
125
|
+
if (!el || !anchor) return;
|
|
126
|
+
const r = anchor.getBoundingClientRect();
|
|
127
|
+
el.style.display = 'block';
|
|
128
|
+
const cw = el.offsetWidth;
|
|
129
|
+
const ch = el.offsetHeight;
|
|
130
|
+
let left = r.left;
|
|
131
|
+
if (left + cw > window.innerWidth - 8) left = Math.max(8, window.innerWidth - cw - 8);
|
|
132
|
+
let top = r.top - ch - 8;
|
|
133
|
+
if (top < 8) top = r.bottom + 8; // flip below when no room above
|
|
134
|
+
el.style.left = Math.round(left) + 'px';
|
|
135
|
+
el.style.top = Math.round(top) + 'px';
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async function showPrCard(anchor) {
|
|
139
|
+
const n = anchor.getAttribute('data-pr');
|
|
140
|
+
if (!n) return;
|
|
141
|
+
_prActiveNum = n;
|
|
142
|
+
renderPrCard(n, PR_CARD_CACHE[n] || null); // instant paint: cache or loading
|
|
143
|
+
positionPrCard(anchor);
|
|
144
|
+
if (PR_CARD_CACHE[n]) return;
|
|
145
|
+
try {
|
|
146
|
+
const data = await api('/webui/github/pr/' + encodeURIComponent(n));
|
|
147
|
+
PR_CARD_CACHE[n] = data;
|
|
148
|
+
if (_prActiveNum === n) { renderPrCard(n, data); positionPrCard(anchor); }
|
|
149
|
+
} catch (err) {
|
|
150
|
+
if (_prActiveNum === n) {
|
|
151
|
+
renderPrCard(n, { number: n, available: false, reason: (err && err.message) || 'error' });
|
|
152
|
+
positionPrCard(anchor);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function hidePrCard() {
|
|
158
|
+
clearTimeout(_prHideTimer);
|
|
159
|
+
_prHideTimer = setTimeout(function () {
|
|
160
|
+
if (_prCardEl) _prCardEl.style.display = 'none';
|
|
161
|
+
_prActiveNum = null;
|
|
162
|
+
}, 180);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function initPrHovercards() {
|
|
166
|
+
ensurePrCard();
|
|
167
|
+
// Event delegation: one pair of listeners covers every current and future
|
|
168
|
+
// .pr-ref, no matter which tab rendered it.
|
|
169
|
+
document.addEventListener('mouseover', function (e) {
|
|
170
|
+
const ref = e.target && e.target.closest ? e.target.closest('.pr-ref') : null;
|
|
171
|
+
if (!ref) return;
|
|
172
|
+
clearTimeout(_prHideTimer);
|
|
173
|
+
clearTimeout(_prShowTimer);
|
|
174
|
+
_prShowTimer = setTimeout(function () { showPrCard(ref); }, 250); // debounce hover
|
|
175
|
+
});
|
|
176
|
+
document.addEventListener('mouseout', function (e) {
|
|
177
|
+
const ref = e.target && e.target.closest ? e.target.closest('.pr-ref') : null;
|
|
178
|
+
if (!ref) return;
|
|
179
|
+
clearTimeout(_prShowTimer);
|
|
180
|
+
hidePrCard();
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async function initGithub() {
|
|
185
|
+
initPrHovercards();
|
|
186
|
+
try {
|
|
187
|
+
const info = await api('/webui/github/repo');
|
|
188
|
+
if (info) GITHUB_REPO_INFO = info;
|
|
189
|
+
} catch (_) { /* linkify falls back to '#'; hovercard still works */ }
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// --- Pull Requests panel ---
|
|
193
|
+
async function loadPullRequests() {
|
|
194
|
+
const host = $('pull-requests');
|
|
195
|
+
if (!host) return;
|
|
196
|
+
// Localized placeholder while the (cold gh pr list) fetch resolves — avoids
|
|
197
|
+
// sitting on the static English "Loading..." from the server-rendered shell.
|
|
198
|
+
host.innerHTML = '<p class="muted">' + esc(t('common.loading')) + '</p>';
|
|
199
|
+
let res;
|
|
200
|
+
try {
|
|
201
|
+
res = await api('/webui/github/prs');
|
|
202
|
+
} catch (err) {
|
|
203
|
+
host.innerHTML = '<p class="status-failed">' + esc(t('pr.loadFailed')) + esc(err.message || '') + '</p>';
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
renderPullRequests(res && res.data ? res.data : []);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function renderPullRequests(prs) {
|
|
210
|
+
const host = $('pull-requests');
|
|
211
|
+
if (!host) return;
|
|
212
|
+
if (!prs.length) {
|
|
213
|
+
// No open PRs (or gh unavailable): guide the user to hover any #N instead.
|
|
214
|
+
host.innerHTML = '<p class="muted">' + esc(t('pr.empty')) + '</p>';
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
host.innerHTML = '<ul class="pr-list">' + prs.map(function (pr) {
|
|
218
|
+
const ref = '<a class="pr-ref" data-pr="' + esc(pr.number) + '" href="' + prUrlFor(pr.number) +
|
|
219
|
+
'" target="_blank" rel="noopener noreferrer">#' + esc(pr.number) + '</a>';
|
|
220
|
+
const branch = pr.headRefName ? ('<span class="pill">' + esc(pr.headRefName) + '</span>') : '';
|
|
221
|
+
const files = '<span class="muted small">' + esc(pr.fileCount || 0) + ' ' + esc(t('pr.files')) + '</span>';
|
|
222
|
+
return '<li class="pr-row">' + ref + ' <span class="pr-row-title">' + esc(pr.title || '') + '</span> ' + branch + ' ' + files + '</li>';
|
|
223
|
+
}).join('') + '</ul>';
|
|
224
|
+
}
|
|
225
|
+
`;
|
|
@@ -36,6 +36,7 @@ const I18N_DICT = {
|
|
|
36
36
|
'nav.assets': { en: 'Assets', zh: '资产' },
|
|
37
37
|
'nav.interactions': { en: 'Interactions', zh: '交互' },
|
|
38
38
|
'nav.personality': { en: 'Personality', zh: '人格' },
|
|
39
|
+
'nav.pullRequests': { en: 'Pull Requests', zh: 'PR' },
|
|
39
40
|
|
|
40
41
|
// ---- Common ----
|
|
41
42
|
'common.loading': { en: 'Loading...', zh: '加载中...' },
|
|
@@ -262,6 +263,19 @@ const I18N_DICT = {
|
|
|
262
263
|
'personality.cat.mutation': { en: 'Mutation', zh: '变异' },
|
|
263
264
|
'personality.cat.asset': { en: 'Asset', zh: '资产' },
|
|
264
265
|
'personality.cat.run': { en: 'Run', zh: '运行' },
|
|
266
|
+
|
|
267
|
+
// ---- Pull Requests (panel + PR hovercard) ----
|
|
268
|
+
'pr.card.title': { en: 'Pull Requests', zh: 'Pull Requests' },
|
|
269
|
+
'pr.card.desc': { en: 'Open pull requests on this repository. Hover any #reference — here or anywhere in the dashboard — for its live GitHub status.', zh: '本仓库的开放 PR。悬浮任意 #编号(此处或仪表盘任意位置)即可查看其 GitHub 实时状态。' },
|
|
270
|
+
'pr.empty': { en: 'No open pull requests (or gh CLI unavailable). Hover a #reference anywhere to fetch its status.', zh: '暂无开放 PR(或 gh CLI 不可用)。悬浮任意位置的 #编号即可拉取其状态。' },
|
|
271
|
+
'pr.loading': { en: 'Loading PR…', zh: '加载 PR 中…' },
|
|
272
|
+
'pr.loadFailed': { en: 'Failed to load pull requests: ', zh: '加载 PR 失败:' },
|
|
273
|
+
'pr.unavailable': { en: 'PR status unavailable', zh: 'PR 状态不可用' },
|
|
274
|
+
'pr.files': { en: 'files', zh: '文件' },
|
|
275
|
+
'pr.state.merged': { en: 'Merged', zh: '已合并' },
|
|
276
|
+
'pr.state.open': { en: 'Open', zh: '开放' },
|
|
277
|
+
'pr.state.closed': { en: 'Closed', zh: '已关闭' },
|
|
278
|
+
'pr.state.draft': { en: 'Draft', zh: '草稿' },
|
|
265
279
|
};
|
|
266
280
|
|
|
267
281
|
// Status / outcome enum tokens — keep raw key as fallback so unknown
|
|
@@ -7,6 +7,7 @@ const { pipelinesJs } = require('./pipelines');
|
|
|
7
7
|
const { assetsJs } = require('./assets');
|
|
8
8
|
const { interactionsJs } = require('./interactions');
|
|
9
9
|
const { personalityJs } = require('./personality');
|
|
10
|
+
const { githubJs } = require('./github');
|
|
10
11
|
const { bootstrapJs } = require('./bootstrap');
|
|
11
12
|
|
|
12
13
|
const SECTION_HEADERS = {
|
|
@@ -16,6 +17,7 @@ const SECTION_HEADERS = {
|
|
|
16
17
|
assets: '// ---- Assets ----',
|
|
17
18
|
interactions: '// ---- Interactions (Hub Activity unified timeline + Agent) ----',
|
|
18
19
|
personality: '// ---- Personality ----',
|
|
20
|
+
github: '// ---- GitHub (PR hovercard + Pull Requests panel) ----',
|
|
19
21
|
bootstrap: '// ---- Tabs ----',
|
|
20
22
|
};
|
|
21
23
|
|
|
@@ -28,6 +30,7 @@ function getClientJs() {
|
|
|
28
30
|
SECTION_HEADERS.assets, assetsJs,
|
|
29
31
|
SECTION_HEADERS.interactions, interactionsJs,
|
|
30
32
|
SECTION_HEADERS.personality, personalityJs,
|
|
33
|
+
SECTION_HEADERS.github, githubJs,
|
|
31
34
|
SECTION_HEADERS.bootstrap, bootstrapJs,
|
|
32
35
|
].join('\n');
|
|
33
36
|
}
|
|
@@ -227,7 +227,9 @@ function renderRunDetail(run) {
|
|
|
227
227
|
) + '</div>';
|
|
228
228
|
}
|
|
229
229
|
if (detail.initialUserPrompt) {
|
|
230
|
-
|
|
230
|
+
// Linkify PR refs (#123) authors wrote in the prompt — esc() FIRST, then
|
|
231
|
+
// linkify the escaped text, so we never turn raw input into markup.
|
|
232
|
+
html += '<div class="detail-block"><h4>' + esc(t('pipelines.detail.initialUserPrompt')) + '</h4><pre class="snippet">' + linkifyPRRefs(esc(detail.initialUserPrompt)) + '</pre></div>';
|
|
231
233
|
}
|
|
232
234
|
html += '</div>';
|
|
233
235
|
}
|
|
@@ -16,6 +16,7 @@ const ICONS = {
|
|
|
16
16
|
refresh: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/><path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"/><path d="M8 16H3v5"/></svg>',
|
|
17
17
|
sun: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/></svg>',
|
|
18
18
|
moon: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/></svg>',
|
|
19
|
+
gitpr: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="18" cy="18" r="3"/><circle cx="6" cy="6" r="3"/><path d="M13 6h3a2 2 0 0 1 2 2v7"/><line x1="6" x2="6" y1="9" y2="21"/></svg>',
|
|
19
20
|
};
|
|
20
21
|
|
|
21
22
|
// Sidebar items reference an i18n key; the live label is rendered by
|
|
@@ -26,6 +27,7 @@ const NAV = [
|
|
|
26
27
|
{ tab: 'assets', icon: 'package', labelKey: 'nav.assets' },
|
|
27
28
|
{ tab: 'interactions', icon: 'activity', labelKey: 'nav.interactions' },
|
|
28
29
|
{ tab: 'personality', icon: 'brain', labelKey: 'nav.personality' },
|
|
30
|
+
{ tab: 'pullrequests', icon: 'gitpr', labelKey: 'nav.pullRequests' },
|
|
29
31
|
];
|
|
30
32
|
|
|
31
33
|
function navItem({ tab, icon, labelKey }, idx) {
|
|
@@ -210,6 +212,14 @@ function getIndexHtml() {
|
|
|
210
212
|
<div id="memory-graph-chart" class="chart-container chart-xl"></div>
|
|
211
213
|
</div>
|
|
212
214
|
</section>
|
|
215
|
+
|
|
216
|
+
<section data-view="pullrequests" class="view">
|
|
217
|
+
<div class="card">
|
|
218
|
+
<h2 data-i18n="pr.card.title">Pull Requests</h2>
|
|
219
|
+
<p class="muted small card-sub" data-i18n="pr.card.desc">Open pull requests on this repository. Hover any #reference — here or anywhere in the dashboard — for its live GitHub status.</p>
|
|
220
|
+
<div id="pull-requests" data-i18n="common.loading">Loading...</div>
|
|
221
|
+
</div>
|
|
222
|
+
</section>
|
|
213
223
|
</main>
|
|
214
224
|
</div>
|
|
215
225
|
</div>
|
|
@@ -633,6 +633,67 @@ tr:last-child td { border-bottom: none; }
|
|
|
633
633
|
border-radius: 10px;
|
|
634
634
|
font-size: 13px;
|
|
635
635
|
}
|
|
636
|
+
|
|
637
|
+
/* ---- GitHub PR references + hovercard + Pull Requests panel ---- */
|
|
638
|
+
.pr-ref {
|
|
639
|
+
color: hsl(var(--accent));
|
|
640
|
+
text-decoration: none;
|
|
641
|
+
font-weight: 600;
|
|
642
|
+
white-space: nowrap;
|
|
643
|
+
border-bottom: 1px dotted hsl(var(--accent) / 0.5);
|
|
644
|
+
}
|
|
645
|
+
.pr-ref:hover { border-bottom-style: solid; }
|
|
646
|
+
|
|
647
|
+
/* Floating card. Uses the (previously unused) popover surface tokens ported
|
|
648
|
+
from evox-desktop, so it matches light/dark automatically. */
|
|
649
|
+
.pr-hovercard {
|
|
650
|
+
position: fixed;
|
|
651
|
+
z-index: 1000;
|
|
652
|
+
max-width: 340px;
|
|
653
|
+
min-width: 220px;
|
|
654
|
+
padding: 12px 14px;
|
|
655
|
+
background: hsl(var(--popover));
|
|
656
|
+
color: hsl(var(--popover-foreground));
|
|
657
|
+
border: 1px solid hsl(var(--border));
|
|
658
|
+
border-radius: 12px;
|
|
659
|
+
box-shadow: 0 8px 28px rgba(0,0,0,0.22);
|
|
660
|
+
font-size: 13px;
|
|
661
|
+
line-height: 1.45;
|
|
662
|
+
pointer-events: auto;
|
|
663
|
+
}
|
|
664
|
+
.pr-card-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
|
|
665
|
+
.pr-card-ref { color: hsl(var(--muted-foreground)); font-weight: 600; text-decoration: none; }
|
|
666
|
+
.pr-card-ref:hover { color: hsl(var(--accent)); }
|
|
667
|
+
.pr-card-time { margin-left: auto; font-size: 12px; }
|
|
668
|
+
.pr-card-title { font-weight: 600; margin: 2px 0 8px 0; word-break: break-word; }
|
|
669
|
+
.pr-card-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; font-size: 12px; }
|
|
670
|
+
.pr-card-author { color: hsl(var(--muted-foreground)); }
|
|
671
|
+
.pr-diff { font-variant-numeric: tabular-nums; }
|
|
672
|
+
.pr-add { color: hsl(var(--success)); font-weight: 600; }
|
|
673
|
+
.pr-del { color: hsl(var(--destructive)); font-weight: 600; }
|
|
674
|
+
.pr-files { color: hsl(var(--muted-foreground)); }
|
|
675
|
+
|
|
676
|
+
/* Status badge — colour keyed to normalized state. */
|
|
677
|
+
.pr-badge {
|
|
678
|
+
display: inline-flex;
|
|
679
|
+
align-items: center;
|
|
680
|
+
padding: 1px 9px;
|
|
681
|
+
border-radius: 999px;
|
|
682
|
+
font-size: 11px;
|
|
683
|
+
font-weight: 700;
|
|
684
|
+
text-transform: none;
|
|
685
|
+
white-space: nowrap;
|
|
686
|
+
}
|
|
687
|
+
.pr-badge.merged { background: hsl(271 60% 55% / 0.16); color: hsl(271 60% 60%); }
|
|
688
|
+
.pr-badge.open { background: hsl(var(--success) / 0.16); color: hsl(var(--success)); }
|
|
689
|
+
.pr-badge.closed { background: hsl(var(--destructive) / 0.16); color: hsl(var(--destructive)); }
|
|
690
|
+
.pr-badge.draft { background: hsl(var(--muted-foreground) / 0.16); color: hsl(var(--muted-foreground)); }
|
|
691
|
+
.pr-badge.unknown,
|
|
692
|
+
.pr-badge.loading { background: hsl(var(--muted-foreground) / 0.14); color: hsl(var(--muted-foreground)); }
|
|
693
|
+
|
|
694
|
+
.pr-list { list-style: none; margin: 4px 0 0 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
|
|
695
|
+
.pr-row { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding: 8px 10px; border: 1px solid hsl(var(--border) / 0.5); border-radius: 10px; }
|
|
696
|
+
.pr-row-title { flex: 1 1 auto; min-width: 0; word-break: break-word; }
|
|
636
697
|
`;
|
|
637
698
|
}
|
|
638
699
|
|