diff --git a/.github/workflows/close-inactive-issues.yml b/.github/workflows/close-inactive-issues.yml new file mode 100644 index 00000000..57b55c50 --- /dev/null +++ b/.github/workflows/close-inactive-issues.yml @@ -0,0 +1,70 @@ +name: Close Inactive Issues +on: + schedule: + - cron: '0 0 * * *' # Run daily at midnight UTC + workflow_dispatch: # Allow manual triggering + +jobs: + close-inactive: + runs-on: ubuntu-latest + permissions: + issues: write + steps: + - name: Close inactive issues + uses: actions/github-script@v7 + with: + script: | + const daysUntilClose = 14 + const warningLabel = 'stale' + const warningMessage = 'This issue has been automatically marked as stale due to inactivity. It will be closed in 3 days if no further activity occurs.' + + const now = new Date() + const timeAgo = new Date(now.getTime() - (daysUntilClose * 24 * 60 * 60 * 1000)) + + const issues = await github.rest.issues.listForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + sort: 'updated', + direction: 'asc' + }) + + for (const issue of issues.data) { + const lastUpdated = new Date(issue.updated_at) + + if (lastUpdated < timeAgo) { + // Check if issue has warning label + if (issue.labels.find(label => label.name === warningLabel)) { + // Close issue + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + state: 'closed', + state_reason: 'not_planned' + }) + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + body: 'This issue has been automatically closed due to inactivity.' + }) + } else { + // Add warning label and comment + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + labels: [warningLabel] + }) + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + body: warningMessage + }) + } + } + } diff --git a/components/shared/vendor-metadata.tsx b/components/shared/vendor-metadata.tsx index 5ef5ee68..948aeba6 100644 --- a/components/shared/vendor-metadata.tsx +++ b/components/shared/vendor-metadata.tsx @@ -367,6 +367,8 @@ export function VendorLogo({ ); } + + if (vendor.includes("xai")) { const color = vendorColor("vercel"); return ( diff --git a/lib/constants.ts b/lib/constants.ts index 0992af3b..58cb57fd 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -146,6 +146,49 @@ export const OPENAI_PRICING: Record = { }; +export const MISTRAL_PRICING: Record = { + "mistral-large-latest": { + input: 0.002, + output: 0.006, + }, + "pixtral-large-latest": { + input: 0.002, + output: 0.006, + }, + "mistral-small-latest": { + input: 0.0002, + output: 0.0006, + }, + "codestral-latest": { + input: 0.0002, + output: 0.0006, + }, + "ministral-8b-latest": { + input: 0.0001, + output: 0.0001, + }, + "ministral-3b-latest": { + input: 0.00004, + output: 0.00004, + }, + "mistral-embed": { + input: 0.0001, + output: 0, + }, + "open-mistral-7b": { + input: 0.00025, + output: 0.00025, + }, + "open-mixtral-8x7b": { + input: 0.0007, + output: 0.0007, + }, + "open-mixtral-8x22b": { + input: 0.002, + output: 0.006, + }, +}; + export const XAI_PRICING: Record = { "grok-beta": { input: 0.005, diff --git a/lib/utils.ts b/lib/utils.ts index 6ac8f0f4..07640ba9 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -16,6 +16,7 @@ import { CostTableEntry, GROQ_PRICING, LangTraceAttributes, + MISTRAL_PRICING, OPENAI_PRICING, PERPLEXITY_PRICING, SpanStatusCode, @@ -526,8 +527,8 @@ export function calculatePriceFromUsage( vendor = "openai"; } else if (model.includes("claude")) { vendor = "anthropic"; - } else if (model.includes("mistral")) { - vendor = "mistral"; // Assuming there is a MISTRAL_PRICING object + } else if (model.includes("tral")) { + vendor = "mistral"; } else if (model.includes("grok")) { vendor = "xai"; } else if (model.includes("gemini")) { @@ -581,6 +582,8 @@ export function calculatePriceFromUsage( costTable = GEMINI_PRICING[model]; } else if (model.includes("grok")) { costTable = XAI_PRICING[model]; + } else if (model.includes("tral")) { + costTable = MISTRAL_PRICING[model]; } } else if (vendor === "openai") { // check if model is present as key in OPENAI_PRICING @@ -642,6 +645,8 @@ export function calculatePriceFromUsage( costTable = GEMINI_PRICING[model]; } else if (vendor === "xai") { costTable = XAI_PRICING[model]; + } else if (vendor === "mistral") { + costTable = MISTRAL_PRICING[model]; } if (costTable) { const total =