limixbot 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{ActivityPanel-O6Su2c-u.js → ActivityPanel-CagbdBtd.js} +1 -1
- package/dist/assets/{App-Bcey1qup.js → App-DFjF9FvF.js} +119 -119
- package/dist/assets/{AppEventEditor-BlJGPJ3Z.js → AppEventEditor-BgX3KO6T.js} +1 -1
- package/dist/assets/BotSettingsDialog-ieeszW_3.js +16 -0
- package/dist/assets/{BrowserPanel-BWcb5CXi.js → BrowserPanel-BB3qz5lN.js} +2 -2
- package/dist/assets/{BrowserProfilesManager-dKHyQotG.js → BrowserProfilesManager-CVdcfOF8.js} +1 -1
- package/dist/assets/CloudAddDialog-Bl1bRrYD.js +1 -0
- package/dist/assets/{ComputerFilesPane-wgtikCgi.js → ComputerFilesPane-piKNDkt6.js} +1 -1
- package/dist/assets/ComputerPanel-COQweEJR.js +2 -0
- package/dist/assets/{DataPanel-BlBidswi.js → DataPanel-DdHxcsUa.js} +1 -1
- package/dist/assets/{DesktopViewer-D7JeLJbi.js → DesktopViewer-BNIgo9Nm.js} +1 -1
- package/dist/assets/{FilesView-CNkEKeZB.js → FilesView-Dy1gKmcM.js} +1 -1
- package/dist/assets/{GrokMoveDialog-fyBulzXL.js → GrokMoveDialog-CUnJWZi7.js} +6 -6
- package/dist/assets/{InspectorPanel-Cut2OqiB.js → InspectorPanel-CWdxtHne.js} +2 -2
- package/dist/assets/{KeyboardShortcutsModal-DnxUB4cd.js → KeyboardShortcutsModal-6FMUgbpC.js} +1 -1
- package/dist/assets/{LiveDesktop-CnbyXW61.js → LiveDesktop-CDbI9dPy.js} +1 -1
- package/dist/assets/LocalVmWorkspace-CslSGvNI.js +1 -0
- package/dist/assets/{MacLocalControl-CpswtfCI.js → MacLocalControl-CwHtEWES.js} +1 -1
- package/dist/assets/MarkdownFilePreview-DrdGFCnN.js +1 -0
- package/dist/assets/{MenuMotion-VeZ_fZ8M.js → MenuMotion-IQitGKH4.js} +1 -1
- package/dist/assets/{NewBotDialog-rBjsSV0e.js → NewBotDialog-V2wMpLPn.js} +1 -1
- package/dist/assets/PhoneAppDialog-DmBPVDxr.js +1 -0
- package/dist/assets/{PlacesRail-C_3Mh4C8.js → PlacesRail-v1XIqiBG.js} +9 -9
- package/dist/assets/{PluginsPanel-CMsgWSNg.js → PluginsPanel-CMARnTMq.js} +2 -2
- package/dist/assets/{ProIntroduction-6ByF2_US.js → ProIntroduction--jIMb4bL.js} +1 -1
- package/dist/assets/{RemoteAgentSettingsPanel-D4X4rHMQ.js → RemoteAgentSettingsPanel-Co34aJHb.js} +1 -1
- package/dist/assets/{RoomPanel-mg6M04wy.js → RoomPanel-ClyWQx9x.js} +2 -2
- package/dist/assets/{RoutinesPage-DomuZMUT.js → RoutinesPage-DRwSDyGu.js} +1 -1
- package/dist/assets/SettingsModal-CHa_Zc-J.js +11 -0
- package/dist/assets/{ShareTeamDialog-B_0Gr8Mq.js → ShareTeamDialog-BQ9h2Rd2.js} +1 -1
- package/dist/assets/{SignedInSites-C-eqeBxT.js → SignedInSites-B16Ruhd0.js} +1 -1
- package/dist/assets/{TeamLibraryPanel-DpXOFOQr.js → TeamLibraryPanel-NwC4Fc9C.js} +1 -1
- package/dist/assets/TeamMapPage-DabJFxkf.js +1 -0
- package/dist/assets/{TriggersPage-D7RDjrjV.js → TriggersPage-Cn_f8AcZ.js} +1 -1
- package/dist/assets/{VisibilitySection-Bimhk6c5.js → VisibilitySection-DyGNmx9n.js} +1 -1
- package/dist/assets/{WebhookTrigger-D5c2bPJu.js → WebhookTrigger-C-9-FE3w.js} +1 -1
- package/dist/assets/WorksOnGrid-M_5NkZch.js +1 -0
- package/dist/assets/{abnfDiagram-YUKMZFIV-D7az-C1J.js → abnfDiagram-YUKMZFIV-CBzJU2O6.js} +1 -1
- package/dist/assets/{activity-W_ia4q-Y.js → activity-bd7MWK8m.js} +1 -1
- package/dist/assets/{architectureDiagram-47P4ROYG-B2IC9169.js → architectureDiagram-47P4ROYG-DVR1DP3v.js} +1 -1
- package/dist/assets/{blockDiagram-E7TT5TSB-FnweBzU4.js → blockDiagram-E7TT5TSB-BYqUHhoh.js} +1 -1
- package/dist/assets/{c4Diagram-CRA5TL53-rxgwSaAP.js → c4Diagram-CRA5TL53-BtQERHwr.js} +1 -1
- package/dist/assets/{calendar-days-wM1DS-Cu.js → calendar-days-YMHxUvlg.js} +1 -1
- package/dist/assets/channel-D6e78p3W.js +1 -0
- package/dist/assets/{chunk-2Q5K7J3B-B7yhqEe8.js → chunk-2Q5K7J3B-Cwf_xeHP.js} +1 -1
- package/dist/assets/{chunk-5VM5RSS4-Sw6phnaf.js → chunk-5VM5RSS4-Doo-zxI4.js} +1 -1
- package/dist/assets/{chunk-7TKQ45FW-CheglUSd.js → chunk-7TKQ45FW-CD2AgrRj.js} +1 -1
- package/dist/assets/{chunk-AW2ZBBNX-CswkqPkf.js → chunk-AW2ZBBNX-e5OuWeq_.js} +1 -1
- package/dist/assets/{chunk-FVRAUYC3-DeN53o4S.js → chunk-FVRAUYC3-C8jo43it.js} +2 -2
- package/dist/assets/{chunk-HTAEGDNF-CCZ_Udf0.js → chunk-HTAEGDNF-DLsD4agj.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-nG1rfC9P.js → chunk-JWPE2WC7-UZDUbeTy.js} +1 -1
- package/dist/assets/{chunk-KQW6MTUR-Bh_TxL0e.js → chunk-KQW6MTUR-DR9SuVX3.js} +1 -1
- package/dist/assets/{chunk-XXDRQBXY-CLIJBS-V.js → chunk-XXDRQBXY-DwEl4815.js} +1 -1
- package/dist/assets/{classDiagram-v2-K4WV4PDN-B04FntQx.js → classDiagram-v2-K4WV4PDN-CQZho8e0.js} +1 -1
- package/dist/assets/{coins-81htcDNx.js → coins-DpzGN3sd.js} +1 -1
- package/dist/assets/{core-BLAzrox0.js → core-BNopzNRl.js} +1 -1
- package/dist/assets/{cose-bilkent-JH36ORCC-D9PAieWF.js → cose-bilkent-JH36ORCC-DUZ9OWzu.js} +1 -1
- package/dist/assets/{cynefin-EF2NZ3EQ-BAC2DRg5.js → cynefin-EF2NZ3EQ-DVHnJdjN.js} +1 -1
- package/dist/assets/{cynefinDiagram-3GCD6N5R-Cc3k_C-5.js → cynefinDiagram-3GCD6N5R-dYhbIkRt.js} +1 -1
- package/dist/assets/{dagre-W4DXFKR2-CpbzxBGo.js → dagre-W4DXFKR2-DqJNpw5w.js} +1 -1
- package/dist/assets/{diagram-2UJZ2QOL-d22NGVzG.js → diagram-2UJZ2QOL-DKNDqAnE.js} +1 -1
- package/dist/assets/{diagram-OVF4WLC6-BFTJTNpN.js → diagram-OVF4WLC6-DENMVM-d.js} +1 -1
- package/dist/assets/{diagram-PFPMY2P6-CA_YgAo3.js → diagram-PFPMY2P6-CrRFeR5V.js} +1 -1
- package/dist/assets/{diagram-UMYRVEAY-CCsuWndY.js → diagram-UMYRVEAY-B5w-desO.js} +1 -1
- package/dist/assets/{diagram-YEKJPTXX-Bcwhmpgl.js → diagram-YEKJPTXX-C7AVX3MB.js} +1 -1
- package/dist/assets/{diagram-ZIFT7M5P-Bs1iIjhq.js → diagram-ZIFT7M5P-BgkTRwwr.js} +1 -1
- package/dist/assets/{ebnfDiagram-VR2GEFS7-CFr96fLM.js → ebnfDiagram-VR2GEFS7-yY_2KNsK.js} +1 -1
- package/dist/assets/{elk-IJKZMXRS-DSdTG_hW.js → elk-IJKZMXRS-xWtfkoqT.js} +1 -1
- package/dist/assets/{erDiagram-O2IAPWRE-BGdMdwi1.js → erDiagram-O2IAPWRE-BMM4saPI.js} +1 -1
- package/dist/assets/{file-up-DvGMRF5I.js → file-up-Bl7ViNTL.js} +1 -1
- package/dist/assets/{flowDiagram-OXPTDLAJ-DL25A20O.js → flowDiagram-OXPTDLAJ-BCRe8i6T.js} +1 -1
- package/dist/assets/{ganttDiagram-R7TSEDQI-DQaNIRGv.js → ganttDiagram-R7TSEDQI-COBrcDi7.js} +1 -1
- package/dist/assets/{gitGraphDiagram-XJZIOB7I-B6ypA1ZF.js → gitGraphDiagram-XJZIOB7I-Dc4RKydD.js} +1 -1
- package/dist/assets/{import-name-Cdh9ZlkK.js → import-name-DA_MmEsd.js} +1 -1
- package/dist/assets/{index-BaW02tJl.js → index-BXLNny-w.js} +1 -1
- package/dist/assets/index-CwYJ9TX8.js +2 -0
- package/dist/assets/{index-CxcnLo81.js → index-D6huutPz.js} +1 -1
- package/dist/assets/{infoDiagram-5W2HQ5XZ-8YbtI4S4.js → infoDiagram-5W2HQ5XZ-BV8RRI_4.js} +1 -1
- package/dist/assets/{ishikawaDiagram-K3B6WC7H-DYpDWk2K.js → ishikawaDiagram-K3B6WC7H-H-XILdGm.js} +1 -1
- package/dist/assets/{journeyDiagram-COXZFDF6-BUd8Vnbq.js → journeyDiagram-COXZFDF6-ChLduKEj.js} +1 -1
- package/dist/assets/{kanban-definition-P3RFRI5V-AywqsEBB.js → kanban-definition-P3RFRI5V-FSZ9F3JH.js} +1 -1
- package/dist/assets/{mcp-servers-Bu5RuYBT.js → mcp-servers-CYvHVOYi.js} +1 -1
- package/dist/assets/{mermaid.core-B5yiNmEY.js → mermaid.core-BRsJ02Pz.js} +4 -4
- package/dist/assets/{mindmap-definition-LZFPQGKD-DRALSCg6.js → mindmap-definition-LZFPQGKD-TWHzZjNT.js} +1 -1
- package/dist/assets/{minimize-CWsi9mRL.js → minimize-BYscOtPM.js} +1 -1
- package/dist/assets/{monitor-c1mf38zt.js → monitor-DFEzCfQk.js} +1 -1
- package/dist/assets/{new-bot-mp2gi3ed.js → new-bot-_oEUbcDw.js} +2 -2
- package/dist/assets/{org-library-Bi3EieNo.js → org-library-CapoiPaN.js} +1 -1
- package/dist/assets/{package-format-CaPiTXn3.js → package-format-Cn4nABBW.js} +1 -1
- package/dist/assets/{pegDiagram-BGZESJAR-Drj_UJz5.js → pegDiagram-BGZESJAR-LQWOF7IE.js} +1 -1
- package/dist/assets/{pieDiagram-CAPJLFHJ-CL7MryRt.js → pieDiagram-CAPJLFHJ-BRXp4qFw.js} +1 -1
- package/dist/assets/{quadrantDiagram-GDMTTRAM-BvWxqPJn.js → quadrantDiagram-GDMTTRAM-DyIdGBZo.js} +1 -1
- package/dist/assets/{rail-DApFzTxo.js → rail-Du7tlPwj.js} +1 -1
- package/dist/assets/{railroadDiagram-SM67HX2B-CGfR0UsO.js → railroadDiagram-SM67HX2B-BrL1MhW1.js} +1 -1
- package/dist/assets/{remote-desktop-panel-B4uIIoh3.js → remote-desktop-panel-DbxYe3uv.js} +1 -1
- package/dist/assets/{requirementDiagram-X7JNWC4A-CJq96anP.js → requirementDiagram-X7JNWC4A-DTYjaC8j.js} +1 -1
- package/dist/assets/{sankeyDiagram-UM26HJRW-BdZSA65i.js → sankeyDiagram-UM26HJRW-BR9dASO5.js} +1 -1
- package/dist/assets/{sequenceDiagram-ZO4K6R2Y-B5W6udgn.js → sequenceDiagram-ZO4K6R2Y-BR1k8h2_.js} +1 -1
- package/dist/assets/{sizeCapture-INFHLROL-CuKCNVLn.js → sizeCapture-INFHLROL-u8zOvZVi.js} +1 -1
- package/dist/assets/{stateDiagram-v2-TBUQTH76-C7mAgpvB.js → stateDiagram-v2-TBUQTH76-mQ64BAFv.js} +1 -1
- package/dist/assets/styles-BlayaJti.js +23 -0
- package/dist/assets/{swimlanes-N4OXWK64-D-mimAU7.js → swimlanes-N4OXWK64-CmzC3Mu0.js} +1 -1
- package/dist/assets/swimlanesDiagram-K3J5GTZL-Coei7rJr.js +8 -0
- package/dist/assets/{team-share-wuAG66b7.js → team-share-C3w1L3WL.js} +1 -1
- package/dist/assets/{timeline-definition-YOQAKGHF-C5prnOXi.js → timeline-definition-YOQAKGHF-9aPCRsK2.js} +1 -1
- package/dist/assets/{usecaseDiagram-VIAY4XPW-BC-9KKSF.js → usecaseDiagram-VIAY4XPW--ngAouwr.js} +1 -1
- package/dist/assets/{vennDiagram-BLWOH2XV-LCNTQN9e.js → vennDiagram-BLWOH2XV-C3zKxuAB.js} +1 -1
- package/dist/assets/vi-uLErku_e.js +15 -0
- package/dist/assets/{wardleyDiagram-YMQ3BMBF-CtWGEzVU.js → wardleyDiagram-YMQ3BMBF-CZWsQPSF.js} +1 -1
- package/dist/assets/{xychartDiagram-TAQBALBS-DadPRdBp.js → xychartDiagram-TAQBALBS-BTcsDP6v.js} +1 -1
- package/dist/index.html +2 -2
- package/dist/rail.html +4 -4
- package/dist-server/index.js +426 -421
- package/dist-server/openmausbot.js +22 -22
- package/dist-server/package.json +1 -1
- package/dist-server/pair-cli.js +22 -22
- package/dist-server/server/index.js +1 -1
- package/dist-server/server/limix-skill-folder.js +72 -0
- package/dist-server/server/routes/bot-skills.js +2 -1
- package/package.json +1 -1
- package/dist/assets/BotSettingsDialog-PiCk9us7.js +0 -16
- package/dist/assets/CloudAddDialog-D1ZSbkxV.js +0 -1
- package/dist/assets/ComputerPanel-Cyj53a7W.js +0 -2
- package/dist/assets/LocalVmWorkspace-D9xFPGF0.js +0 -1
- package/dist/assets/MarkdownFilePreview-V-y-0ksi.js +0 -1
- package/dist/assets/PhoneAppDialog-DAW1N-hM.js +0 -1
- package/dist/assets/SettingsModal-Dd9l0b2C.js +0 -11
- package/dist/assets/TeamMapPage-CIQPYaxL.js +0 -1
- package/dist/assets/WorksOnGrid-PZ-caKHg.js +0 -1
- package/dist/assets/channel-BQyC_QMX.js +0 -1
- package/dist/assets/index-oVds-_Vz.js +0 -2
- package/dist/assets/module-DCUsy2BQ.js +0 -3
- package/dist/assets/styles-C_rlkDrt.js +0 -23
- package/dist/assets/swimlanesDiagram-K3J5GTZL-Dn31PG7h.js +0 -8
- package/dist/assets/vi-NX09tr5q.js +0 -15
|
@@ -8620,8 +8620,8 @@ child=null,removeTokenFile(tokenFile);let terminated=existing?terminateChild(exi
|
|
|
8620
8620
|
ected. Try again to recover it.",endpoint_busy:"The secure connection is still being prepared. Try again in a moment.",endpoint_rate_limited:"The secure connection service is busy right now. Local Wi-Fi and Tailscale pairing still work; try again in {wait}.",update_required:"This version of Limix Bot can no longer make secure links. Update Limix Bot, then try again. Local Wi-Fi and Tailscale pairing still work.",endpoint_capacity:"Secure HTTPS links are temporarily full. Try again in {wait}, or \
|
|
8621
8621
|
pair on this Wi-Fi or with Tailscale.",endpoint_unavailable:"The secure connection service could not finish setup. Local Wi-Fi and Tailscale pairing still work. If this keeps happening, contact support with the error reference.",endpoint_cleanup_pending:"The secure connection is still being removed. Try signing out again shortly.",control_plane_unavailable:"Secure access is not available right now. Local pairing still works.",internal_error:"The secure connection service had a problem. Local pai\
|
|
8622
8622
|
ring still works; try again.",invalid_response:"The secure connection service returned an unexpected response. Try again.",request_failed:"The secure connection request could not be completed. Local pairing still works; try again."});function retryWait(retryAfterMs){let seconds=Math.ceil((retryAfterMs??0)/1e3);return seconds>0?seconds<90?`${seconds} seconds`:`${Math.round(seconds/60)} minutes`:"a few minutes"}function friendlyCompanionAccountError(error62){let code=error62 instanceof ControlPlaneError?
|
|
8623
|
-
error62.code:"",message5=(FRIENDLY_MESSAGES[code]??FRIENDLY_MESSAGES.request_failed).replace("{wait}",()=>retryWait(error62.retryAfterMs)),reference=error62 instanceof ControlPlaneError&&error62.requestId?` Reference: ${error62.requestId}.`:"";return`${message5}${reference}`}var DEFAULT_COMPANION_CONTROL_PLANE_URL="https://accounts.
|
|
8624
|
-
|
|
8623
|
+
error62.code:"",message5=(FRIENDLY_MESSAGES[code]??FRIENDLY_MESSAGES.request_failed).replace("{wait}",()=>retryWait(error62.retryAfterMs)),reference=error62 instanceof ControlPlaneError&&error62.requestId?` Reference: ${error62.requestId}.`:"";return`${message5}${reference}`}var DEFAULT_COMPANION_CONTROL_PLANE_URL="https://accounts.limixmedia.com",COMPANION_CLIENT_INSTANCE_FIELD="companionClientInstanceId",COMPANION_ACCOUNT_TOKEN_FIELD="companionAccountToken",COMPANION_ACCOUNT_USER_ID_FIELD="companionAccountUserId",COMPANION_ACCOUNT_EMAIL_FIELD="companionAccountEmail",COMPANION_INSTALLATION_ID_FIELD="companionInstallationId",COMPANION_INSTALLATION_CREDENTIAL_FIELD="companionInstallationCredential",COMPANION_INSTALLATION_EXPIRY_FIELD="companionInstallationCredentialE\
|
|
8624
|
+
xpiresAt",COMPANION_ACCOUNT_CLEANUP_PENDING_FIELD="companionAccountCleanupPending",COMPANION_ENDPOINT_RELEASE_PENDING_FIELD="companionEndpointReleasePending",COMPANION_ENDPOINT_PAUSED_FIELD="companionEndpointPaused",COMPANION_TUNNEL_RETIRED_FIELD="companionTunnelRetired",COMPANION_TUNNEL_WAITING_FIELD="companionTunnelWaiting",UUID=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,INSTALLATION_ID2=UUID,INSTALLATION_CREDENTIAL2=/^omb_install_[A-Za-z0-9_-]{22}\.[A-Za-z0-9_-]{43}$/,
|
|
8625
8625
|
DEFAULT_HEALTH_CACHE_MS=3e4,DEFAULT_AUTO_RETRY_BASE_MS=10*6e4,DEFAULT_AUTO_RETRY_MAX_MS=360*6e4,DEFAULT_ENDPOINT_CHECK_INTERVAL_MS=15*6e4,DEFAULT_FIRST_ENDPOINT_CHECK_MS=2*6e4,DEFAULT_RELEASE_GRACE_MS=60*6e4,DEFAULT_RELEASE_JITTER_MS=180*6e4,REQUEST_WINDOW_MS=60*6e4,AUTO_RETRY_CODES=new Set(["endpoint_capacity","endpoint_rate_limited","endpoint_unavailable","endpoint_busy","network_unavailable","control_plane_unavailable","internal_error","rate_limited","credential_rotation_rate_limited"]),ENDPOINT_NEEDS_RECONCILE=new Set(
|
|
8626
8626
|
["deleting","deleted","error"]),WATCHDOG_CHECK_STATES=new Set(["starting","ready","retrying","error"]),CONNECTOR_FAILING_STATES=new Set(["retrying","error"]),defaultSetTimer=(callback,milliseconds)=>{let timer2=setTimeout(callback,milliseconds);return timer2.unref?.(),timer2},ownString=(document3,field)=>typeof document3?.[field]=="string"?document3[field]:"";function resolveCompanionControlPlaneURL({isPackaged,environment=process.env}={}){return Object.hasOwn(environment,"OMB_CONTROL_PLANE_URL")?
|
|
8627
8627
|
normalizeControlPlaneURL(environment.OMB_CONTROL_PLANE_URL):isPackaged?DEFAULT_COMPANION_CONTROL_PLANE_URL:""}function companionAccountCleanupPending(credentials){return credentials?.[COMPANION_ACCOUNT_CLEANUP_PENDING_FIELD]===!0}var companionTunnelRetired=credentials=>!!storedAccount(credentials)&&!managedCompanionTunnelAccess(credentials)&&credentials?.[COMPANION_TUNNEL_RETIRED_FIELD]===!0;function storedAccount(credentials){let email3=normalizeAccountEmail(ownString(credentials,COMPANION_ACCOUNT_EMAIL_FIELD)),
|
|
@@ -8651,26 +8651,26 @@ credential)&&await client.revokeInstallation(accountToken,installation.installat
|
|
|
8651
8651
|
...document3};return relayOnly==="retired"?next[COMPANION_TUNNEL_RETIRED_FIELD]=!0:delete next[COMPANION_TUNNEL_RETIRED_FIELD],relayOnly==="retired"||relayOnly==="full"?next[COMPANION_TUNNEL_WAITING_FIELD]=!0:delete next[COMPANION_TUNNEL_WAITING_FIELD],next}),withoutTunnel();try{await updateCredentials(document3=>withProvisionedAccount(document3,{accountToken,user,installation,provision:endpoint}))}catch(error62){throw await client.deleteEndpoint(installation.credential).catch(()=>{}),await client.
|
|
8652
8652
|
revokeInstallation(accountToken,installation.installation.id).catch(()=>{}),error62}resetAutoRetry();let connection=await activatePersistedEndpoint();return phase=null,companionIsOn()&&connection&&["unavailable","error"].includes(connection.status)&&(phase={status:"error",email:user.email,endpoint:endpoint.endpoint.url,message:"The address is ready, but this app could not start its secure connection. Local pairing still works."}),settledState()},writeLog=line3=>{try{log2(line3)}catch{}},failAction=(error62,{
|
|
8653
8653
|
email:email3,expiredSessionIsSignedOut=!1,signedOut=!1}={})=>{let message5=friendlyCompanionAccountError(error62);return writeLog(error62 instanceof ControlPlaneError?`companion account: setup failed code=${error62.code} status=${error62.status||"none"} ref=${error62.requestId||"none"}`:"companion account: setup failed on this computer (not a control-plane answer)"),phase={status:signedOut||expiredSessionIsSignedOut&&error62 instanceof ControlPlaneError&&error62.status===401?"signed-out":"error",
|
|
8654
|
-
email:email3,message:message5},message5},requestCode=rawEmail=>serialize(async()=>{if(!configured)throw new Error(FRIENDLY_MESSAGES.control_plane_unavailable);let email3=normalizeAccountEmail(rawEmail),requested;try{await requireHealthyControlPlane(),requested=await client.requestOTP(email3)}catch(error62){let message5=failAction(error62,{email:email3,signedOut:!0});throw new Error(message5)}return phase={status:"signed-out",email:requested.email},settledState()}),
|
|
8655
|
-
async()=>{if(!configured)throw new Error(FRIENDLY_MESSAGES.control_plane_unavailable);requestedAt=now();let email3=normalizeAccountEmail(rawEmail);phase={status:"connecting",email:email3};let verified;try{await requireHealthyControlPlane(),verified=await
|
|
8656
|
-
|
|
8657
|
-
|
|
8658
|
-
|
|
8659
|
-
email};try{return await requireHealthyControlPlane(),await provision({accountToken:account2.accountToken,user:{id:account2.userId,email:account2.email}})}catch(error62){return failAction(error62,{email:account2.email,expiredSessionIsSignedOut:!0}),scheduleAutoRetry(error62),settledState()}},retry=()=>serialize(async()=>(requestedAt=
|
|
8660
|
-
document3);if(!account2||!access2||!account2.installationCredential||companionAccountCleanupPending(document3)||typeof client.getEndpoint!="function")return null;lastEndpointCheck=now();let endpoint;try{endpoint=await client.getEndpoint(account2.installationCredential)}catch(error62){return error62 instanceof ControlPlaneError&&
|
|
8661
|
-
null||now()-lastEndpointCheck>=endpointCheckIntervalMs/2,recoveryDue=({atLaunch=!1}={})=>{if(!autoRecover||!companionIsOn())return!1;if(atLaunch)return!0;if(autoRetryTimer!==null)return!1;let connection=managedConnectionState?.()??{};return WATCHDOG_CHECK_STATES.has(connection.status)&&endpointCheckDue()},requestedRecently=()=>requestedAt!==
|
|
8662
|
-
currentNeed=async()=>{let answer=await Promise.resolve().then(()=>managedEndpointNeeded()).catch(()=>null);phonesUnused=answer===MANAGED_ENDPOINT_PHONES_UNUSED;let need=phonesUnused?!1:typeof answer=="boolean"?answer:null;return need===!1&&relay.capable()?!1:requestedRecently()?(phonesUnused=!1,!0):need},releaseScheduledAt=()=>{let at2=credentials()[MANAGED_COMPANION_RELEASE_AT_FIELD];
|
|
8663
|
-
document3=>{let next={...document3};return delete next[MANAGED_COMPANION_RELEASE_AT_FIELD],next})},releaseAddress=async()=>{let need=await currentNeed(),pause2=phonesUnused;if(need!==!1)return need&&await cancelRelease(),settledState();let document3=credentials(),account2=storedAccount(document3);if(!account2?.installationCredential||!managedCompanionTunnelAccess(document3)||
|
|
8664
|
-
deleteEndpoint(account2.installationCredential)}catch(error62){if(removalPending=error62 instanceof ControlPlaneError&&error62.code==="endpoint_cleanup_pending",!(removalPending||error62 instanceof ControlPlaneError&&error62.status===401))return writeLog(error62 instanceof ControlPlaneError?`companion account: could not give the secure address back code=${error62.code}
|
|
8665
|
-
|
|
8666
|
-
reviewAddress=async({atLaunch=!1}={})=>{let document3=credentials();if(!storedAccount(document3)||companionAccountCleanupPending(document3))return null;if(!managedCompanionTunnelAccess(document3)){let waiting2=document3[COMPANION_TUNNEL_WAITING_FIELD]===!0;return!savedAddress(document3)&&!waiting2||autoRetryTimer!==null?null:await currentNeed()===!0?retryWork():
|
|
8667
|
-
null;let releaseAt=releaseScheduledAt();if(releaseAt!==null&&now()>=releaseAt)return releaseAddress();let connection=managedConnectionState?.()??{};if(companionIsOn()&&CONNECTOR_FAILING_STATES.has(connection.status)&&(atLaunch||endpointCheckDue())){let released=await reconcileIfEndpointGone({onGone:releaseAddress});if(released)return released}
|
|
8668
|
-
current=>managedCompanionTunnelAccess(current)?{...current,[MANAGED_COMPANION_RELEASE_AT_FIELD]:now()+delay3}:current),writeLog(`companion account: no device needs the secure address; giving it back in ${Math.round(delay3/6e4)} min`)}return null},retryIfWanted=async()=>requestedRecently()||savedAddress(credentials())&&await currentNeed()!==!1?
|
|
8669
|
-
retryFromTimer=()=>serialize(onDemand?retryIfWanted:retryWork);let prepare=()=>serialize(async()=>{let document3=credentials();if(!configured||!companionIsOn()||!storedAccount(document3)||companionAccountCleanupPending(document3))return settledState();if(requestedAt=now(),!managedCompanionTunnelAccess(document3))return retryWork();await cancelRelease();
|
|
8670
|
-
has(connection.status)){let repaired=await reconcileIfEndpointGone();if(repaired)return repaired}return settledState()}),watchdogTick=()=>{if(watchdogTimer=null,!disposed&&(watchdogTimer=setTimer(watchdogTick,endpointCheckIntervalMs),phase?.status!=="signed-out")){if(onDemand){serialize(()=>reviewAddress()).catch(()=>{});return}
|
|
8671
|
-
setTimer(watchdogTick,firstEndpointCheckMs))};return Object.freeze({state:async()=>(await probeControlPlane(),settledState()),requestCode,verifyCode,retry,prepare,signOut:()=>serialize(async()=>{if(resetAutoRetry(),!storedAccount(credentials()))return await clearAfterCleanup(),settledState();let email3=storedAccount(
|
|
8672
|
-
error62,{email:email3}),settledState()}}),restore:()=>serialize(async()=>{if(!configured||(startWatchdog(),!await probeControlPlane({force:!0})))return settledState();if(companionAccountCleanupPending(credentials()))return retryWork();if(await ensureClientIdentity(),onDemand){let reviewed=await reviewAddress({atLaunch:!0});
|
|
8673
|
-
account2&&companionIsOn()){let reconciled=await reconcileIfEndpointGone();if(reconciled)return reconciled}return phase=null,settledState()}),dispose:()=>{disposed=!0,cancelAutoRetry(),watchdogTimer!==null&&clearTimer(watchdogTimer),watchdogTimer=null}})}var SIGNIN_CODE_TTL_MS=10*6e4;init_user_errors();function parseAllowList(value){return(value??"").split(/[,\s]+/).map(entry=>entry.trim().toLowerCase()).filter(Boolean)}var NOT_WELCOME={ok:!1,status:403,...userError("serverError.email.notAllowed")};init_decision_log();init_redact2();init_usage_ledger();import{appendFile as appendFile2,mkdir as mkdir2}from"node:fs/promises";import{basename as basename2,join as join2}from"node:path";var DIR2="admin-activity";var PRUNE_EVERY_MS2=60*6e4,writeQueues2=new Map,lastPrune2=new Map;function adminActivityFileFor(dataDir,at2){return join2(dataDir,DIR2,`${monthKey(at2)}.ndjson`)}async function writeRow(dataDir,row){let at2=new Date(row.at);await mkdir2(join2(dataDir,DIR2),{recursive:!0,mode:448}),await appendFile2(adminActivityFileFor(dataDir,at2),JSON.stringify(row)+`
|
|
8654
|
+
email:email3,message:message5},message5},requestCode=rawEmail=>serialize(async()=>{if(!configured)throw new Error(FRIENDLY_MESSAGES.control_plane_unavailable);let email3=normalizeAccountEmail(rawEmail),requested;try{await requireHealthyControlPlane(),requested=await client.requestOTP(email3)}catch(error62){let message5=failAction(error62,{email:email3,signedOut:!0});throw new Error(message5)}return phase={status:"signed-out",email:requested.email},settledState()}),signInFlow=(rawEmail,obtain)=>serialize(
|
|
8655
|
+
async()=>{if(!configured)throw new Error(FRIENDLY_MESSAGES.control_plane_unavailable);requestedAt=now();let email3=normalizeAccountEmail(rawEmail);phase={status:"connecting",email:email3};let verified;try{await requireHealthyControlPlane(),verified=await obtain(email3)}catch(error62){let message5=failAction(error62,{email:email3,signedOut:!0});throw new Error(message5)}let previous2=storedAccount(credentials()),refreshingPendingCleanup=!!(previous2&&previous2.userId===verified.user.id&&companionAccountCleanupPending(
|
|
8656
|
+
credentials())),authenticatedPersisted=!1;try{previous2&&previous2.userId!==verified.user.id&&await cleanupCurrentAccount();let existingIdentity=ownString(credentials(),COMPANION_CLIENT_INSTANCE_FIELD),clientInstanceId=UUID.test(existingIdentity)?existingIdentity:newClientInstanceId?.();if(!UUID.test(clientInstanceId??""))throw new Error("A stable computer identity could not be created");return await updateCredentials(document3=>withAuthenticatedAccount(document3,{...verified,clientInstanceId,preserveCleanupPending:refreshingPendingCleanup})),
|
|
8657
|
+
authenticatedPersisted=!0,refreshingPendingCleanup?(await cleanupCurrentAccount({markPending:!1}),settledState()):await provision(verified)}catch(error62){return authenticatedPersisted||await client.signOut(verified.accountToken).catch(()=>{}),failAction(error62,{email:authenticatedPersisted?verified.user.email:previous2?.email??email3,expiredSessionIsSignedOut:authenticatedPersisted}),authenticatedPersisted&&scheduleAutoRetry(error62),settledState()}}),verifyCode=(rawEmail,rawCode)=>signInFlow(
|
|
8658
|
+
rawEmail,email3=>client.verifyOTP(email3,rawCode)),connectLimix=credential=>signInFlow(credential.email,async()=>({accountToken:credential.bearer,user:{id:credential.userId,email:credential.email}})),retryWork=async()=>{if(!configured)return settledState();let account2=storedAccount(credentials());if(!account2)return phase=null,settledState();if(companionAccountCleanupPending(credentials())){phase={status:"connecting",email:account2.email};try{await requireHealthyControlPlane(),await cleanupCurrentAccount(
|
|
8659
|
+
{markPending:!1})}catch(error62){failAction(error62,{email:account2.email,expiredSessionIsSignedOut:!0})}return settledState()}phase={status:"connecting",email:account2.email};try{return await requireHealthyControlPlane(),await provision({accountToken:account2.accountToken,user:{id:account2.userId,email:account2.email}})}catch(error62){return failAction(error62,{email:account2.email,expiredSessionIsSignedOut:!0}),scheduleAutoRetry(error62),settledState()}},retry=()=>serialize(async()=>(requestedAt=
|
|
8660
|
+
now(),retryWork())),reconcileIfEndpointGone=async({onGone=retryWork}={})=>{let document3=credentials(),account2=storedAccount(document3),access2=managedCompanionTunnelAccess(document3);if(!account2||!access2||!account2.installationCredential||companionAccountCleanupPending(document3)||typeof client.getEndpoint!="function")return null;lastEndpointCheck=now();let endpoint;try{endpoint=await client.getEndpoint(account2.installationCredential)}catch(error62){return error62 instanceof ControlPlaneError&&
|
|
8661
|
+
error62.status===401?onGone():null}return endpoint&&endpoint.url===access2.endpoint&&!ENDPOINT_NEEDS_RECONCILE.has(endpoint.status)?null:onGone()},endpointCheckDue=()=>lastEndpointCheck===null||now()-lastEndpointCheck>=endpointCheckIntervalMs/2,recoveryDue=({atLaunch=!1}={})=>{if(!autoRecover||!companionIsOn())return!1;if(atLaunch)return!0;if(autoRetryTimer!==null)return!1;let connection=managedConnectionState?.()??{};return WATCHDOG_CHECK_STATES.has(connection.status)&&endpointCheckDue()},requestedRecently=()=>requestedAt!==
|
|
8662
|
+
null&&now()-requestedAt<REQUEST_WINDOW_MS,savedAddress=document3=>normalizeManagedCompanionEndpoint(document3[MANAGED_COMPANION_ENDPOINT_FIELD]),phonesUnused=!1,currentNeed=async()=>{let answer=await Promise.resolve().then(()=>managedEndpointNeeded()).catch(()=>null);phonesUnused=answer===MANAGED_ENDPOINT_PHONES_UNUSED;let need=phonesUnused?!1:typeof answer=="boolean"?answer:null;return need===!1&&relay.capable()?!1:requestedRecently()?(phonesUnused=!1,!0):need},releaseScheduledAt=()=>{let at2=credentials()[MANAGED_COMPANION_RELEASE_AT_FIELD];
|
|
8663
|
+
return Number.isSafeInteger(at2)&&at2>0?at2:null},cancelRelease=async()=>{releaseScheduledAt()!==null&&await updateCredentials(document3=>{let next={...document3};return delete next[MANAGED_COMPANION_RELEASE_AT_FIELD],next})},releaseAddress=async()=>{let need=await currentNeed(),pause2=phonesUnused;if(need!==!1)return need&&await cancelRelease(),settledState();let document3=credentials(),account2=storedAccount(document3);if(!account2?.installationCredential||!managedCompanionTunnelAccess(document3)||
|
|
8664
|
+
companionAccountCleanupPending(document3))return settledState();await stopManagedEndpoint();let removalPending=!1;try{await client.deleteEndpoint(account2.installationCredential)}catch(error62){if(removalPending=error62 instanceof ControlPlaneError&&error62.code==="endpoint_cleanup_pending",!(removalPending||error62 instanceof ControlPlaneError&&error62.status===401))return writeLog(error62 instanceof ControlPlaneError?`companion account: could not give the secure address back code=${error62.code}\
|
|
8665
|
+
status=${error62.status||"none"} ref=${error62.requestId||"none"}`:"companion account: could not give the secure address back (not a control-plane answer)"),await activatePersistedEndpoint(),settledState()}return await updateCredentials(current=>({...withoutManagedCompanionTunnelAccess(current),...removalPending?{[COMPANION_ENDPOINT_RELEASE_PENDING_FIELD]:!0}:{},...pause2?{[COMPANION_ENDPOINT_PAUSED_FIELD]:!0}:{}})),resetAutoRetry(),phase=null,writeLog(pause2?"companion account: gave the secure\
|
|
8666
|
+
address back; no paired phone was used in 30 days":"companion account: gave the secure address back; no device needs it"),settledState()},reviewAddress=async({atLaunch=!1}={})=>{let document3=credentials();if(!storedAccount(document3)||companionAccountCleanupPending(document3))return null;if(!managedCompanionTunnelAccess(document3)){let waiting2=document3[COMPANION_TUNNEL_WAITING_FIELD]===!0;return!savedAddress(document3)&&!waiting2||autoRetryTimer!==null?null:await currentNeed()===!0?retryWork():
|
|
8667
|
+
null}let need=await currentNeed();if(need!==!1)return need&&await cancelRelease(),need===null&&atLaunch?null:recoveryDue({atLaunch})?reconcileIfEndpointGone():null;let releaseAt=releaseScheduledAt();if(releaseAt!==null&&now()>=releaseAt)return releaseAddress();let connection=managedConnectionState?.()??{};if(companionIsOn()&&CONNECTOR_FAILING_STATES.has(connection.status)&&(atLaunch||endpointCheckDue())){let released=await reconcileIfEndpointGone({onGone:releaseAddress});if(released)return released}
|
|
8668
|
+
if(releaseAt===null||releaseAt-now()>releaseGraceMs+releaseJitterMs){let delay3=releaseGraceMs+Math.round(random()*releaseJitterMs);await updateCredentials(current=>managedCompanionTunnelAccess(current)?{...current,[MANAGED_COMPANION_RELEASE_AT_FIELD]:now()+delay3}:current),writeLog(`companion account: no device needs the secure address; giving it back in ${Math.round(delay3/6e4)} min`)}return null},retryIfWanted=async()=>requestedRecently()||savedAddress(credentials())&&await currentNeed()!==!1?
|
|
8669
|
+
retryWork():(resetAutoRetry(),phase?.status==="error"&&(phase=null),writeLog("companion account: stopped retrying; no device needs a secure address"),settledState());retryFromTimer=()=>serialize(onDemand?retryIfWanted:retryWork);let prepare=()=>serialize(async()=>{let document3=credentials();if(!configured||!companionIsOn()||!storedAccount(document3)||companionAccountCleanupPending(document3))return settledState();if(requestedAt=now(),!managedCompanionTunnelAccess(document3))return retryWork();await cancelRelease();
|
|
8670
|
+
let connection=managedConnectionState?.()??{};if(["stopped","unconfigured"].includes(connection.status))await activatePersistedEndpoint();else if(CONNECTOR_FAILING_STATES.has(connection.status)){let repaired=await reconcileIfEndpointGone();if(repaired)return repaired}return settledState()}),watchdogTick=()=>{if(watchdogTimer=null,!disposed&&(watchdogTimer=setTimer(watchdogTick,endpointCheckIntervalMs),phase?.status!=="signed-out")){if(onDemand){serialize(()=>reviewAddress()).catch(()=>{});return}
|
|
8671
|
+
recoveryDue()&&serialize(()=>reconcileIfEndpointGone()).catch(()=>{})}},startWatchdog=()=>{!(autoRecover||onDemand)||disposed||!configured||watchdogTimer!==null||(watchdogTimer=setTimer(watchdogTick,firstEndpointCheckMs))};return Object.freeze({state:async()=>(await probeControlPlane(),settledState()),requestCode,verifyCode,connectLimix,retry,prepare,signOut:()=>serialize(async()=>{if(resetAutoRetry(),!storedAccount(credentials()))return await clearAfterCleanup(),settledState();let email3=storedAccount(
|
|
8672
|
+
credentials())?.email;phase={status:"connecting",email:email3};try{return await cleanupCurrentAccount(),healthy=!0,lastHealthCheck=now(),settledState()}catch(error62){return failAction(error62,{email:email3}),settledState()}}),restore:()=>serialize(async()=>{if(!configured||(startWatchdog(),!await probeControlPlane({force:!0})))return settledState();if(companionAccountCleanupPending(credentials()))return retryWork();if(await ensureClientIdentity(),onDemand){let reviewed=await reviewAddress({atLaunch:!0});
|
|
8673
|
+
return reviewed||(phase=null,settledState())}let account2=storedAccount(credentials());if(account2&&!managedCompanionTunnelAccess(credentials()))return retryWork();if(autoRecover&&account2&&companionIsOn()){let reconciled=await reconcileIfEndpointGone();if(reconciled)return reconciled}return phase=null,settledState()}),dispose:()=>{disposed=!0,cancelAutoRetry(),watchdogTimer!==null&&clearTimer(watchdogTimer),watchdogTimer=null}})}var SIGNIN_CODE_TTL_MS=10*6e4;init_user_errors();function parseAllowList(value){return(value??"").split(/[,\s]+/).map(entry=>entry.trim().toLowerCase()).filter(Boolean)}var NOT_WELCOME={ok:!1,status:403,...userError("serverError.email.notAllowed")};init_decision_log();init_redact2();init_usage_ledger();import{appendFile as appendFile2,mkdir as mkdir2}from"node:fs/promises";import{basename as basename2,join as join2}from"node:path";var DIR2="admin-activity";var PRUNE_EVERY_MS2=60*6e4,writeQueues2=new Map,lastPrune2=new Map;function adminActivityFileFor(dataDir,at2){return join2(dataDir,DIR2,`${monthKey(at2)}.ndjson`)}async function writeRow(dataDir,row){let at2=new Date(row.at);await mkdir2(join2(dataDir,DIR2),{recursive:!0,mode:448}),await appendFile2(adminActivityFileFor(dataDir,at2),JSON.stringify(row)+`
|
|
8674
8674
|
`,{mode:384}),at2.getTime()-(lastPrune2.get(dataDir)??0)>=PRUNE_EVERY_MS2&&(lastPrune2.set(dataDir,at2.getTime()),await pruneMonthFiles(join2(dataDir,DIR2),boundRetentionDays(),at2))}function appendAdminAction(dataDir,row){let record12={...row,at:row.at??new Date().toISOString(),...row.before?{before:auditValues(row.before)}:{},...row.after?{after:auditValues(row.after)}:{}},queued=(writeQueues2.get(dataDir)??Promise.resolve()).then(()=>writeRow(dataDir,record12)).catch(()=>{});writeQueues2.set(
|
|
8675
8675
|
dataDir,queued),queued.finally(()=>{writeQueues2.get(dataDir)===queued&&writeQueues2.delete(dataDir)})}async function flushAdminActivity(dataDir){await writeQueues2.get(dataDir)}var SECRET_PARTS=["token","secret","password","passwd","passphrase","credential","authorization","cookie","bearer","apikey","api_key"],OPAQUE_MAP=/^(?:headers|env|environment)$/i,MAX_VALUE_CHARS=2e3,HIDDEN="[hidden]";function isSecretName2(name){let lower=name.toLowerCase();return lower.endsWith("tokens")?!1:SECRET_PARTS.some(part=>lower.includes(part))?!0:/(?:^|[_.-])keys?$/.test(lower)||/[a-z]Keys?$/.test(name)}function isSecretParameter(name){
|
|
8676
8676
|
if(name==="-k"||name==="-K")return!0;let bare=name.replace(/^-+/,"");return isSecretName2(bare)||/^(?:auth|sig|signature|pass|pwd|code)$/i.test(bare)}function keyLikeSegment(segment){return(segment.match(/[A-Za-z0-9]{16,}/g)??[]).some(run6=>/\d/.test(run6)&&/[A-Za-z]/.test(run6))}function maskUrlSecrets(text13){return text13.replace(/\b([a-z][\w+.-]*:\/\/)([^\s/?#]*)([^\s?#]*)([^\s]*)/gi,(_all,scheme,authority2,path3,rest)=>{let at2=authority2.lastIndexOf("@"),host2=at2>=0?`${HIDDEN}@${authority2.
|
package/dist-server/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"type":"module","version":"0.3.
|
|
1
|
+
{"type":"module","version":"0.3.3"}
|
package/dist-server/pair-cli.js
CHANGED
|
@@ -8619,8 +8619,8 @@ child=null,removeTokenFile(tokenFile);let terminated=existing?terminateChild(exi
|
|
|
8619
8619
|
ected. Try again to recover it.",endpoint_busy:"The secure connection is still being prepared. Try again in a moment.",endpoint_rate_limited:"The secure connection service is busy right now. Local Wi-Fi and Tailscale pairing still work; try again in {wait}.",update_required:"This version of Limix Bot can no longer make secure links. Update Limix Bot, then try again. Local Wi-Fi and Tailscale pairing still work.",endpoint_capacity:"Secure HTTPS links are temporarily full. Try again in {wait}, or \
|
|
8620
8620
|
pair on this Wi-Fi or with Tailscale.",endpoint_unavailable:"The secure connection service could not finish setup. Local Wi-Fi and Tailscale pairing still work. If this keeps happening, contact support with the error reference.",endpoint_cleanup_pending:"The secure connection is still being removed. Try signing out again shortly.",control_plane_unavailable:"Secure access is not available right now. Local pairing still works.",internal_error:"The secure connection service had a problem. Local pai\
|
|
8621
8621
|
ring still works; try again.",invalid_response:"The secure connection service returned an unexpected response. Try again.",request_failed:"The secure connection request could not be completed. Local pairing still works; try again."});function retryWait(retryAfterMs){let seconds=Math.ceil((retryAfterMs??0)/1e3);return seconds>0?seconds<90?`${seconds} seconds`:`${Math.round(seconds/60)} minutes`:"a few minutes"}function friendlyCompanionAccountError(error62){let code=error62 instanceof ControlPlaneError?
|
|
8622
|
-
error62.code:"",message5=(FRIENDLY_MESSAGES[code]??FRIENDLY_MESSAGES.request_failed).replace("{wait}",()=>retryWait(error62.retryAfterMs)),reference=error62 instanceof ControlPlaneError&&error62.requestId?` Reference: ${error62.requestId}.`:"";return`${message5}${reference}`}var DEFAULT_COMPANION_CONTROL_PLANE_URL="https://accounts.
|
|
8623
|
-
|
|
8622
|
+
error62.code:"",message5=(FRIENDLY_MESSAGES[code]??FRIENDLY_MESSAGES.request_failed).replace("{wait}",()=>retryWait(error62.retryAfterMs)),reference=error62 instanceof ControlPlaneError&&error62.requestId?` Reference: ${error62.requestId}.`:"";return`${message5}${reference}`}var DEFAULT_COMPANION_CONTROL_PLANE_URL="https://accounts.limixmedia.com",COMPANION_CLIENT_INSTANCE_FIELD="companionClientInstanceId",COMPANION_ACCOUNT_TOKEN_FIELD="companionAccountToken",COMPANION_ACCOUNT_USER_ID_FIELD="companionAccountUserId",COMPANION_ACCOUNT_EMAIL_FIELD="companionAccountEmail",COMPANION_INSTALLATION_ID_FIELD="companionInstallationId",COMPANION_INSTALLATION_CREDENTIAL_FIELD="companionInstallationCredential",COMPANION_INSTALLATION_EXPIRY_FIELD="companionInstallationCredentialE\
|
|
8623
|
+
xpiresAt",COMPANION_ACCOUNT_CLEANUP_PENDING_FIELD="companionAccountCleanupPending",COMPANION_ENDPOINT_RELEASE_PENDING_FIELD="companionEndpointReleasePending",COMPANION_ENDPOINT_PAUSED_FIELD="companionEndpointPaused",COMPANION_TUNNEL_RETIRED_FIELD="companionTunnelRetired",COMPANION_TUNNEL_WAITING_FIELD="companionTunnelWaiting",UUID=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,INSTALLATION_ID2=UUID,INSTALLATION_CREDENTIAL2=/^omb_install_[A-Za-z0-9_-]{22}\.[A-Za-z0-9_-]{43}$/,
|
|
8624
8624
|
DEFAULT_HEALTH_CACHE_MS=3e4,DEFAULT_AUTO_RETRY_BASE_MS=10*6e4,DEFAULT_AUTO_RETRY_MAX_MS=360*6e4,DEFAULT_ENDPOINT_CHECK_INTERVAL_MS=15*6e4,DEFAULT_FIRST_ENDPOINT_CHECK_MS=2*6e4,DEFAULT_RELEASE_GRACE_MS=60*6e4,DEFAULT_RELEASE_JITTER_MS=180*6e4,REQUEST_WINDOW_MS=60*6e4,AUTO_RETRY_CODES=new Set(["endpoint_capacity","endpoint_rate_limited","endpoint_unavailable","endpoint_busy","network_unavailable","control_plane_unavailable","internal_error","rate_limited","credential_rotation_rate_limited"]),ENDPOINT_NEEDS_RECONCILE=new Set(
|
|
8625
8625
|
["deleting","deleted","error"]),WATCHDOG_CHECK_STATES=new Set(["starting","ready","retrying","error"]),CONNECTOR_FAILING_STATES=new Set(["retrying","error"]),defaultSetTimer=(callback,milliseconds)=>{let timer2=setTimeout(callback,milliseconds);return timer2.unref?.(),timer2},ownString=(document3,field)=>typeof document3?.[field]=="string"?document3[field]:"";function resolveCompanionControlPlaneURL({isPackaged,environment=process.env}={}){return Object.hasOwn(environment,"OMB_CONTROL_PLANE_URL")?
|
|
8626
8626
|
normalizeControlPlaneURL(environment.OMB_CONTROL_PLANE_URL):isPackaged?DEFAULT_COMPANION_CONTROL_PLANE_URL:""}function companionAccountCleanupPending(credentials){return credentials?.[COMPANION_ACCOUNT_CLEANUP_PENDING_FIELD]===!0}var companionTunnelRetired=credentials=>!!storedAccount(credentials)&&!managedCompanionTunnelAccess(credentials)&&credentials?.[COMPANION_TUNNEL_RETIRED_FIELD]===!0;function storedAccount(credentials){let email3=normalizeAccountEmail(ownString(credentials,COMPANION_ACCOUNT_EMAIL_FIELD)),
|
|
@@ -8650,26 +8650,26 @@ credential)&&await client.revokeInstallation(accountToken,installation.installat
|
|
|
8650
8650
|
...document3};return relayOnly==="retired"?next[COMPANION_TUNNEL_RETIRED_FIELD]=!0:delete next[COMPANION_TUNNEL_RETIRED_FIELD],relayOnly==="retired"||relayOnly==="full"?next[COMPANION_TUNNEL_WAITING_FIELD]=!0:delete next[COMPANION_TUNNEL_WAITING_FIELD],next}),withoutTunnel();try{await updateCredentials(document3=>withProvisionedAccount(document3,{accountToken,user,installation,provision:endpoint}))}catch(error62){throw await client.deleteEndpoint(installation.credential).catch(()=>{}),await client.
|
|
8651
8651
|
revokeInstallation(accountToken,installation.installation.id).catch(()=>{}),error62}resetAutoRetry();let connection=await activatePersistedEndpoint();return phase=null,companionIsOn()&&connection&&["unavailable","error"].includes(connection.status)&&(phase={status:"error",email:user.email,endpoint:endpoint.endpoint.url,message:"The address is ready, but this app could not start its secure connection. Local pairing still works."}),settledState()},writeLog=line3=>{try{log2(line3)}catch{}},failAction=(error62,{
|
|
8652
8652
|
email:email3,expiredSessionIsSignedOut=!1,signedOut=!1}={})=>{let message5=friendlyCompanionAccountError(error62);return writeLog(error62 instanceof ControlPlaneError?`companion account: setup failed code=${error62.code} status=${error62.status||"none"} ref=${error62.requestId||"none"}`:"companion account: setup failed on this computer (not a control-plane answer)"),phase={status:signedOut||expiredSessionIsSignedOut&&error62 instanceof ControlPlaneError&&error62.status===401?"signed-out":"error",
|
|
8653
|
-
email:email3,message:message5},message5},requestCode=rawEmail=>serialize(async()=>{if(!configured)throw new Error(FRIENDLY_MESSAGES.control_plane_unavailable);let email3=normalizeAccountEmail(rawEmail),requested;try{await requireHealthyControlPlane(),requested=await client.requestOTP(email3)}catch(error62){let message5=failAction(error62,{email:email3,signedOut:!0});throw new Error(message5)}return phase={status:"signed-out",email:requested.email},settledState()}),
|
|
8654
|
-
async()=>{if(!configured)throw new Error(FRIENDLY_MESSAGES.control_plane_unavailable);requestedAt=now();let email3=normalizeAccountEmail(rawEmail);phase={status:"connecting",email:email3};let verified;try{await requireHealthyControlPlane(),verified=await
|
|
8655
|
-
|
|
8656
|
-
|
|
8657
|
-
|
|
8658
|
-
email};try{return await requireHealthyControlPlane(),await provision({accountToken:account2.accountToken,user:{id:account2.userId,email:account2.email}})}catch(error62){return failAction(error62,{email:account2.email,expiredSessionIsSignedOut:!0}),scheduleAutoRetry(error62),settledState()}},retry=()=>serialize(async()=>(requestedAt=
|
|
8659
|
-
document3);if(!account2||!access2||!account2.installationCredential||companionAccountCleanupPending(document3)||typeof client.getEndpoint!="function")return null;lastEndpointCheck=now();let endpoint;try{endpoint=await client.getEndpoint(account2.installationCredential)}catch(error62){return error62 instanceof ControlPlaneError&&
|
|
8660
|
-
null||now()-lastEndpointCheck>=endpointCheckIntervalMs/2,recoveryDue=({atLaunch=!1}={})=>{if(!autoRecover||!companionIsOn())return!1;if(atLaunch)return!0;if(autoRetryTimer!==null)return!1;let connection=managedConnectionState?.()??{};return WATCHDOG_CHECK_STATES.has(connection.status)&&endpointCheckDue()},requestedRecently=()=>requestedAt!==
|
|
8661
|
-
currentNeed=async()=>{let answer=await Promise.resolve().then(()=>managedEndpointNeeded()).catch(()=>null);phonesUnused=answer===MANAGED_ENDPOINT_PHONES_UNUSED;let need=phonesUnused?!1:typeof answer=="boolean"?answer:null;return need===!1&&relay.capable()?!1:requestedRecently()?(phonesUnused=!1,!0):need},releaseScheduledAt=()=>{let at2=credentials()[MANAGED_COMPANION_RELEASE_AT_FIELD];
|
|
8662
|
-
document3=>{let next={...document3};return delete next[MANAGED_COMPANION_RELEASE_AT_FIELD],next})},releaseAddress=async()=>{let need=await currentNeed(),pause2=phonesUnused;if(need!==!1)return need&&await cancelRelease(),settledState();let document3=credentials(),account2=storedAccount(document3);if(!account2?.installationCredential||!managedCompanionTunnelAccess(document3)||
|
|
8663
|
-
deleteEndpoint(account2.installationCredential)}catch(error62){if(removalPending=error62 instanceof ControlPlaneError&&error62.code==="endpoint_cleanup_pending",!(removalPending||error62 instanceof ControlPlaneError&&error62.status===401))return writeLog(error62 instanceof ControlPlaneError?`companion account: could not give the secure address back code=${error62.code}
|
|
8664
|
-
|
|
8665
|
-
reviewAddress=async({atLaunch=!1}={})=>{let document3=credentials();if(!storedAccount(document3)||companionAccountCleanupPending(document3))return null;if(!managedCompanionTunnelAccess(document3)){let waiting2=document3[COMPANION_TUNNEL_WAITING_FIELD]===!0;return!savedAddress(document3)&&!waiting2||autoRetryTimer!==null?null:await currentNeed()===!0?retryWork():
|
|
8666
|
-
null;let releaseAt=releaseScheduledAt();if(releaseAt!==null&&now()>=releaseAt)return releaseAddress();let connection=managedConnectionState?.()??{};if(companionIsOn()&&CONNECTOR_FAILING_STATES.has(connection.status)&&(atLaunch||endpointCheckDue())){let released=await reconcileIfEndpointGone({onGone:releaseAddress});if(released)return released}
|
|
8667
|
-
current=>managedCompanionTunnelAccess(current)?{...current,[MANAGED_COMPANION_RELEASE_AT_FIELD]:now()+delay3}:current),writeLog(`companion account: no device needs the secure address; giving it back in ${Math.round(delay3/6e4)} min`)}return null},retryIfWanted=async()=>requestedRecently()||savedAddress(credentials())&&await currentNeed()!==!1?
|
|
8668
|
-
retryFromTimer=()=>serialize(onDemand?retryIfWanted:retryWork);let prepare=()=>serialize(async()=>{let document3=credentials();if(!configured||!companionIsOn()||!storedAccount(document3)||companionAccountCleanupPending(document3))return settledState();if(requestedAt=now(),!managedCompanionTunnelAccess(document3))return retryWork();await cancelRelease();
|
|
8669
|
-
has(connection.status)){let repaired=await reconcileIfEndpointGone();if(repaired)return repaired}return settledState()}),watchdogTick=()=>{if(watchdogTimer=null,!disposed&&(watchdogTimer=setTimer(watchdogTick,endpointCheckIntervalMs),phase?.status!=="signed-out")){if(onDemand){serialize(()=>reviewAddress()).catch(()=>{});return}
|
|
8670
|
-
setTimer(watchdogTick,firstEndpointCheckMs))};return Object.freeze({state:async()=>(await probeControlPlane(),settledState()),requestCode,verifyCode,retry,prepare,signOut:()=>serialize(async()=>{if(resetAutoRetry(),!storedAccount(credentials()))return await clearAfterCleanup(),settledState();let email3=storedAccount(
|
|
8671
|
-
error62,{email:email3}),settledState()}}),restore:()=>serialize(async()=>{if(!configured||(startWatchdog(),!await probeControlPlane({force:!0})))return settledState();if(companionAccountCleanupPending(credentials()))return retryWork();if(await ensureClientIdentity(),onDemand){let reviewed=await reviewAddress({atLaunch:!0});
|
|
8672
|
-
account2&&companionIsOn()){let reconciled=await reconcileIfEndpointGone();if(reconciled)return reconciled}return phase=null,settledState()}),dispose:()=>{disposed=!0,cancelAutoRetry(),watchdogTimer!==null&&clearTimer(watchdogTimer),watchdogTimer=null}})}var SIGNIN_CODE_TTL_MS=10*6e4;init_user_errors();function parseAllowList(value){return(value??"").split(/[,\s]+/).map(entry=>entry.trim().toLowerCase()).filter(Boolean)}var NOT_WELCOME={ok:!1,status:403,...userError("serverError.email.notAllowed")};init_decision_log();init_redact2();init_usage_ledger();import{appendFile as appendFile2,mkdir as mkdir2}from"node:fs/promises";import{basename as basename2,join as join2}from"node:path";var DIR2="admin-activity";var PRUNE_EVERY_MS2=60*6e4,writeQueues2=new Map,lastPrune2=new Map;function adminActivityFileFor(dataDir,at2){return join2(dataDir,DIR2,`${monthKey(at2)}.ndjson`)}async function writeRow(dataDir,row){let at2=new Date(row.at);await mkdir2(join2(dataDir,DIR2),{recursive:!0,mode:448}),await appendFile2(adminActivityFileFor(dataDir,at2),JSON.stringify(row)+`
|
|
8653
|
+
email:email3,message:message5},message5},requestCode=rawEmail=>serialize(async()=>{if(!configured)throw new Error(FRIENDLY_MESSAGES.control_plane_unavailable);let email3=normalizeAccountEmail(rawEmail),requested;try{await requireHealthyControlPlane(),requested=await client.requestOTP(email3)}catch(error62){let message5=failAction(error62,{email:email3,signedOut:!0});throw new Error(message5)}return phase={status:"signed-out",email:requested.email},settledState()}),signInFlow=(rawEmail,obtain)=>serialize(
|
|
8654
|
+
async()=>{if(!configured)throw new Error(FRIENDLY_MESSAGES.control_plane_unavailable);requestedAt=now();let email3=normalizeAccountEmail(rawEmail);phase={status:"connecting",email:email3};let verified;try{await requireHealthyControlPlane(),verified=await obtain(email3)}catch(error62){let message5=failAction(error62,{email:email3,signedOut:!0});throw new Error(message5)}let previous2=storedAccount(credentials()),refreshingPendingCleanup=!!(previous2&&previous2.userId===verified.user.id&&companionAccountCleanupPending(
|
|
8655
|
+
credentials())),authenticatedPersisted=!1;try{previous2&&previous2.userId!==verified.user.id&&await cleanupCurrentAccount();let existingIdentity=ownString(credentials(),COMPANION_CLIENT_INSTANCE_FIELD),clientInstanceId=UUID.test(existingIdentity)?existingIdentity:newClientInstanceId?.();if(!UUID.test(clientInstanceId??""))throw new Error("A stable computer identity could not be created");return await updateCredentials(document3=>withAuthenticatedAccount(document3,{...verified,clientInstanceId,preserveCleanupPending:refreshingPendingCleanup})),
|
|
8656
|
+
authenticatedPersisted=!0,refreshingPendingCleanup?(await cleanupCurrentAccount({markPending:!1}),settledState()):await provision(verified)}catch(error62){return authenticatedPersisted||await client.signOut(verified.accountToken).catch(()=>{}),failAction(error62,{email:authenticatedPersisted?verified.user.email:previous2?.email??email3,expiredSessionIsSignedOut:authenticatedPersisted}),authenticatedPersisted&&scheduleAutoRetry(error62),settledState()}}),verifyCode=(rawEmail,rawCode)=>signInFlow(
|
|
8657
|
+
rawEmail,email3=>client.verifyOTP(email3,rawCode)),connectLimix=credential=>signInFlow(credential.email,async()=>({accountToken:credential.bearer,user:{id:credential.userId,email:credential.email}})),retryWork=async()=>{if(!configured)return settledState();let account2=storedAccount(credentials());if(!account2)return phase=null,settledState();if(companionAccountCleanupPending(credentials())){phase={status:"connecting",email:account2.email};try{await requireHealthyControlPlane(),await cleanupCurrentAccount(
|
|
8658
|
+
{markPending:!1})}catch(error62){failAction(error62,{email:account2.email,expiredSessionIsSignedOut:!0})}return settledState()}phase={status:"connecting",email:account2.email};try{return await requireHealthyControlPlane(),await provision({accountToken:account2.accountToken,user:{id:account2.userId,email:account2.email}})}catch(error62){return failAction(error62,{email:account2.email,expiredSessionIsSignedOut:!0}),scheduleAutoRetry(error62),settledState()}},retry=()=>serialize(async()=>(requestedAt=
|
|
8659
|
+
now(),retryWork())),reconcileIfEndpointGone=async({onGone=retryWork}={})=>{let document3=credentials(),account2=storedAccount(document3),access2=managedCompanionTunnelAccess(document3);if(!account2||!access2||!account2.installationCredential||companionAccountCleanupPending(document3)||typeof client.getEndpoint!="function")return null;lastEndpointCheck=now();let endpoint;try{endpoint=await client.getEndpoint(account2.installationCredential)}catch(error62){return error62 instanceof ControlPlaneError&&
|
|
8660
|
+
error62.status===401?onGone():null}return endpoint&&endpoint.url===access2.endpoint&&!ENDPOINT_NEEDS_RECONCILE.has(endpoint.status)?null:onGone()},endpointCheckDue=()=>lastEndpointCheck===null||now()-lastEndpointCheck>=endpointCheckIntervalMs/2,recoveryDue=({atLaunch=!1}={})=>{if(!autoRecover||!companionIsOn())return!1;if(atLaunch)return!0;if(autoRetryTimer!==null)return!1;let connection=managedConnectionState?.()??{};return WATCHDOG_CHECK_STATES.has(connection.status)&&endpointCheckDue()},requestedRecently=()=>requestedAt!==
|
|
8661
|
+
null&&now()-requestedAt<REQUEST_WINDOW_MS,savedAddress=document3=>normalizeManagedCompanionEndpoint(document3[MANAGED_COMPANION_ENDPOINT_FIELD]),phonesUnused=!1,currentNeed=async()=>{let answer=await Promise.resolve().then(()=>managedEndpointNeeded()).catch(()=>null);phonesUnused=answer===MANAGED_ENDPOINT_PHONES_UNUSED;let need=phonesUnused?!1:typeof answer=="boolean"?answer:null;return need===!1&&relay.capable()?!1:requestedRecently()?(phonesUnused=!1,!0):need},releaseScheduledAt=()=>{let at2=credentials()[MANAGED_COMPANION_RELEASE_AT_FIELD];
|
|
8662
|
+
return Number.isSafeInteger(at2)&&at2>0?at2:null},cancelRelease=async()=>{releaseScheduledAt()!==null&&await updateCredentials(document3=>{let next={...document3};return delete next[MANAGED_COMPANION_RELEASE_AT_FIELD],next})},releaseAddress=async()=>{let need=await currentNeed(),pause2=phonesUnused;if(need!==!1)return need&&await cancelRelease(),settledState();let document3=credentials(),account2=storedAccount(document3);if(!account2?.installationCredential||!managedCompanionTunnelAccess(document3)||
|
|
8663
|
+
companionAccountCleanupPending(document3))return settledState();await stopManagedEndpoint();let removalPending=!1;try{await client.deleteEndpoint(account2.installationCredential)}catch(error62){if(removalPending=error62 instanceof ControlPlaneError&&error62.code==="endpoint_cleanup_pending",!(removalPending||error62 instanceof ControlPlaneError&&error62.status===401))return writeLog(error62 instanceof ControlPlaneError?`companion account: could not give the secure address back code=${error62.code}\
|
|
8664
|
+
status=${error62.status||"none"} ref=${error62.requestId||"none"}`:"companion account: could not give the secure address back (not a control-plane answer)"),await activatePersistedEndpoint(),settledState()}return await updateCredentials(current=>({...withoutManagedCompanionTunnelAccess(current),...removalPending?{[COMPANION_ENDPOINT_RELEASE_PENDING_FIELD]:!0}:{},...pause2?{[COMPANION_ENDPOINT_PAUSED_FIELD]:!0}:{}})),resetAutoRetry(),phase=null,writeLog(pause2?"companion account: gave the secure\
|
|
8665
|
+
address back; no paired phone was used in 30 days":"companion account: gave the secure address back; no device needs it"),settledState()},reviewAddress=async({atLaunch=!1}={})=>{let document3=credentials();if(!storedAccount(document3)||companionAccountCleanupPending(document3))return null;if(!managedCompanionTunnelAccess(document3)){let waiting2=document3[COMPANION_TUNNEL_WAITING_FIELD]===!0;return!savedAddress(document3)&&!waiting2||autoRetryTimer!==null?null:await currentNeed()===!0?retryWork():
|
|
8666
|
+
null}let need=await currentNeed();if(need!==!1)return need&&await cancelRelease(),need===null&&atLaunch?null:recoveryDue({atLaunch})?reconcileIfEndpointGone():null;let releaseAt=releaseScheduledAt();if(releaseAt!==null&&now()>=releaseAt)return releaseAddress();let connection=managedConnectionState?.()??{};if(companionIsOn()&&CONNECTOR_FAILING_STATES.has(connection.status)&&(atLaunch||endpointCheckDue())){let released=await reconcileIfEndpointGone({onGone:releaseAddress});if(released)return released}
|
|
8667
|
+
if(releaseAt===null||releaseAt-now()>releaseGraceMs+releaseJitterMs){let delay3=releaseGraceMs+Math.round(random()*releaseJitterMs);await updateCredentials(current=>managedCompanionTunnelAccess(current)?{...current,[MANAGED_COMPANION_RELEASE_AT_FIELD]:now()+delay3}:current),writeLog(`companion account: no device needs the secure address; giving it back in ${Math.round(delay3/6e4)} min`)}return null},retryIfWanted=async()=>requestedRecently()||savedAddress(credentials())&&await currentNeed()!==!1?
|
|
8668
|
+
retryWork():(resetAutoRetry(),phase?.status==="error"&&(phase=null),writeLog("companion account: stopped retrying; no device needs a secure address"),settledState());retryFromTimer=()=>serialize(onDemand?retryIfWanted:retryWork);let prepare=()=>serialize(async()=>{let document3=credentials();if(!configured||!companionIsOn()||!storedAccount(document3)||companionAccountCleanupPending(document3))return settledState();if(requestedAt=now(),!managedCompanionTunnelAccess(document3))return retryWork();await cancelRelease();
|
|
8669
|
+
let connection=managedConnectionState?.()??{};if(["stopped","unconfigured"].includes(connection.status))await activatePersistedEndpoint();else if(CONNECTOR_FAILING_STATES.has(connection.status)){let repaired=await reconcileIfEndpointGone();if(repaired)return repaired}return settledState()}),watchdogTick=()=>{if(watchdogTimer=null,!disposed&&(watchdogTimer=setTimer(watchdogTick,endpointCheckIntervalMs),phase?.status!=="signed-out")){if(onDemand){serialize(()=>reviewAddress()).catch(()=>{});return}
|
|
8670
|
+
recoveryDue()&&serialize(()=>reconcileIfEndpointGone()).catch(()=>{})}},startWatchdog=()=>{!(autoRecover||onDemand)||disposed||!configured||watchdogTimer!==null||(watchdogTimer=setTimer(watchdogTick,firstEndpointCheckMs))};return Object.freeze({state:async()=>(await probeControlPlane(),settledState()),requestCode,verifyCode,connectLimix,retry,prepare,signOut:()=>serialize(async()=>{if(resetAutoRetry(),!storedAccount(credentials()))return await clearAfterCleanup(),settledState();let email3=storedAccount(
|
|
8671
|
+
credentials())?.email;phase={status:"connecting",email:email3};try{return await cleanupCurrentAccount(),healthy=!0,lastHealthCheck=now(),settledState()}catch(error62){return failAction(error62,{email:email3}),settledState()}}),restore:()=>serialize(async()=>{if(!configured||(startWatchdog(),!await probeControlPlane({force:!0})))return settledState();if(companionAccountCleanupPending(credentials()))return retryWork();if(await ensureClientIdentity(),onDemand){let reviewed=await reviewAddress({atLaunch:!0});
|
|
8672
|
+
return reviewed||(phase=null,settledState())}let account2=storedAccount(credentials());if(account2&&!managedCompanionTunnelAccess(credentials()))return retryWork();if(autoRecover&&account2&&companionIsOn()){let reconciled=await reconcileIfEndpointGone();if(reconciled)return reconciled}return phase=null,settledState()}),dispose:()=>{disposed=!0,cancelAutoRetry(),watchdogTimer!==null&&clearTimer(watchdogTimer),watchdogTimer=null}})}var SIGNIN_CODE_TTL_MS=10*6e4;init_user_errors();function parseAllowList(value){return(value??"").split(/[,\s]+/).map(entry=>entry.trim().toLowerCase()).filter(Boolean)}var NOT_WELCOME={ok:!1,status:403,...userError("serverError.email.notAllowed")};init_decision_log();init_redact2();init_usage_ledger();import{appendFile as appendFile2,mkdir as mkdir2}from"node:fs/promises";import{basename as basename2,join as join2}from"node:path";var DIR2="admin-activity";var PRUNE_EVERY_MS2=60*6e4,writeQueues2=new Map,lastPrune2=new Map;function adminActivityFileFor(dataDir,at2){return join2(dataDir,DIR2,`${monthKey(at2)}.ndjson`)}async function writeRow(dataDir,row){let at2=new Date(row.at);await mkdir2(join2(dataDir,DIR2),{recursive:!0,mode:448}),await appendFile2(adminActivityFileFor(dataDir,at2),JSON.stringify(row)+`
|
|
8673
8673
|
`,{mode:384}),at2.getTime()-(lastPrune2.get(dataDir)??0)>=PRUNE_EVERY_MS2&&(lastPrune2.set(dataDir,at2.getTime()),await pruneMonthFiles(join2(dataDir,DIR2),boundRetentionDays(),at2))}function appendAdminAction(dataDir,row){let record12={...row,at:row.at??new Date().toISOString(),...row.before?{before:auditValues(row.before)}:{},...row.after?{after:auditValues(row.after)}:{}},queued=(writeQueues2.get(dataDir)??Promise.resolve()).then(()=>writeRow(dataDir,record12)).catch(()=>{});writeQueues2.set(
|
|
8674
8674
|
dataDir,queued),queued.finally(()=>{writeQueues2.get(dataDir)===queued&&writeQueues2.delete(dataDir)})}async function flushAdminActivity(dataDir){await writeQueues2.get(dataDir)}var SECRET_PARTS=["token","secret","password","passwd","passphrase","credential","authorization","cookie","bearer","apikey","api_key"],OPAQUE_MAP=/^(?:headers|env|environment)$/i,MAX_VALUE_CHARS=2e3,HIDDEN="[hidden]";function isSecretName2(name){let lower=name.toLowerCase();return lower.endsWith("tokens")?!1:SECRET_PARTS.some(part=>lower.includes(part))?!0:/(?:^|[_.-])keys?$/.test(lower)||/[a-z]Keys?$/.test(name)}function isSecretParameter(name){
|
|
8675
8675
|
if(name==="-k"||name==="-K")return!0;let bare=name.replace(/^-+/,"");return isSecretName2(bare)||/^(?:auth|sig|signature|pass|pwd|code)$/i.test(bare)}function keyLikeSegment(segment){return(segment.match(/[A-Za-z0-9]{16,}/g)??[]).some(run6=>/\d/.test(run6)&&/[A-Za-z]/.test(run6))}function maskUrlSecrets(text13){return text13.replace(/\b([a-z][\w+.-]*:\/\/)([^\s/?#]*)([^\s?#]*)([^\s]*)/gi,(_all,scheme,authority2,path3,rest)=>{let at2=authority2.lastIndexOf("@"),host2=at2>=0?`${HIDDEN}@${authority2.
|
|
@@ -11933,7 +11933,7 @@ function configStatus() {
|
|
|
11933
11933
|
decider: describeDecider(cfg), helpers: describeHelpers(cfg),
|
|
11934
11934
|
imageGen: avatarImageStatus(cfg), savedKeys: nestedKeyStatus(cfg),
|
|
11935
11935
|
live: liveSettingsFor(cfg),
|
|
11936
|
-
profile: CLOUD_TEAM ? NOBODY_PROFILE : { name: cfg.profile?.name
|
|
11936
|
+
profile: CLOUD_TEAM ? NOBODY_PROFILE : { name: cfg.profile?.name || process.env.LIMIX_ACCOUNT_NAME || "", email: cfg.profile?.email || process.env.LIMIX_ACCOUNT_EMAIL || "", aboutMe: cfg.profile?.aboutMe ?? "", ...(cfg.profile?.avatarUrl ? { avatarUrl: cfg.profile.avatarUrl } : {}) },
|
|
11937
11937
|
managedPolicy: managedPolicy.summary(),
|
|
11938
11938
|
...(CLOUD_HOME ? { cloudHome: true } : {}), ...(CLOUD_TEAM ? { team: { id: CLOUD_TEAM.id, name: CLOUD_TEAM.name, ...(CLOUD_HOME ? { cloudPage: `${CLOUD_HOME.adminOrigin}/cloud` } : {}) } } : {}),
|
|
11939
11939
|
language: appLanguage() ?? "", computerName: cfg.computerName ?? "", everyBotRules: cfg.everyBotRules ?? "",
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// Limix Bot: skills kept in a folder on this computer (no internet needed). The folder is either one skill (it has a
|
|
2
|
+
// SKILL.md) or a folder of skills (each direct subfolder with a SKILL.md). Same limits and checks as a GitHub import:
|
|
3
|
+
// the files go through installSkill(), which scans them and leaves the skill switched off until the owner reads it.
|
|
4
|
+
import { lstatSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
5
|
+
import { basename, isAbsolute, join } from "node:path";
|
|
6
|
+
import { planSkillFolder } from "./skill-folder.js";
|
|
7
|
+
const MAX_ENTRIES = 400;
|
|
8
|
+
const MAX_DEPTH = 8;
|
|
9
|
+
function listEntries(root) {
|
|
10
|
+
const out = [];
|
|
11
|
+
const walk = (dir, prefix, depth) => {
|
|
12
|
+
if (depth > MAX_DEPTH || out.length > MAX_ENTRIES)
|
|
13
|
+
return;
|
|
14
|
+
for (const name of readdirSync(dir)) {
|
|
15
|
+
if (out.length > MAX_ENTRIES)
|
|
16
|
+
return;
|
|
17
|
+
const absolute = join(dir, name);
|
|
18
|
+
const path = prefix ? `${prefix}/${name}` : name;
|
|
19
|
+
const info = lstatSync(absolute);
|
|
20
|
+
if (info.isSymbolicLink())
|
|
21
|
+
out.push({ path, kind: "link", size: 0, absolute });
|
|
22
|
+
else if (info.isDirectory()) {
|
|
23
|
+
out.push({ path, kind: "folder", size: 0, absolute });
|
|
24
|
+
walk(absolute, path, depth + 1);
|
|
25
|
+
}
|
|
26
|
+
else if (info.isFile()) {
|
|
27
|
+
out.push({ path, kind: "file", size: info.size, executable: process.platform !== "win32" && (info.mode & 0o111) !== 0, absolute });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
walk(root, "", 1);
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
function readOne(dir) {
|
|
35
|
+
const { take, skipped } = planSkillFolder(listEntries(dir));
|
|
36
|
+
if (take[0]?.path !== "SKILL.md")
|
|
37
|
+
throw new Error(`no SKILL.md in ${basename(dir)}`);
|
|
38
|
+
const files = take
|
|
39
|
+
.filter((entry) => entry.kind === "file")
|
|
40
|
+
.map((entry) => ({ path: entry.path, content: readFileSync(entry.absolute), executable: entry.executable === true }));
|
|
41
|
+
return { source: `local:${basename(dir)}`, files, skipped };
|
|
42
|
+
}
|
|
43
|
+
export function readLocalSkills(folder) {
|
|
44
|
+
try {
|
|
45
|
+
if (!isAbsolute(folder) || !statSync(folder).isDirectory())
|
|
46
|
+
return { error: "Choose a folder on this computer." };
|
|
47
|
+
const dirs = [];
|
|
48
|
+
const has = (dir) => { try {
|
|
49
|
+
return statSync(join(dir, "SKILL.md")).isFile();
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return false;
|
|
53
|
+
} };
|
|
54
|
+
if (has(folder))
|
|
55
|
+
dirs.push(folder);
|
|
56
|
+
else
|
|
57
|
+
for (const name of readdirSync(folder)) {
|
|
58
|
+
const sub = join(folder, name);
|
|
59
|
+
try {
|
|
60
|
+
if (statSync(sub).isDirectory() && has(sub))
|
|
61
|
+
dirs.push(sub);
|
|
62
|
+
}
|
|
63
|
+
catch { /* skip unreadable */ }
|
|
64
|
+
}
|
|
65
|
+
if (!dirs.length)
|
|
66
|
+
return { error: "No SKILL.md found in that folder or in its subfolders." };
|
|
67
|
+
return { skills: dirs.slice(0, 50).map(readOne) };
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
return { error: error instanceof Error ? error.message : "Could not read that folder." };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -3,6 +3,7 @@ import { setImportedSkillEnabled } from "../imported-skills.js";
|
|
|
3
3
|
import { setNativeSkillEnabled } from "../native-skill-choices.js";
|
|
4
4
|
import { botSkillTemplateSchema } from "../new-bot-defaults.js";
|
|
5
5
|
import { fetchSkillFromSource } from "../skill-fetch.js";
|
|
6
|
+
import { readLocalSkills } from "../limix-skill-folder.js";
|
|
6
7
|
import { skillImportSummary } from "../skill-folder.js";
|
|
7
8
|
import { installLibrarySkill, librarySkillOptOuts, listLibrarySkills, readLibrarySkillFile, readSkillLibraryIndex, setLibrarySkillEveryBot, setLibrarySkillOptOut, setLibrarySkillReviewState, skillsLibraryEnabled, unassignLibrarySkill } from "../skill-library.js";
|
|
8
9
|
import { installSkill, listBotSkillsWithOrigin, listStagedSkillWrites, parseSkillMd, removeSkill, scanSkillText, setSkillEnabled, } from "../skills.js";
|
|
@@ -62,7 +63,7 @@ export function createBotSkillsRoutes(deps) {
|
|
|
62
63
|
const parsed = z.object({ source: z.string().min(1).max(2000) }).safeParse(await readBody(req));
|
|
63
64
|
if (!parsed.success)
|
|
64
65
|
return json(res, 400, { error: "source must be a GitHub or skills.sh URL, or owner/repo" });
|
|
65
|
-
const fetched = await fetchSkillFromSource(parsed.data.source);
|
|
66
|
+
const fetched = parsed.data.source.startsWith("local-folder:") ? readLocalSkills(parsed.data.source.slice("local-folder:".length)) : await fetchSkillFromSource(parsed.data.source);
|
|
66
67
|
if ("error" in fetched)
|
|
67
68
|
return json(res, 422, { error: fetched.error });
|
|
68
69
|
const results = fetched.skills.map((skill) => ({ skill, result: installSkill(m[1], skill.source, skill.files, skill.github) }));
|