@nxuss/lemma 1.43.0 → 1.45.0
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/README.md +26 -8
- package/bin/brain-ingest.js +48 -13
- package/bin/cloud.js +228 -0
- package/dist/cjs/cli/hostHooks.d.ts +44 -7
- package/dist/cjs/cli/hostHooks.d.ts.map +1 -1
- package/dist/cjs/cli/hostHooks.js +201 -11
- package/dist/cjs/cli/hostHooks.js.map +1 -1
- package/dist/cjs/cli/lemma-proxy.d.ts.map +1 -1
- package/dist/cjs/cli/lemma-proxy.js +13 -16
- package/dist/cjs/cli/lemma-proxy.js.map +1 -1
- package/dist/cjs/cloud/CloudBrainClient.d.ts +52 -0
- package/dist/cjs/cloud/CloudBrainClient.d.ts.map +1 -0
- package/dist/cjs/cloud/CloudBrainClient.js +161 -0
- package/dist/cjs/cloud/CloudBrainClient.js.map +1 -0
- package/dist/cjs/cloud/CloudConfig.d.ts +41 -0
- package/dist/cjs/cloud/CloudConfig.d.ts.map +1 -0
- package/dist/cjs/cloud/CloudConfig.js +133 -0
- package/dist/cjs/cloud/CloudConfig.js.map +1 -0
- package/dist/cjs/cloud/CloudEntitlement.d.ts +55 -0
- package/dist/cjs/cloud/CloudEntitlement.d.ts.map +1 -0
- package/dist/cjs/cloud/CloudEntitlement.js +174 -0
- package/dist/cjs/cloud/CloudEntitlement.js.map +1 -0
- package/dist/cjs/cloud/billing/stripeApi.d.ts +43 -0
- package/dist/cjs/cloud/billing/stripeApi.d.ts.map +1 -0
- package/dist/cjs/cloud/billing/stripeApi.js +116 -0
- package/dist/cjs/cloud/billing/stripeApi.js.map +1 -0
- package/dist/cjs/cloud/billing/stripeWebhook.d.ts +35 -0
- package/dist/cjs/cloud/billing/stripeWebhook.d.ts.map +1 -0
- package/dist/cjs/cloud/billing/stripeWebhook.js +190 -0
- package/dist/cjs/cloud/billing/stripeWebhook.js.map +1 -0
- package/dist/cjs/cloud/console/ConsoleStore.d.ts +111 -0
- package/dist/cjs/cloud/console/ConsoleStore.d.ts.map +1 -0
- package/dist/cjs/cloud/console/ConsoleStore.js +172 -0
- package/dist/cjs/cloud/console/ConsoleStore.js.map +1 -0
- package/dist/cjs/cloud/console/consoleRouter.d.ts +68 -0
- package/dist/cjs/cloud/console/consoleRouter.d.ts.map +1 -0
- package/dist/cjs/cloud/console/consoleRouter.js +301 -0
- package/dist/cjs/cloud/console/consoleRouter.js.map +1 -0
- package/dist/cjs/cloud/console/mailer.d.ts +22 -0
- package/dist/cjs/cloud/console/mailer.d.ts.map +1 -0
- package/dist/cjs/cloud/console/mailer.js +35 -0
- package/dist/cjs/cloud/console/mailer.js.map +1 -0
- package/dist/cjs/cloud/identity/PlanPolicy.d.ts +42 -6
- package/dist/cjs/cloud/identity/PlanPolicy.d.ts.map +1 -1
- package/dist/cjs/cloud/identity/PlanPolicy.js +102 -22
- package/dist/cjs/cloud/identity/PlanPolicy.js.map +1 -1
- package/dist/cjs/cloud/identity/RateLimiter.d.ts +21 -1
- package/dist/cjs/cloud/identity/RateLimiter.d.ts.map +1 -1
- package/dist/cjs/cloud/identity/RateLimiter.js +59 -2
- package/dist/cjs/cloud/identity/RateLimiter.js.map +1 -1
- package/dist/cjs/cloud/identity/TenantResolver.d.ts +6 -1
- package/dist/cjs/cloud/identity/TenantResolver.d.ts.map +1 -1
- package/dist/cjs/cloud/identity/TenantResolver.js +1 -1
- package/dist/cjs/cloud/identity/TenantResolver.js.map +1 -1
- package/dist/cjs/cloud/identity/authenticateV2.d.ts.map +1 -1
- package/dist/cjs/cloud/identity/authenticateV2.js +7 -4
- package/dist/cjs/cloud/identity/authenticateV2.js.map +1 -1
- package/dist/cjs/cloud/identity/identityStore.d.ts +96 -10
- package/dist/cjs/cloud/identity/identityStore.d.ts.map +1 -1
- package/dist/cjs/cloud/identity/identityStore.js +203 -4
- package/dist/cjs/cloud/identity/identityStore.js.map +1 -1
- package/dist/cjs/cloud/metering/PostgresLedgerStore.d.ts +18 -0
- package/dist/cjs/cloud/metering/PostgresLedgerStore.d.ts.map +1 -0
- package/dist/cjs/cloud/metering/PostgresLedgerStore.js +56 -0
- package/dist/cjs/cloud/metering/PostgresLedgerStore.js.map +1 -0
- package/dist/cjs/cloud/metering/UsageLedger.d.ts +74 -0
- package/dist/cjs/cloud/metering/UsageLedger.d.ts.map +1 -1
- package/dist/cjs/cloud/metering/UsageLedger.js +122 -17
- package/dist/cjs/cloud/metering/UsageLedger.js.map +1 -1
- package/dist/cjs/cloud/metering/index.d.ts +1 -0
- package/dist/cjs/cloud/metering/index.d.ts.map +1 -1
- package/dist/cjs/cloud/metering/index.js +1 -0
- package/dist/cjs/cloud/metering/index.js.map +1 -1
- package/dist/cjs/cloud/store/FileBrainStore.d.ts +6 -1
- package/dist/cjs/cloud/store/FileBrainStore.d.ts.map +1 -1
- package/dist/cjs/cloud/store/FileBrainStore.js +8 -0
- package/dist/cjs/cloud/store/FileBrainStore.js.map +1 -1
- package/dist/cjs/cloud/store/PostgresBrainStore.d.ts +11 -1
- package/dist/cjs/cloud/store/PostgresBrainStore.d.ts.map +1 -1
- package/dist/cjs/cloud/store/PostgresBrainStore.js +32 -0
- package/dist/cjs/cloud/store/PostgresBrainStore.js.map +1 -1
- package/dist/cjs/cloud/store/memorySummary.d.ts +29 -0
- package/dist/cjs/cloud/store/memorySummary.d.ts.map +1 -0
- package/dist/cjs/cloud/store/memorySummary.js +66 -0
- package/dist/cjs/cloud/store/memorySummary.js.map +1 -0
- package/dist/cjs/cloud/v2/app.d.ts.map +1 -1
- package/dist/cjs/cloud/v2/app.js +6 -0
- package/dist/cjs/cloud/v2/app.js.map +1 -1
- package/dist/cjs/cloud/v2/inputGuard.d.ts +23 -0
- package/dist/cjs/cloud/v2/inputGuard.d.ts.map +1 -0
- package/dist/cjs/cloud/v2/inputGuard.js +71 -0
- package/dist/cjs/cloud/v2/inputGuard.js.map +1 -0
- package/dist/cjs/cloud/v2/routes/admin.d.ts +24 -0
- package/dist/cjs/cloud/v2/routes/admin.d.ts.map +1 -0
- package/dist/cjs/cloud/v2/routes/admin.js +344 -0
- package/dist/cjs/cloud/v2/routes/admin.js.map +1 -0
- package/dist/cjs/cloud/v2/routes/entitlement.d.ts +13 -0
- package/dist/cjs/cloud/v2/routes/entitlement.d.ts.map +1 -0
- package/dist/cjs/cloud/v2/routes/entitlement.js +24 -0
- package/dist/cjs/cloud/v2/routes/entitlement.js.map +1 -0
- package/dist/cjs/cloud/v2/routes/index.d.ts +14 -1
- package/dist/cjs/cloud/v2/routes/index.d.ts.map +1 -1
- package/dist/cjs/cloud/v2/routes/index.js +36 -0
- package/dist/cjs/cloud/v2/routes/index.js.map +1 -1
- package/dist/cjs/cloud/v2/routes/memories.d.ts +21 -2
- package/dist/cjs/cloud/v2/routes/memories.d.ts.map +1 -1
- package/dist/cjs/cloud/v2/routes/memories.js +77 -0
- package/dist/cjs/cloud/v2/routes/memories.js.map +1 -1
- package/dist/cjs/cloud/v2/routes/recall.d.ts +1 -0
- package/dist/cjs/cloud/v2/routes/recall.d.ts.map +1 -1
- package/dist/cjs/cloud/v2/routes/recall.js +4 -0
- package/dist/cjs/cloud/v2/routes/recall.js.map +1 -1
- package/dist/cjs/cloud/v2/routes/tenant.d.ts +36 -0
- package/dist/cjs/cloud/v2/routes/tenant.d.ts.map +1 -0
- package/dist/cjs/cloud/v2/routes/tenant.js +65 -0
- package/dist/cjs/cloud/v2/routes/tenant.js.map +1 -0
- package/dist/cjs/cloud/v2/routes/usage.d.ts +1 -1
- package/dist/cjs/cloud/v2/routes/usage.d.ts.map +1 -1
- package/dist/cjs/cloud/v2/routes/verify.d.ts +1 -0
- package/dist/cjs/cloud/v2/routes/verify.d.ts.map +1 -1
- package/dist/cjs/cloud/v2/routes/verify.js +4 -0
- package/dist/cjs/cloud/v2/routes/verify.js.map +1 -1
- package/dist/cjs/cloud/v2/server.d.ts +9 -3
- package/dist/cjs/cloud/v2/server.d.ts.map +1 -1
- package/dist/cjs/cloud/v2/server.js +36 -2
- package/dist/cjs/cloud/v2/server.js.map +1 -1
- package/dist/cjs/cloud/v2/usageRecorder.d.ts +19 -0
- package/dist/cjs/cloud/v2/usageRecorder.d.ts.map +1 -0
- package/dist/cjs/cloud/v2/usageRecorder.js +42 -0
- package/dist/cjs/cloud/v2/usageRecorder.js.map +1 -0
- package/dist/cjs/contracts/api-v2.types.d.ts +92 -2
- package/dist/cjs/contracts/api-v2.types.d.ts.map +1 -1
- package/dist/cjs/contracts/store.d.ts +37 -0
- package/dist/cjs/contracts/store.d.ts.map +1 -1
- package/dist/cjs/mcp/index.js +7 -1
- package/dist/cjs/mcp/index.js.map +1 -1
- package/dist/cjs/mcp/tools/memory.d.ts.map +1 -1
- package/dist/cjs/mcp/tools/memory.js +74 -4
- package/dist/cjs/mcp/tools/memory.js.map +1 -1
- package/dist/cjs/mcp/tools/misc.d.ts.map +1 -1
- package/dist/cjs/mcp/tools/misc.js +2 -1
- package/dist/cjs/mcp/tools/misc.js.map +1 -1
- package/dist/cjs/mcp/tools/workspace.d.ts.map +1 -1
- package/dist/cjs/mcp/tools/workspace.js +4 -1
- package/dist/cjs/mcp/tools/workspace.js.map +1 -1
- package/dist/cjs/mcp/tools.d.ts +10 -0
- package/dist/cjs/mcp/tools.d.ts.map +1 -1
- package/dist/cjs/mcp/tools.js +47 -12
- package/dist/cjs/mcp/tools.js.map +1 -1
- package/dist/cjs/proxy/KeyManager.d.ts.map +1 -1
- package/dist/cjs/proxy/KeyManager.js +5 -0
- package/dist/cjs/proxy/KeyManager.js.map +1 -1
- package/dist/cjs/subconscious/CloudBrain.d.ts +77 -0
- package/dist/cjs/subconscious/CloudBrain.d.ts.map +1 -0
- package/dist/cjs/subconscious/CloudBrain.js +347 -0
- package/dist/cjs/subconscious/CloudBrain.js.map +1 -0
- package/dist/cjs/subconscious/HostRecall.d.ts.map +1 -1
- package/dist/cjs/subconscious/HostRecall.js +11 -4
- package/dist/cjs/subconscious/HostRecall.js.map +1 -1
- package/dist/cjs/subconscious/ProjectIdentity.d.ts +9 -0
- package/dist/cjs/subconscious/ProjectIdentity.d.ts.map +1 -0
- package/dist/cjs/subconscious/ProjectIdentity.js +63 -0
- package/dist/cjs/subconscious/ProjectIdentity.js.map +1 -0
- package/dist/cjs/subconscious/TeamBrain.d.ts +9 -3
- package/dist/cjs/subconscious/TeamBrain.d.ts.map +1 -1
- package/dist/cjs/subconscious/TeamBrain.js +39 -5
- package/dist/cjs/subconscious/TeamBrain.js.map +1 -1
- package/dist/cjs/utils/FixCapture.d.ts +7 -5
- package/dist/cjs/utils/FixCapture.d.ts.map +1 -1
- package/dist/cjs/utils/FixCapture.js +64 -32
- package/dist/cjs/utils/FixCapture.js.map +1 -1
- package/dist/cjs/utils/NoTerminal.d.ts +27 -0
- package/dist/cjs/utils/NoTerminal.d.ts.map +1 -0
- package/dist/cjs/utils/NoTerminal.js +37 -0
- package/dist/cjs/utils/NoTerminal.js.map +1 -0
- package/dist/cjs/utils/OpenCodeSession.d.ts +70 -0
- package/dist/cjs/utils/OpenCodeSession.d.ts.map +1 -0
- package/dist/cjs/utils/OpenCodeSession.js +154 -0
- package/dist/cjs/utils/OpenCodeSession.js.map +1 -0
- package/dist/cjs/utils/ProLicense.d.ts.map +1 -1
- package/dist/cjs/utils/ProLicense.js +11 -3
- package/dist/cjs/utils/ProLicense.js.map +1 -1
- package/dist/cjs/utils/SessionCapture.d.ts +31 -7
- package/dist/cjs/utils/SessionCapture.d.ts.map +1 -1
- package/dist/cjs/utils/SessionCapture.js +185 -32
- package/dist/cjs/utils/SessionCapture.js.map +1 -1
- package/dist/cjs/utils/StopNudge.d.ts +8 -0
- package/dist/cjs/utils/StopNudge.d.ts.map +1 -0
- package/dist/cjs/utils/StopNudge.js +93 -0
- package/dist/cjs/utils/StopNudge.js.map +1 -0
- package/dist/cjs/utils/TestAutofixInterceptor.d.ts.map +1 -1
- package/dist/cjs/utils/TestAutofixInterceptor.js +2 -0
- package/dist/cjs/utils/TestAutofixInterceptor.js.map +1 -1
- package/dist/esm/cli/hostHooks.d.ts +44 -7
- package/dist/esm/cli/hostHooks.d.ts.map +1 -1
- package/dist/esm/cli/hostHooks.js +199 -10
- package/dist/esm/cli/hostHooks.js.map +1 -1
- package/dist/esm/cli/lemma-proxy.d.ts.map +1 -1
- package/dist/esm/cli/lemma-proxy.js +14 -17
- package/dist/esm/cli/lemma-proxy.js.map +1 -1
- package/dist/esm/cloud/CloudBrainClient.d.ts +52 -0
- package/dist/esm/cloud/CloudBrainClient.d.ts.map +1 -0
- package/dist/esm/cloud/CloudBrainClient.js +153 -0
- package/dist/esm/cloud/CloudBrainClient.js.map +1 -0
- package/dist/esm/cloud/CloudConfig.d.ts +41 -0
- package/dist/esm/cloud/CloudConfig.d.ts.map +1 -0
- package/dist/esm/cloud/CloudConfig.js +118 -0
- package/dist/esm/cloud/CloudConfig.js.map +1 -0
- package/dist/esm/cloud/CloudEntitlement.d.ts +55 -0
- package/dist/esm/cloud/CloudEntitlement.d.ts.map +1 -0
- package/dist/esm/cloud/CloudEntitlement.js +159 -0
- package/dist/esm/cloud/CloudEntitlement.js.map +1 -0
- package/dist/esm/cloud/billing/stripeApi.d.ts +43 -0
- package/dist/esm/cloud/billing/stripeApi.d.ts.map +1 -0
- package/dist/esm/cloud/billing/stripeApi.js +108 -0
- package/dist/esm/cloud/billing/stripeApi.js.map +1 -0
- package/dist/esm/cloud/billing/stripeWebhook.d.ts +35 -0
- package/dist/esm/cloud/billing/stripeWebhook.d.ts.map +1 -0
- package/dist/esm/cloud/billing/stripeWebhook.js +181 -0
- package/dist/esm/cloud/billing/stripeWebhook.js.map +1 -0
- package/dist/esm/cloud/console/ConsoleStore.d.ts +111 -0
- package/dist/esm/cloud/console/ConsoleStore.d.ts.map +1 -0
- package/dist/esm/cloud/console/ConsoleStore.js +161 -0
- package/dist/esm/cloud/console/ConsoleStore.js.map +1 -0
- package/dist/esm/cloud/console/consoleRouter.d.ts +68 -0
- package/dist/esm/cloud/console/consoleRouter.d.ts.map +1 -0
- package/dist/esm/cloud/console/consoleRouter.js +290 -0
- package/dist/esm/cloud/console/consoleRouter.js.map +1 -0
- package/dist/esm/cloud/console/mailer.d.ts +22 -0
- package/dist/esm/cloud/console/mailer.d.ts.map +1 -0
- package/dist/esm/cloud/console/mailer.js +30 -0
- package/dist/esm/cloud/console/mailer.js.map +1 -0
- package/dist/esm/cloud/identity/PlanPolicy.d.ts +42 -6
- package/dist/esm/cloud/identity/PlanPolicy.d.ts.map +1 -1
- package/dist/esm/cloud/identity/PlanPolicy.js +100 -21
- package/dist/esm/cloud/identity/PlanPolicy.js.map +1 -1
- package/dist/esm/cloud/identity/RateLimiter.d.ts +21 -1
- package/dist/esm/cloud/identity/RateLimiter.d.ts.map +1 -1
- package/dist/esm/cloud/identity/RateLimiter.js +57 -2
- package/dist/esm/cloud/identity/RateLimiter.js.map +1 -1
- package/dist/esm/cloud/identity/TenantResolver.d.ts +6 -1
- package/dist/esm/cloud/identity/TenantResolver.d.ts.map +1 -1
- package/dist/esm/cloud/identity/TenantResolver.js +1 -1
- package/dist/esm/cloud/identity/TenantResolver.js.map +1 -1
- package/dist/esm/cloud/identity/authenticateV2.d.ts.map +1 -1
- package/dist/esm/cloud/identity/authenticateV2.js +7 -4
- package/dist/esm/cloud/identity/authenticateV2.js.map +1 -1
- package/dist/esm/cloud/identity/identityStore.d.ts +96 -10
- package/dist/esm/cloud/identity/identityStore.d.ts.map +1 -1
- package/dist/esm/cloud/identity/identityStore.js +199 -3
- package/dist/esm/cloud/identity/identityStore.js.map +1 -1
- package/dist/esm/cloud/metering/PostgresLedgerStore.d.ts +18 -0
- package/dist/esm/cloud/metering/PostgresLedgerStore.d.ts.map +1 -0
- package/dist/esm/cloud/metering/PostgresLedgerStore.js +52 -0
- package/dist/esm/cloud/metering/PostgresLedgerStore.js.map +1 -0
- package/dist/esm/cloud/metering/UsageLedger.d.ts +74 -0
- package/dist/esm/cloud/metering/UsageLedger.d.ts.map +1 -1
- package/dist/esm/cloud/metering/UsageLedger.js +119 -16
- package/dist/esm/cloud/metering/UsageLedger.js.map +1 -1
- package/dist/esm/cloud/metering/index.d.ts +1 -0
- package/dist/esm/cloud/metering/index.d.ts.map +1 -1
- package/dist/esm/cloud/metering/index.js +1 -0
- package/dist/esm/cloud/metering/index.js.map +1 -1
- package/dist/esm/cloud/store/FileBrainStore.d.ts +6 -1
- package/dist/esm/cloud/store/FileBrainStore.d.ts.map +1 -1
- package/dist/esm/cloud/store/FileBrainStore.js +8 -0
- package/dist/esm/cloud/store/FileBrainStore.js.map +1 -1
- package/dist/esm/cloud/store/PostgresBrainStore.d.ts +11 -1
- package/dist/esm/cloud/store/PostgresBrainStore.d.ts.map +1 -1
- package/dist/esm/cloud/store/PostgresBrainStore.js +32 -0
- package/dist/esm/cloud/store/PostgresBrainStore.js.map +1 -1
- package/dist/esm/cloud/store/memorySummary.d.ts +29 -0
- package/dist/esm/cloud/store/memorySummary.d.ts.map +1 -0
- package/dist/esm/cloud/store/memorySummary.js +60 -0
- package/dist/esm/cloud/store/memorySummary.js.map +1 -0
- package/dist/esm/cloud/v2/app.d.ts.map +1 -1
- package/dist/esm/cloud/v2/app.js +6 -0
- package/dist/esm/cloud/v2/app.js.map +1 -1
- package/dist/esm/cloud/v2/inputGuard.d.ts +23 -0
- package/dist/esm/cloud/v2/inputGuard.d.ts.map +1 -0
- package/dist/esm/cloud/v2/inputGuard.js +63 -0
- package/dist/esm/cloud/v2/inputGuard.js.map +1 -0
- package/dist/esm/cloud/v2/routes/admin.d.ts +24 -0
- package/dist/esm/cloud/v2/routes/admin.d.ts.map +1 -0
- package/dist/esm/cloud/v2/routes/admin.js +337 -0
- package/dist/esm/cloud/v2/routes/admin.js.map +1 -0
- package/dist/esm/cloud/v2/routes/entitlement.d.ts +13 -0
- package/dist/esm/cloud/v2/routes/entitlement.d.ts.map +1 -0
- package/dist/esm/cloud/v2/routes/entitlement.js +21 -0
- package/dist/esm/cloud/v2/routes/entitlement.js.map +1 -0
- package/dist/esm/cloud/v2/routes/index.d.ts +14 -1
- package/dist/esm/cloud/v2/routes/index.d.ts.map +1 -1
- package/dist/esm/cloud/v2/routes/index.js +37 -1
- package/dist/esm/cloud/v2/routes/index.js.map +1 -1
- package/dist/esm/cloud/v2/routes/memories.d.ts +21 -2
- package/dist/esm/cloud/v2/routes/memories.d.ts.map +1 -1
- package/dist/esm/cloud/v2/routes/memories.js +75 -0
- package/dist/esm/cloud/v2/routes/memories.js.map +1 -1
- package/dist/esm/cloud/v2/routes/recall.d.ts +1 -0
- package/dist/esm/cloud/v2/routes/recall.d.ts.map +1 -1
- package/dist/esm/cloud/v2/routes/recall.js +5 -1
- package/dist/esm/cloud/v2/routes/recall.js.map +1 -1
- package/dist/esm/cloud/v2/routes/tenant.d.ts +36 -0
- package/dist/esm/cloud/v2/routes/tenant.d.ts.map +1 -0
- package/dist/esm/cloud/v2/routes/tenant.js +61 -0
- package/dist/esm/cloud/v2/routes/tenant.js.map +1 -0
- package/dist/esm/cloud/v2/routes/usage.d.ts +1 -1
- package/dist/esm/cloud/v2/routes/usage.d.ts.map +1 -1
- package/dist/esm/cloud/v2/routes/verify.d.ts +1 -0
- package/dist/esm/cloud/v2/routes/verify.d.ts.map +1 -1
- package/dist/esm/cloud/v2/routes/verify.js +5 -1
- package/dist/esm/cloud/v2/routes/verify.js.map +1 -1
- package/dist/esm/cloud/v2/server.d.ts +9 -3
- package/dist/esm/cloud/v2/server.d.ts.map +1 -1
- package/dist/esm/cloud/v2/server.js +36 -3
- package/dist/esm/cloud/v2/server.js.map +1 -1
- package/dist/esm/cloud/v2/usageRecorder.d.ts +19 -0
- package/dist/esm/cloud/v2/usageRecorder.d.ts.map +1 -0
- package/dist/esm/cloud/v2/usageRecorder.js +37 -0
- package/dist/esm/cloud/v2/usageRecorder.js.map +1 -0
- package/dist/esm/contracts/api-v2.types.d.ts +92 -2
- package/dist/esm/contracts/api-v2.types.d.ts.map +1 -1
- package/dist/esm/contracts/store.d.ts +37 -0
- package/dist/esm/contracts/store.d.ts.map +1 -1
- package/dist/esm/mcp/index.js +8 -2
- package/dist/esm/mcp/index.js.map +1 -1
- package/dist/esm/mcp/tools/memory.d.ts.map +1 -1
- package/dist/esm/mcp/tools/memory.js +74 -4
- package/dist/esm/mcp/tools/memory.js.map +1 -1
- package/dist/esm/mcp/tools/misc.d.ts.map +1 -1
- package/dist/esm/mcp/tools/misc.js +2 -1
- package/dist/esm/mcp/tools/misc.js.map +1 -1
- package/dist/esm/mcp/tools/workspace.d.ts.map +1 -1
- package/dist/esm/mcp/tools/workspace.js +4 -1
- package/dist/esm/mcp/tools/workspace.js.map +1 -1
- package/dist/esm/mcp/tools.d.ts +10 -0
- package/dist/esm/mcp/tools.d.ts.map +1 -1
- package/dist/esm/mcp/tools.js +46 -12
- package/dist/esm/mcp/tools.js.map +1 -1
- package/dist/esm/proxy/KeyManager.d.ts.map +1 -1
- package/dist/esm/proxy/KeyManager.js +5 -0
- package/dist/esm/proxy/KeyManager.js.map +1 -1
- package/dist/esm/subconscious/CloudBrain.d.ts +77 -0
- package/dist/esm/subconscious/CloudBrain.d.ts.map +1 -0
- package/dist/esm/subconscious/CloudBrain.js +330 -0
- package/dist/esm/subconscious/CloudBrain.js.map +1 -0
- package/dist/esm/subconscious/HostRecall.d.ts.map +1 -1
- package/dist/esm/subconscious/HostRecall.js +11 -4
- package/dist/esm/subconscious/HostRecall.js.map +1 -1
- package/dist/esm/subconscious/ProjectIdentity.d.ts +9 -0
- package/dist/esm/subconscious/ProjectIdentity.d.ts.map +1 -0
- package/dist/esm/subconscious/ProjectIdentity.js +56 -0
- package/dist/esm/subconscious/ProjectIdentity.js.map +1 -0
- package/dist/esm/subconscious/TeamBrain.d.ts +9 -3
- package/dist/esm/subconscious/TeamBrain.d.ts.map +1 -1
- package/dist/esm/subconscious/TeamBrain.js +39 -7
- package/dist/esm/subconscious/TeamBrain.js.map +1 -1
- package/dist/esm/utils/FixCapture.d.ts +7 -5
- package/dist/esm/utils/FixCapture.d.ts.map +1 -1
- package/dist/esm/utils/FixCapture.js +64 -33
- package/dist/esm/utils/FixCapture.js.map +1 -1
- package/dist/esm/utils/NoTerminal.d.ts +27 -0
- package/dist/esm/utils/NoTerminal.d.ts.map +1 -0
- package/dist/esm/utils/NoTerminal.js +33 -0
- package/dist/esm/utils/NoTerminal.js.map +1 -0
- package/dist/esm/utils/OpenCodeSession.d.ts +70 -0
- package/dist/esm/utils/OpenCodeSession.d.ts.map +1 -0
- package/dist/esm/utils/OpenCodeSession.js +146 -0
- package/dist/esm/utils/OpenCodeSession.js.map +1 -0
- package/dist/esm/utils/ProLicense.d.ts.map +1 -1
- package/dist/esm/utils/ProLicense.js +11 -3
- package/dist/esm/utils/ProLicense.js.map +1 -1
- package/dist/esm/utils/SessionCapture.d.ts +31 -7
- package/dist/esm/utils/SessionCapture.d.ts.map +1 -1
- package/dist/esm/utils/SessionCapture.js +185 -32
- package/dist/esm/utils/SessionCapture.js.map +1 -1
- package/dist/esm/utils/StopNudge.d.ts +8 -0
- package/dist/esm/utils/StopNudge.d.ts.map +1 -0
- package/dist/esm/utils/StopNudge.js +86 -0
- package/dist/esm/utils/StopNudge.js.map +1 -0
- package/dist/esm/utils/TestAutofixInterceptor.d.ts.map +1 -1
- package/dist/esm/utils/TestAutofixInterceptor.js +2 -0
- package/dist/esm/utils/TestAutofixInterceptor.js.map +1 -1
- package/lemma-proxy.cjs +5 -0
- package/package.json +2 -1
- package/sdks/crewai/dist/ts/src/client.d.ts +5 -1
- package/sdks/crewai/dist/ts/src/client.js +8 -0
- package/sdks/crewai/dist/ts/src/types.d.ts +32 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { CreateMemoryRequest, CreateMemoryResponse, EntitlementResponse, ForgetResponse, RecallRequest, RecallResponse, UsageResponse, VerifyRequest, VerifyResponse } from '../contracts/api-v2.types';
|
|
2
|
+
export interface CloudConfig {
|
|
3
|
+
/** Origin + path prefix ending in /v2, no trailing slash. */
|
|
4
|
+
baseUrl: string;
|
|
5
|
+
apiKey: string;
|
|
6
|
+
timeoutMs: number;
|
|
7
|
+
/** Where the pair came from. The URL and the key always come from the SAME source. */
|
|
8
|
+
source?: 'env' | 'file';
|
|
9
|
+
/** Only meaningful for 'file': what `lemma cloud login` recorded about sharing. */
|
|
10
|
+
autoshare?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export type CloudConfigStatus = {
|
|
13
|
+
config: CloudConfig;
|
|
14
|
+
}
|
|
15
|
+
/** `problem` is null when Cloud is simply not configured, and a sentence when it is configured wrongly. */
|
|
16
|
+
| {
|
|
17
|
+
config: null;
|
|
18
|
+
problem: string | null;
|
|
19
|
+
};
|
|
20
|
+
export declare const DEFAULT_TIMEOUT_MS = 4000;
|
|
21
|
+
export declare function cloudConfigStatus(env?: NodeJS.ProcessEnv): CloudConfigStatus;
|
|
22
|
+
/**
|
|
23
|
+
* Whether stores are shared without being asked. An explicit LEMMA_CLOUD_AUTOSHARE wins ('1' on,
|
|
24
|
+
* '0' off); otherwise it follows what `lemma cloud login` recorded for the saved connection.
|
|
25
|
+
* Lives here, not in the Brain module, so the CLI can answer it without loading the Brain.
|
|
26
|
+
*/
|
|
27
|
+
export declare function autoShareFor(status: CloudConfigStatus, env?: NodeJS.ProcessEnv): boolean;
|
|
28
|
+
export declare class CloudError extends Error {
|
|
29
|
+
/** HTTP status, or 0 when no response arrived (network, timeout). */
|
|
30
|
+
readonly status: number;
|
|
31
|
+
readonly code: string;
|
|
32
|
+
constructor(
|
|
33
|
+
/** HTTP status, or 0 when no response arrived (network, timeout). */
|
|
34
|
+
status: number, code: string, message: string);
|
|
35
|
+
}
|
|
36
|
+
export declare class CloudBrainClient {
|
|
37
|
+
private readonly config;
|
|
38
|
+
private readonly fetchImpl;
|
|
39
|
+
constructor(config: CloudConfig, fetchImpl?: typeof fetch);
|
|
40
|
+
remember(request: CreateMemoryRequest): Promise<CreateMemoryResponse>;
|
|
41
|
+
recall(request: RecallRequest): Promise<RecallResponse>;
|
|
42
|
+
verify(request: VerifyRequest): Promise<VerifyResponse>;
|
|
43
|
+
/** Cheapest authenticated call: the "is this key good and is the server there" check. */
|
|
44
|
+
usage(): Promise<UsageResponse>;
|
|
45
|
+
/** What this key's plan includes. A server from before the endpoint existed answers 404. */
|
|
46
|
+
entitlement(): Promise<EntitlementResponse>;
|
|
47
|
+
forget(id: string): Promise<ForgetResponse>;
|
|
48
|
+
private call;
|
|
49
|
+
}
|
|
50
|
+
/** A CloudError (or any error) as one short line for a tool reply, with no URL and no key. */
|
|
51
|
+
export declare function describeCloudFailure(err: unknown): string;
|
|
52
|
+
//# sourceMappingURL=CloudBrainClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CloudBrainClient.d.ts","sourceRoot":"","sources":["../../../src/cloud/CloudBrainClient.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,cAAc,EACd,aAAa,EACb,aAAa,EACb,cAAc,EACf,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,WAAW;IAC1B,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,sFAAsF;IACtF,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxB,mFAAmF;IACnF,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE;AACzB,2GAA2G;GACzG;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAI7C,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,iBAAiB,CAmBzF;AAuBD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,iBAAiB,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAKrG;AAED,qBAAa,UAAW,SAAQ,KAAK;IAEjC,qEAAqE;IACrE,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM;;IAFrB,qEAAqE;IAC5D,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM;CAKlB;AAED,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBADT,MAAM,EAAE,WAAW,EACnB,SAAS,GAAE,OAAO,KAAa;IAGlD,QAAQ,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAIrE,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;IAIvD,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;IAIvD,yFAAyF;IACzF,KAAK,IAAI,OAAO,CAAC,aAAa,CAAC;IAI/B,4FAA4F;IAC5F,WAAW,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAI3C,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;YAI7B,IAAI;CAgCnB;AAED,8FAA8F;AAC9F,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAOzD"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CloudBrainClient = exports.CloudError = exports.DEFAULT_TIMEOUT_MS = void 0;
|
|
4
|
+
exports.cloudConfigStatus = cloudConfigStatus;
|
|
5
|
+
exports.autoShareFor = autoShareFor;
|
|
6
|
+
exports.describeCloudFailure = describeCloudFailure;
|
|
7
|
+
/**
|
|
8
|
+
* Lemma Cloud — the MCP's client for the /v2 API.
|
|
9
|
+
*
|
|
10
|
+
* Deliberately small and unforgiving about what it may do to the caller: every request has a
|
|
11
|
+
* hard timeout, nothing is retried (a slow Cloud must never make a local memory call slow), and
|
|
12
|
+
* a failure surfaces as a CloudError the caller can turn into one line of text. The API key is
|
|
13
|
+
* read from the environment and only ever placed in the Authorization header: it is never
|
|
14
|
+
* logged, never part of an error message, and never sent over plain http to a non-local host.
|
|
15
|
+
*/
|
|
16
|
+
const CloudConfig_1 = require("./CloudConfig");
|
|
17
|
+
const KEY_SHAPE = /^lk_(live|test)_[0-9a-f]{32,64}$/;
|
|
18
|
+
const LOCAL_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]']);
|
|
19
|
+
exports.DEFAULT_TIMEOUT_MS = 4000;
|
|
20
|
+
function cloudConfigStatus(env = process.env) {
|
|
21
|
+
const envUrl = env.LEMMA_CLOUD_URL?.trim();
|
|
22
|
+
const envKey = env.LEMMA_CLOUD_KEY?.trim();
|
|
23
|
+
if (!envUrl && !envKey) {
|
|
24
|
+
// Nothing in the environment: use what `lemma cloud login` saved. The pair is taken whole
|
|
25
|
+
// from the file, so a key can never be sent to a URL it was not issued for.
|
|
26
|
+
const saved = (0, CloudConfig_1.readUserConfig)(env);
|
|
27
|
+
if (!saved.found)
|
|
28
|
+
return { config: null, problem: null };
|
|
29
|
+
if ('problem' in saved)
|
|
30
|
+
return { config: null, problem: saved.problem };
|
|
31
|
+
const checked = validate(saved.config.url, saved.config.key, env, { url: 'the saved Cloud URL', key: 'the saved Cloud key' });
|
|
32
|
+
return checked.config
|
|
33
|
+
? { config: { ...checked.config, source: 'file', autoshare: saved.config.autoshare } }
|
|
34
|
+
: checked;
|
|
35
|
+
}
|
|
36
|
+
if (!envUrl)
|
|
37
|
+
return { config: null, problem: 'LEMMA_CLOUD_KEY is set but LEMMA_CLOUD_URL is not.' };
|
|
38
|
+
if (!envKey)
|
|
39
|
+
return { config: null, problem: 'LEMMA_CLOUD_URL is set but LEMMA_CLOUD_KEY is not.' };
|
|
40
|
+
const checked = validate(envUrl, envKey, env, { url: 'LEMMA_CLOUD_URL', key: 'LEMMA_CLOUD_KEY' });
|
|
41
|
+
return checked.config ? { config: { ...checked.config, source: 'env' } } : checked;
|
|
42
|
+
}
|
|
43
|
+
function validate(rawUrl, apiKey, env, name) {
|
|
44
|
+
if (!KEY_SHAPE.test(apiKey))
|
|
45
|
+
return { config: null, problem: `${name.key} is not a Lemma API key (expected lk_live_… or lk_test_…).` };
|
|
46
|
+
let url;
|
|
47
|
+
try {
|
|
48
|
+
url = new URL(rawUrl);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return { config: null, problem: `${name.url} is not a valid URL.` };
|
|
52
|
+
}
|
|
53
|
+
const local = LOCAL_HOSTS.has(url.hostname);
|
|
54
|
+
if (url.protocol !== 'https:' && !(url.protocol === 'http:' && local)) {
|
|
55
|
+
return { config: null, problem: `${name.url} must be https (plain http is only allowed for localhost).` };
|
|
56
|
+
}
|
|
57
|
+
if (url.username || url.password)
|
|
58
|
+
return { config: null, problem: `${name.url} must not contain credentials.` };
|
|
59
|
+
const prefix = url.pathname.replace(/\/+$/, '').replace(/\/v2$/, '');
|
|
60
|
+
const asked = Number(env.LEMMA_CLOUD_TIMEOUT_MS);
|
|
61
|
+
const timeoutMs = Number.isFinite(asked) && asked >= 500 && asked <= 30000 ? Math.floor(asked) : exports.DEFAULT_TIMEOUT_MS;
|
|
62
|
+
return { config: { baseUrl: `${url.origin}${prefix}/v2`, apiKey, timeoutMs } };
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Whether stores are shared without being asked. An explicit LEMMA_CLOUD_AUTOSHARE wins ('1' on,
|
|
66
|
+
* '0' off); otherwise it follows what `lemma cloud login` recorded for the saved connection.
|
|
67
|
+
* Lives here, not in the Brain module, so the CLI can answer it without loading the Brain.
|
|
68
|
+
*/
|
|
69
|
+
function autoShareFor(status, env = process.env) {
|
|
70
|
+
if (!status.config)
|
|
71
|
+
return false;
|
|
72
|
+
if (env.LEMMA_CLOUD_AUTOSHARE === '1')
|
|
73
|
+
return true;
|
|
74
|
+
if (env.LEMMA_CLOUD_AUTOSHARE === '0')
|
|
75
|
+
return false;
|
|
76
|
+
return status.config.source === 'file' && status.config.autoshare === true;
|
|
77
|
+
}
|
|
78
|
+
class CloudError extends Error {
|
|
79
|
+
constructor(
|
|
80
|
+
/** HTTP status, or 0 when no response arrived (network, timeout). */
|
|
81
|
+
status, code, message) {
|
|
82
|
+
super(message);
|
|
83
|
+
this.status = status;
|
|
84
|
+
this.code = code;
|
|
85
|
+
this.name = 'CloudError';
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
exports.CloudError = CloudError;
|
|
89
|
+
class CloudBrainClient {
|
|
90
|
+
constructor(config, fetchImpl = fetch) {
|
|
91
|
+
this.config = config;
|
|
92
|
+
this.fetchImpl = fetchImpl;
|
|
93
|
+
}
|
|
94
|
+
remember(request) {
|
|
95
|
+
return this.call('POST', '/memories', request);
|
|
96
|
+
}
|
|
97
|
+
recall(request) {
|
|
98
|
+
return this.call('POST', '/recall', request);
|
|
99
|
+
}
|
|
100
|
+
verify(request) {
|
|
101
|
+
return this.call('POST', '/verify', request);
|
|
102
|
+
}
|
|
103
|
+
/** Cheapest authenticated call: the "is this key good and is the server there" check. */
|
|
104
|
+
usage() {
|
|
105
|
+
return this.call('GET', '/usage');
|
|
106
|
+
}
|
|
107
|
+
/** What this key's plan includes. A server from before the endpoint existed answers 404. */
|
|
108
|
+
entitlement() {
|
|
109
|
+
return this.call('GET', '/entitlement');
|
|
110
|
+
}
|
|
111
|
+
forget(id) {
|
|
112
|
+
return this.call('DELETE', `/memories/${encodeURIComponent(id)}`);
|
|
113
|
+
}
|
|
114
|
+
async call(method, path, body) {
|
|
115
|
+
const controller = new AbortController();
|
|
116
|
+
const timer = setTimeout(() => controller.abort(), this.config.timeoutMs);
|
|
117
|
+
let res;
|
|
118
|
+
try {
|
|
119
|
+
res = await this.fetchImpl(this.config.baseUrl + path, {
|
|
120
|
+
method,
|
|
121
|
+
headers: { Authorization: `Bearer ${this.config.apiKey}`, 'Content-Type': 'application/json' },
|
|
122
|
+
body: body === undefined ? undefined : JSON.stringify(body),
|
|
123
|
+
signal: controller.signal,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
const aborted = err?.name === 'AbortError';
|
|
128
|
+
// Not err.message: a network error's text can quote the URL, and nothing here should echo config.
|
|
129
|
+
throw new CloudError(0, aborted ? 'timeout' : 'network', aborted ? `no answer within ${this.config.timeoutMs} ms` : 'could not reach Lemma Cloud');
|
|
130
|
+
}
|
|
131
|
+
finally {
|
|
132
|
+
clearTimeout(timer);
|
|
133
|
+
}
|
|
134
|
+
let json = null;
|
|
135
|
+
try {
|
|
136
|
+
json = await res.json();
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
/* an error page or an empty body */
|
|
140
|
+
}
|
|
141
|
+
if (!res.ok) {
|
|
142
|
+
const code = typeof json?.error?.code === 'string' ? json.error.code : `http_${res.status}`;
|
|
143
|
+
const message = typeof json?.error?.message === 'string' ? json.error.message : `HTTP ${res.status}`;
|
|
144
|
+
throw new CloudError(res.status, code, message);
|
|
145
|
+
}
|
|
146
|
+
return json;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
exports.CloudBrainClient = CloudBrainClient;
|
|
150
|
+
/** A CloudError (or any error) as one short line for a tool reply, with no URL and no key. */
|
|
151
|
+
function describeCloudFailure(err) {
|
|
152
|
+
if (err instanceof CloudError) {
|
|
153
|
+
if (err.status === 401)
|
|
154
|
+
return 'the Cloud API key was rejected (revoked or wrong)';
|
|
155
|
+
if (err.status === 429)
|
|
156
|
+
return `Cloud limit reached (${err.message})`;
|
|
157
|
+
return err.status === 0 ? err.message : `${err.code}: ${err.message}`;
|
|
158
|
+
}
|
|
159
|
+
return 'unexpected error talking to Lemma Cloud';
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=CloudBrainClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CloudBrainClient.js","sourceRoot":"","sources":["../../../src/cloud/CloudBrainClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface UserCloudConfig {
|
|
2
|
+
url: string;
|
|
3
|
+
key: string;
|
|
4
|
+
/** Share every stored memory with the team without being asked. */
|
|
5
|
+
autoshare: boolean;
|
|
6
|
+
}
|
|
7
|
+
export type UserConfigRead = {
|
|
8
|
+
found: false;
|
|
9
|
+
} | {
|
|
10
|
+
found: true;
|
|
11
|
+
config: UserCloudConfig;
|
|
12
|
+
} | {
|
|
13
|
+
found: true;
|
|
14
|
+
problem: string;
|
|
15
|
+
};
|
|
16
|
+
export declare const MARKER_FILE = ".lemma-cloud.json";
|
|
17
|
+
export declare function userConfigPath(env?: NodeJS.ProcessEnv): string;
|
|
18
|
+
export declare function readUserConfig(env?: NodeJS.ProcessEnv): UserConfigRead;
|
|
19
|
+
/** Atomic write, owner-only. Never leaves a half-written or world-readable credential behind. */
|
|
20
|
+
export declare function writeUserConfig(config: UserCloudConfig, env?: NodeJS.ProcessEnv): string;
|
|
21
|
+
/** True when a config existed and was removed. */
|
|
22
|
+
export declare function removeUserConfig(env?: NodeJS.ProcessEnv): boolean;
|
|
23
|
+
export interface CloudMarker {
|
|
24
|
+
url: string;
|
|
25
|
+
}
|
|
26
|
+
export declare function markerPath(root: string): string;
|
|
27
|
+
export declare function readMarker(root: string): CloudMarker | null;
|
|
28
|
+
/**
|
|
29
|
+
* The marker of the repo `start` lives in: the nearest one going up, stopping at the repo root (the
|
|
30
|
+
* first directory with a .git) or the filesystem root. Plain file reads, no subprocess: this runs on
|
|
31
|
+
* every search_memory for every user, Cloud or not, and spawning `git rev-parse` there cost ~9 ms a call.
|
|
32
|
+
*/
|
|
33
|
+
export declare function findMarker(start: string): CloudMarker | null;
|
|
34
|
+
export declare function writeMarker(root: string, url: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* The host of a marker URL, safe to print into the agent's context. The marker is repo content
|
|
37
|
+
* anybody can edit, so only a validated host ever reaches a tool reply: no free text, no path,
|
|
38
|
+
* no control characters.
|
|
39
|
+
*/
|
|
40
|
+
export declare function markerHost(marker: CloudMarker): string;
|
|
41
|
+
//# sourceMappingURL=CloudConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CloudConfig.d.ts","sourceRoot":"","sources":["../../../src/cloud/CloudConfig.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,mEAAmE;IACnE,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,KAAK,EAAE,KAAK,CAAA;CAAE,GAChB;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,eAAe,CAAA;CAAE,GACxC;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAErC,eAAO,MAAM,WAAW,sBAAsB,CAAC;AAE/C,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAG3E;AAED,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,cAAc,CAsBnF;AAED,iGAAiG;AACjG,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAQrG;AAED,kDAAkD;AAClD,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAO9E;AAID,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAW3D;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAW5D;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAI7D;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAEtD"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MARKER_FILE = void 0;
|
|
7
|
+
exports.userConfigPath = userConfigPath;
|
|
8
|
+
exports.readUserConfig = readUserConfig;
|
|
9
|
+
exports.writeUserConfig = writeUserConfig;
|
|
10
|
+
exports.removeUserConfig = removeUserConfig;
|
|
11
|
+
exports.markerPath = markerPath;
|
|
12
|
+
exports.readMarker = readMarker;
|
|
13
|
+
exports.findMarker = findMarker;
|
|
14
|
+
exports.writeMarker = writeMarker;
|
|
15
|
+
exports.markerHost = markerHost;
|
|
16
|
+
/**
|
|
17
|
+
* Lemma Cloud — where a dev's connection settings live.
|
|
18
|
+
*
|
|
19
|
+
* ~/.lemma/cloud.json personal, 0600: { url, key, autoshare }. Written by `lemma cloud login`.
|
|
20
|
+
* <repo>/.lemma-cloud.json committed, NO secret: { url }. Written by `lemma cloud link`.
|
|
21
|
+
*
|
|
22
|
+
* The two are deliberately not interchangeable. The key in the personal file is bound to the URL
|
|
23
|
+
* it was issued for and is only ever sent there. The repo marker is untrusted input (anyone who
|
|
24
|
+
* can push to the repo controls it), so it may suggest a default for `login` and trigger a hint,
|
|
25
|
+
* but it never decides where a key is sent: otherwise a hostile repo would point the URL at its
|
|
26
|
+
* own server and collect the key of every dev who opens it.
|
|
27
|
+
*/
|
|
28
|
+
const fs_1 = __importDefault(require("fs"));
|
|
29
|
+
const os_1 = __importDefault(require("os"));
|
|
30
|
+
const path_1 = __importDefault(require("path"));
|
|
31
|
+
exports.MARKER_FILE = '.lemma-cloud.json';
|
|
32
|
+
function userConfigPath(env = process.env) {
|
|
33
|
+
const override = env.LEMMA_CLOUD_CONFIG?.trim();
|
|
34
|
+
return override || path_1.default.join(os_1.default.homedir(), '.lemma', 'cloud.json');
|
|
35
|
+
}
|
|
36
|
+
function readUserConfig(env = process.env) {
|
|
37
|
+
const file = userConfigPath(env);
|
|
38
|
+
let stat;
|
|
39
|
+
try {
|
|
40
|
+
stat = fs_1.default.statSync(file);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return { found: false };
|
|
44
|
+
}
|
|
45
|
+
// The file holds a credential: if other users on this machine can read it, refuse to use it
|
|
46
|
+
// and say how to fix it, rather than quietly sending a key that is already exposed.
|
|
47
|
+
if (process.platform !== 'win32' && (stat.mode & 0o077) !== 0) {
|
|
48
|
+
return { found: true, problem: `${file} is readable by other users: run chmod 600 on it (or \`lemma cloud login\` again)` };
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
const parsed = JSON.parse(fs_1.default.readFileSync(file, 'utf8'));
|
|
52
|
+
if (typeof parsed?.url !== 'string' || typeof parsed?.key !== 'string' || !parsed.url || !parsed.key) {
|
|
53
|
+
return { found: true, problem: `${file} is missing "url" or "key": run \`lemma cloud login\`` };
|
|
54
|
+
}
|
|
55
|
+
return { found: true, config: { url: parsed.url, key: parsed.key, autoshare: parsed.autoshare === true } };
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return { found: true, problem: `${file} is not valid JSON: run \`lemma cloud login\`` };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** Atomic write, owner-only. Never leaves a half-written or world-readable credential behind. */
|
|
62
|
+
function writeUserConfig(config, env = process.env) {
|
|
63
|
+
const file = userConfigPath(env);
|
|
64
|
+
fs_1.default.mkdirSync(path_1.default.dirname(file), { recursive: true, mode: 0o700 });
|
|
65
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
66
|
+
fs_1.default.writeFileSync(tmp, JSON.stringify(config, null, 2) + '\n', { mode: 0o600 });
|
|
67
|
+
fs_1.default.chmodSync(tmp, 0o600); // the umask can only have removed bits, but be explicit
|
|
68
|
+
fs_1.default.renameSync(tmp, file);
|
|
69
|
+
return file;
|
|
70
|
+
}
|
|
71
|
+
/** True when a config existed and was removed. */
|
|
72
|
+
function removeUserConfig(env = process.env) {
|
|
73
|
+
try {
|
|
74
|
+
fs_1.default.unlinkSync(userConfigPath(env));
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function markerPath(root) {
|
|
82
|
+
return path_1.default.join(root, exports.MARKER_FILE);
|
|
83
|
+
}
|
|
84
|
+
function readMarker(root) {
|
|
85
|
+
try {
|
|
86
|
+
const parsed = JSON.parse(fs_1.default.readFileSync(markerPath(root), 'utf8'));
|
|
87
|
+
if (typeof parsed?.url !== 'string')
|
|
88
|
+
return null;
|
|
89
|
+
const u = new URL(parsed.url);
|
|
90
|
+
if (u.protocol !== 'https:' && !(u.protocol === 'http:' && ['localhost', '127.0.0.1', '[::1]'].includes(u.hostname)))
|
|
91
|
+
return null;
|
|
92
|
+
if (u.username || u.password)
|
|
93
|
+
return null;
|
|
94
|
+
return { url: u.origin + u.pathname.replace(/\/+$/, '') };
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The marker of the repo `start` lives in: the nearest one going up, stopping at the repo root (the
|
|
102
|
+
* first directory with a .git) or the filesystem root. Plain file reads, no subprocess: this runs on
|
|
103
|
+
* every search_memory for every user, Cloud or not, and spawning `git rev-parse` there cost ~9 ms a call.
|
|
104
|
+
*/
|
|
105
|
+
function findMarker(start) {
|
|
106
|
+
let dir = path_1.default.resolve(start);
|
|
107
|
+
for (let depth = 0; depth < 64; depth++) {
|
|
108
|
+
const marker = readMarker(dir);
|
|
109
|
+
if (marker)
|
|
110
|
+
return marker;
|
|
111
|
+
if (fs_1.default.existsSync(path_1.default.join(dir, '.git')))
|
|
112
|
+
return null;
|
|
113
|
+
const parent = path_1.default.dirname(dir);
|
|
114
|
+
if (parent === dir)
|
|
115
|
+
return null;
|
|
116
|
+
dir = parent;
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
function writeMarker(root, url) {
|
|
121
|
+
const file = markerPath(root);
|
|
122
|
+
fs_1.default.writeFileSync(file, JSON.stringify({ url }, null, 2) + '\n', 'utf8');
|
|
123
|
+
return file;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* The host of a marker URL, safe to print into the agent's context. The marker is repo content
|
|
127
|
+
* anybody can edit, so only a validated host ever reaches a tool reply: no free text, no path,
|
|
128
|
+
* no control characters.
|
|
129
|
+
*/
|
|
130
|
+
function markerHost(marker) {
|
|
131
|
+
return new URL(marker.url).host.replace(/[^a-zA-Z0-9.:\-[\]]/g, '');
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=CloudConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CloudConfig.js","sourceRoot":"","sources":["../../../src/cloud/CloudConfig.ts"],"names":[],"mappings":";;;;;;AA8BA,wCAGC;AAED,wCAsBC;AAGD,0CAQC;AAGD,4CAOC;AAQD,gCAEC;AAED,gCAWC;AAOD,gCAWC;AAED,kCAIC;AAOD,gCAEC;AAtID;;;;;;;;;;;GAWG;AACH,4CAAoB;AACpB,4CAAoB;AACpB,gDAAwB;AAcX,QAAA,WAAW,GAAG,mBAAmB,CAAC;AAE/C,SAAgB,cAAc,CAAC,MAAyB,OAAO,CAAC,GAAG;IACjE,MAAM,QAAQ,GAAG,GAAG,CAAC,kBAAkB,EAAE,IAAI,EAAE,CAAC;IAChD,OAAO,QAAQ,IAAI,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;AACrE,CAAC;AAED,SAAgB,cAAc,CAAC,MAAyB,OAAO,CAAC,GAAG;IACjE,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,IAAc,CAAC;IACnB,IAAI,CAAC;QACH,IAAI,GAAG,YAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC1B,CAAC;IACD,4FAA4F;IAC5F,oFAAoF;IACpF,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9D,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,mFAAmF,EAAE,CAAC;IAC9H,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QACzD,IAAI,OAAO,MAAM,EAAE,GAAG,KAAK,QAAQ,IAAI,OAAO,MAAM,EAAE,GAAG,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;YACrG,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,uDAAuD,EAAE,CAAC;QAClG,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,KAAK,IAAI,EAAE,EAAE,CAAC;IAC7G,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,+CAA+C,EAAE,CAAC;IAC1F,CAAC;AACH,CAAC;AAED,iGAAiG;AACjG,SAAgB,eAAe,CAAC,MAAuB,EAAE,MAAyB,OAAO,CAAC,GAAG;IAC3F,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACjC,YAAE,CAAC,SAAS,CAAC,cAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACnE,MAAM,GAAG,GAAG,GAAG,IAAI,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC;IACzC,YAAE,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/E,YAAE,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,wDAAwD;IAClF,YAAE,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACzB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,kDAAkD;AAClD,SAAgB,gBAAgB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACnE,IAAI,CAAC;QACH,YAAE,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAQD,SAAgB,UAAU,CAAC,IAAY;IACrC,OAAO,cAAI,CAAC,IAAI,CAAC,IAAI,EAAE,mBAAW,CAAC,CAAC;AACtC,CAAC;AAED,SAAgB,UAAU,CAAC,IAAY;IACrC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAE,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QACrE,IAAI,OAAO,MAAM,EAAE,GAAG,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QACjD,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QAClI,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC1C,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAgB,UAAU,CAAC,KAAa;IACtC,IAAI,GAAG,GAAG,cAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAC1B,IAAI,YAAE,CAAC,UAAU,CAAC,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QACvD,MAAM,MAAM,GAAG,cAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QAChC,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAgB,WAAW,CAAC,IAAY,EAAE,GAAW;IACnD,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC9B,YAAE,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;IACxE,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,SAAgB,UAAU,CAAC,MAAmB;IAC5C,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,sBAAsB,EAAE,EAAE,CAAC,CAAC;AACtE,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type CloudConfig } from './CloudBrainClient';
|
|
2
|
+
import type { EntitlementResponse } from '../contracts/api-v2.types';
|
|
3
|
+
/** How long the last answer keeps working when the server cannot be reached. */
|
|
4
|
+
export declare const GRACE_MS: number;
|
|
5
|
+
/** An answer older than this is asked for again. */
|
|
6
|
+
export declare const REFRESH_AFTER_MS: number;
|
|
7
|
+
export interface StoredEntitlement {
|
|
8
|
+
v: 1;
|
|
9
|
+
/** Which connection (URL + key) this answer is for. */
|
|
10
|
+
binding: string;
|
|
11
|
+
plan: string;
|
|
12
|
+
includesPro: boolean;
|
|
13
|
+
/** The server answered 401: the seat was taken away. */
|
|
14
|
+
revoked: boolean;
|
|
15
|
+
checkedAt: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function entitlementPath(env?: NodeJS.ProcessEnv): string;
|
|
18
|
+
/** A short fingerprint of the connection. Not the server's key hash: it is salted with the URL. */
|
|
19
|
+
export declare function bindingFor(config: Pick<CloudConfig, 'baseUrl' | 'apiKey'>): string;
|
|
20
|
+
export declare function readStored(env?: NodeJS.ProcessEnv): StoredEntitlement | null;
|
|
21
|
+
/** For tests: forget the one-second memo of {@link cloudGrantsPro}. */
|
|
22
|
+
export declare function resetEntitlementMemo(): void;
|
|
23
|
+
/**
|
|
24
|
+
* Whether the connection this machine is logged in with currently carries Pro. Synchronous, no
|
|
25
|
+
* network, false whenever anything is missing or does not match.
|
|
26
|
+
*/
|
|
27
|
+
export declare function cloudGrantsPro(env?: NodeJS.ProcessEnv, now?: number): boolean;
|
|
28
|
+
/** Keep the server's answer for this connection. */
|
|
29
|
+
export declare function recordEntitlement(config: Pick<CloudConfig, 'baseUrl' | 'apiKey'>, answer: EntitlementResponse, env?: NodeJS.ProcessEnv, now?: number): void;
|
|
30
|
+
/** Forget the entitlement (logout). True when there was one. */
|
|
31
|
+
export declare function clearEntitlement(env?: NodeJS.ProcessEnv): boolean;
|
|
32
|
+
export type RefreshState =
|
|
33
|
+
/** The server says this seat includes Pro. */
|
|
34
|
+
'granted'
|
|
35
|
+
/** The server knows the key and the plan does not include Pro (free). */
|
|
36
|
+
| 'not-included'
|
|
37
|
+
/** The server rejected the key (401): the seat is gone, Pro from Cloud is off now. */
|
|
38
|
+
| 'revoked'
|
|
39
|
+
/** An older server without the endpoint (404): nothing is recorded or changed. */
|
|
40
|
+
| 'unsupported'
|
|
41
|
+
/** No usable answer (network, timeout, 5xx, 429, unreadable body): the last answer stands until the grace runs out. */
|
|
42
|
+
| 'unreachable';
|
|
43
|
+
export interface RefreshResult {
|
|
44
|
+
state: RefreshState;
|
|
45
|
+
plan?: string;
|
|
46
|
+
}
|
|
47
|
+
/** Ask the server and record what it says. Never throws. */
|
|
48
|
+
export declare function refreshEntitlement(config: CloudConfig, env?: NodeJS.ProcessEnv, fetchImpl?: typeof fetch, now?: number): Promise<RefreshResult>;
|
|
49
|
+
/**
|
|
50
|
+
* For the long-lived MCP server: refresh when the saved answer is missing or older than an hour,
|
|
51
|
+
* and look again every half hour. Does nothing, and costs nothing, while Cloud is not configured.
|
|
52
|
+
* The timer is unref'd so it never keeps a process alive. Returns a function that stops it.
|
|
53
|
+
*/
|
|
54
|
+
export declare function startEntitlementRefresh(env?: NodeJS.ProcessEnv, fetchImpl?: typeof fetch): () => void;
|
|
55
|
+
//# sourceMappingURL=CloudEntitlement.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CloudEntitlement.d.ts","sourceRoot":"","sources":["../../../src/cloud/CloudEntitlement.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAmD,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEvG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAErE,gFAAgF;AAChF,eAAO,MAAM,QAAQ,QAA0B,CAAC;AAChD,oDAAoD;AACpD,eAAO,MAAM,gBAAgB,QAAiB,CAAC;AAS/C,MAAM,WAAW,iBAAiB;IAChC,CAAC,EAAE,CAAC,CAAC;IACL,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,OAAO,CAAC;IACrB,wDAAwD;IACxD,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAE5E;AAED,mGAAmG;AACnG,wBAAgB,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,QAAQ,CAAC,GAAG,MAAM,CAElF;AAED,wBAAgB,UAAU,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,iBAAiB,GAAG,IAAI,CAkBzF;AAYD,uEAAuE;AACvE,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,EAAE,GAAG,GAAE,MAAmB,GAAG,OAAO,CAMtG;AAYD,oDAAoD;AACpD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,QAAQ,CAAC,EAAE,MAAM,EAAE,mBAAmB,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,EAAE,GAAG,GAAE,MAAmB,GAAG,IAAI,CAEpL;AAED,gEAAgE;AAChE,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAQ9E;AAED,MAAM,MAAM,YAAY;AACtB,8CAA8C;AAC5C,SAAS;AACX,yEAAyE;GACvE,cAAc;AAChB,sFAAsF;GACpF,SAAS;AACX,kFAAkF;GAChF,aAAa;AACf,uHAAuH;GACrH,aAAa,CAAC;AAElB,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,YAAY,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAOD,4DAA4D;AAC5D,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,WAAW,EACnB,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,SAAS,CAAC,EAAE,OAAO,KAAK,EACxB,GAAG,GAAE,MAAmB,GACvB,OAAO,CAAC,aAAa,CAAC,CAgBxB;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,EAAE,SAAS,CAAC,EAAE,OAAO,KAAK,GAAG,MAAM,IAAI,CAYlH"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.REFRESH_AFTER_MS = exports.GRACE_MS = void 0;
|
|
7
|
+
exports.entitlementPath = entitlementPath;
|
|
8
|
+
exports.bindingFor = bindingFor;
|
|
9
|
+
exports.readStored = readStored;
|
|
10
|
+
exports.resetEntitlementMemo = resetEntitlementMemo;
|
|
11
|
+
exports.cloudGrantsPro = cloudGrantsPro;
|
|
12
|
+
exports.recordEntitlement = recordEntitlement;
|
|
13
|
+
exports.clearEntitlement = clearEntitlement;
|
|
14
|
+
exports.refreshEntitlement = refreshEntitlement;
|
|
15
|
+
exports.startEntitlementRefresh = startEntitlementRefresh;
|
|
16
|
+
/**
|
|
17
|
+
* Lemma Cloud — what a seat entitles this machine to.
|
|
18
|
+
*
|
|
19
|
+
* A seat on a paid Cloud plan also unlocks the local Pro tools. The client does not decide that: it
|
|
20
|
+
* asks the server (GET /v2/entitlement) and keeps the last answer in ~/.lemma/cloud-entitlement.json
|
|
21
|
+
* next to the connection it belongs to. The file is only a cache of the server's answer and, like
|
|
22
|
+
* ~/.lemma-cache/license.json, it can be edited by whoever owns the machine; what it adds is that an
|
|
23
|
+
* answer for one connection is never honoured for another.
|
|
24
|
+
*
|
|
25
|
+
* Three rules, each from a way this has gone wrong before:
|
|
26
|
+
* - Only an explicit 401 takes the entitlement away. A timeout, a 5xx, a 429 or a body we cannot
|
|
27
|
+
* read keeps the last answer until it is older than the grace period (a KeyManager that treated
|
|
28
|
+
* "anything but valid" as "cancelled" once deleted a paying user's license).
|
|
29
|
+
* - Reading is synchronous and touches two small files, never the network: the host hooks are
|
|
30
|
+
* short-lived processes with a latency budget. Only the long-lived MCP server refreshes.
|
|
31
|
+
* - The answer is bound to the URL and key it was fetched with, so logging in as someone else, or
|
|
32
|
+
* pointing at another server, starts from "no entitlement" instead of inheriting the old one.
|
|
33
|
+
*/
|
|
34
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
35
|
+
const fs_1 = __importDefault(require("fs"));
|
|
36
|
+
const path_1 = __importDefault(require("path"));
|
|
37
|
+
const CloudBrainClient_1 = require("./CloudBrainClient");
|
|
38
|
+
const CloudConfig_1 = require("./CloudConfig");
|
|
39
|
+
/** How long the last answer keeps working when the server cannot be reached. */
|
|
40
|
+
exports.GRACE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
41
|
+
/** An answer older than this is asked for again. */
|
|
42
|
+
exports.REFRESH_AFTER_MS = 60 * 60 * 1000;
|
|
43
|
+
/** The MCP checks whether a refresh is due this often. */
|
|
44
|
+
const TICK_MS = 30 * 60 * 1000;
|
|
45
|
+
/** A recorded time this far ahead of the clock is not believed. */
|
|
46
|
+
const FUTURE_SKEW_MS = 5 * 60 * 1000;
|
|
47
|
+
/** Tool gates call this on every request; re-reading two files each time buys nothing. */
|
|
48
|
+
const MEMO_MS = 1000;
|
|
49
|
+
const REFRESH_TIMEOUT_MS = 8000;
|
|
50
|
+
function entitlementPath(env = process.env) {
|
|
51
|
+
return path_1.default.join(path_1.default.dirname((0, CloudConfig_1.userConfigPath)(env)), 'cloud-entitlement.json');
|
|
52
|
+
}
|
|
53
|
+
/** A short fingerprint of the connection. Not the server's key hash: it is salted with the URL. */
|
|
54
|
+
function bindingFor(config) {
|
|
55
|
+
return crypto_1.default.createHash('sha256').update(`${config.baseUrl}\n${config.apiKey}`).digest('hex').slice(0, 16);
|
|
56
|
+
}
|
|
57
|
+
function readStored(env = process.env) {
|
|
58
|
+
try {
|
|
59
|
+
const p = JSON.parse(fs_1.default.readFileSync(entitlementPath(env), 'utf8'));
|
|
60
|
+
if (p?.v !== 1 ||
|
|
61
|
+
typeof p.binding !== 'string' ||
|
|
62
|
+
typeof p.plan !== 'string' ||
|
|
63
|
+
typeof p.includesPro !== 'boolean' ||
|
|
64
|
+
typeof p.revoked !== 'boolean' ||
|
|
65
|
+
typeof p.checkedAt !== 'number' ||
|
|
66
|
+
!Number.isFinite(p.checkedAt)) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
return p;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function writeStored(s, env) {
|
|
76
|
+
const file = entitlementPath(env);
|
|
77
|
+
fs_1.default.mkdirSync(path_1.default.dirname(file), { recursive: true, mode: 0o700 });
|
|
78
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
79
|
+
fs_1.default.writeFileSync(tmp, JSON.stringify(s, null, 2) + '\n', { mode: 0o600 });
|
|
80
|
+
fs_1.default.renameSync(tmp, file);
|
|
81
|
+
memo = null;
|
|
82
|
+
}
|
|
83
|
+
let memo = null;
|
|
84
|
+
/** For tests: forget the one-second memo of {@link cloudGrantsPro}. */
|
|
85
|
+
function resetEntitlementMemo() {
|
|
86
|
+
memo = null;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Whether the connection this machine is logged in with currently carries Pro. Synchronous, no
|
|
90
|
+
* network, false whenever anything is missing or does not match.
|
|
91
|
+
*/
|
|
92
|
+
function cloudGrantsPro(env = process.env, now = Date.now()) {
|
|
93
|
+
const useMemo = env === process.env;
|
|
94
|
+
if (useMemo && memo && now - memo.at < MEMO_MS)
|
|
95
|
+
return memo.value;
|
|
96
|
+
const value = compute(env, now);
|
|
97
|
+
if (useMemo)
|
|
98
|
+
memo = { at: now, value };
|
|
99
|
+
return value;
|
|
100
|
+
}
|
|
101
|
+
function compute(env, now) {
|
|
102
|
+
const status = (0, CloudBrainClient_1.cloudConfigStatus)(env);
|
|
103
|
+
if (!status.config)
|
|
104
|
+
return false;
|
|
105
|
+
const s = readStored(env);
|
|
106
|
+
if (!s || s.revoked || !s.includesPro)
|
|
107
|
+
return false;
|
|
108
|
+
if (s.binding !== bindingFor(status.config))
|
|
109
|
+
return false;
|
|
110
|
+
if (s.checkedAt > now + FUTURE_SKEW_MS)
|
|
111
|
+
return false;
|
|
112
|
+
return now - s.checkedAt < exports.GRACE_MS;
|
|
113
|
+
}
|
|
114
|
+
/** Keep the server's answer for this connection. */
|
|
115
|
+
function recordEntitlement(config, answer, env = process.env, now = Date.now()) {
|
|
116
|
+
writeStored({ v: 1, binding: bindingFor(config), plan: answer.plan, includesPro: answer.includesPro, revoked: false, checkedAt: now }, env);
|
|
117
|
+
}
|
|
118
|
+
/** Forget the entitlement (logout). True when there was one. */
|
|
119
|
+
function clearEntitlement(env = process.env) {
|
|
120
|
+
memo = null;
|
|
121
|
+
try {
|
|
122
|
+
fs_1.default.unlinkSync(entitlementPath(env));
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function isAnswer(x) {
|
|
130
|
+
const a = x;
|
|
131
|
+
return !!a && typeof a.plan === 'string' && typeof a.includesPro === 'boolean';
|
|
132
|
+
}
|
|
133
|
+
/** Ask the server and record what it says. Never throws. */
|
|
134
|
+
async function refreshEntitlement(config, env = process.env, fetchImpl, now = Date.now()) {
|
|
135
|
+
try {
|
|
136
|
+
const answer = await new CloudBrainClient_1.CloudBrainClient({ ...config, timeoutMs: Math.max(config.timeoutMs, REFRESH_TIMEOUT_MS) }, fetchImpl).entitlement();
|
|
137
|
+
if (!isAnswer(answer))
|
|
138
|
+
return { state: 'unreachable' };
|
|
139
|
+
recordEntitlement(config, answer, env, now);
|
|
140
|
+
return { state: answer.includesPro ? 'granted' : 'not-included', plan: answer.plan };
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
if (err instanceof CloudBrainClient_1.CloudError) {
|
|
144
|
+
if (err.status === 401) {
|
|
145
|
+
writeStored({ v: 1, binding: bindingFor(config), plan: 'free', includesPro: false, revoked: true, checkedAt: now }, env);
|
|
146
|
+
return { state: 'revoked' };
|
|
147
|
+
}
|
|
148
|
+
if (err.status === 404)
|
|
149
|
+
return { state: 'unsupported' };
|
|
150
|
+
}
|
|
151
|
+
return { state: 'unreachable' };
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* For the long-lived MCP server: refresh when the saved answer is missing or older than an hour,
|
|
156
|
+
* and look again every half hour. Does nothing, and costs nothing, while Cloud is not configured.
|
|
157
|
+
* The timer is unref'd so it never keeps a process alive. Returns a function that stops it.
|
|
158
|
+
*/
|
|
159
|
+
function startEntitlementRefresh(env = process.env, fetchImpl) {
|
|
160
|
+
const tick = () => {
|
|
161
|
+
const status = (0, CloudBrainClient_1.cloudConfigStatus)(env);
|
|
162
|
+
if (!status.config)
|
|
163
|
+
return;
|
|
164
|
+
const s = readStored(env);
|
|
165
|
+
if (s && s.binding === bindingFor(status.config) && Date.now() - s.checkedAt < exports.REFRESH_AFTER_MS)
|
|
166
|
+
return;
|
|
167
|
+
void refreshEntitlement(status.config, env, fetchImpl).catch(() => { });
|
|
168
|
+
};
|
|
169
|
+
tick();
|
|
170
|
+
const timer = setInterval(tick, TICK_MS);
|
|
171
|
+
timer.unref();
|
|
172
|
+
return () => clearInterval(timer);
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=CloudEntitlement.js.map
|