# Options

```toml
model = "flash3"
input_concurrency = 6
```

# Before All

```lua
local p_utils = require("pricing_utils")

local base_dir = p_utils.base_dir

-- NOTE: Just delete the .md file for the provider name to have it load it. 

-- OPENAI    - https://platform.openai.com/docs/pricing/
--             https://developers.openai.com/api/docs/pricing.md (unfortunately, does not have the data)
-- ANTHROPIC - https://platform.claude.com/docs/en/about-claude/pricing
--             https://claude.com/pricing#api
--             Overview https://docs.anthropic.com/en/docs/about-claude/models/overview
-- GEMINI    - https://ai.google.dev/pricing
-- XAI       - https://console.x.ai/team/5577cfb2-dfde-4893-9817-4eb4de1d4098/models
-- GROQ      - https://console.groq.com/docs/models 
--           - pricing: https://groq.com/pricing/
-- FIREWORKS - Login with filter https://app.fireworks.ai/models?filter=LLM&serverless=true, 
--             Static https://fireworks.ai/pricing#serverless-pricing
-- TOGETHER  - login models price: https://api.together.ai/models
--             names In the browser window: console.log($$('td[id]').map(td => td.id).join('\n'));
-- ZAI       - https://docs.z.ai/guides/overview/pricing (take the md)

-- Config
local final_inputs = inputs
if not final_inputs or #final_inputs == 0 then
    final_inputs = p_utils.load_inputs()
end

for _, input in ipairs(final_inputs) do
    aip.file.ensure_exists(input.json_path, "{\n  \"models\": []\n}\n", { content_when_empty = true })
end

return aip.flow.before_all_response({
    inputs     = final_inputs -- for now, inputs are the providers
})
```

# Data

```lua
local md_path   = input.md_path
local json_path = input.json_path
local html_path = input.html_path
local provider_name = aip.text.trim(value_or(input.name, ""))

if not input.do_json then
    return aip.flow.skip(input.name .. " marked as do_json = false, skipping")
end

if not aip.path.exists(json_path) then
    aip.file.save(json_path, "{\n  \"models\": []\n}\n")
end

if input.url and input.url:find("%S") then
	local res = aip.web.get(input.url)
	aip.file.save(input.html_path, res.content)
end 
-- local rem_url = input.url
-- if not aip.path.exists(md_path) then 
--     local req = {
--         jsonrpc = "2.0",
--         method = "get_md",
--         params = { url = rem_url },
--         id = 1
--     }
-- 
--     -- Yes, it will require to have this mini rpc service (just wrapper on top of puppeteer)
--     local res = aip.web.post("http://localhost:3000/jsonrpc", req)
-- 
--     local content = res.content.result.content
--     aip.file.save(md_path, content)
-- end

if aip.path.exists(html_path) then 
    local slim_html = aip.file.save_html_to_slim(html_path)
    aip.file.save_html_to_md(slim_html.path, md_path)
end 

if not aip.path.exists(md_path) then
    return aip.flow.skip("" .. input.name .. " no md " .. md_path .. " so skipping")
end

local file = aip.file.load(md_path)
local instructions_path = CTX.AGENT_FILE_DIR .. "/instructions.md"
local sections = aip.file.load_md_sections(instructions_path, "# " ..provider_name)

if (not sections or #sections == 0) and provider_name ~= "default" then
  sections = aip.file.load_md_sections(instructions_path, "# default")
end

local provider_instruction = nil

if sections and #sections > 0 then
  provider_instruction = aip.text.trim(sections[1].content)
end
print("provider instruction:", provider_instruction)

if is_null(provider_instruction) or provider_instruction == "" then
  return aip.flow.skip("" .. input.name .. " missing instructions section in instructions.md, so skipping")
end

return {
    provider = input.name,
    content = file.content,
    instruction = provider_instruction
}
```

# Instruction

Here are the data for this {{data.provider}} AI Provider:

```md
{{data.content}}
```

Create a pricing JSON for this provider, following the following rules:

{{data.instruction}}

- Do not put in code block, just the raw json, pretty formatted.
- If caching price not available, set to `null`
- If price has text and audio, take the text price
- When decimal, do not end with 0s. Just up to the number.

with following schema

```ts
{
    models:
        {
            name: string,
            input: {
                cache_write: number | null,
                cached: number | null,
                normal: number | null,
            },
            output: number,
            recent: boolean, // default true if not sure
        }[]
}
```


# Output 

```lua
local content = ai_response.content
content = aip.md.outer_block_content_or_raw(content)

aip.file.save(input.json_path, content)
```

# After All


```lua
local p_utils = require("pricing_utils")

local json_path = p_utils.json_all_path

-- == Prep the final json
local content = "{\n"

local last_idx = #inputs

for k, input in pairs(inputs) do
  local json_path = input.json_path
  local file_content = aip.file.load(json_path).content
  content = content .. "\"" .. input.name .. "\": " .. file_content
  if k == last_idx then 
    content = content .. "\n"
  else
    content = content .. ",\n"
  end
end

content = content .. "}"

-- == Normalize json
local json    = aip.json.parse(content)
local content = aip.json.stringify_pretty(json)

-- == Save final json
aip.file.save(json_path, content)

```
