mattrguerra/cortexmainPrivate on GitHub, published here in full

fixtures.ts

Language TypeScript9.0 KB205 lines

src/ipc/mock/fixtures.ts

  1. // Invented sample data for the browser build: tests, screenshots, `npm run dev`.
  2. // Prices are DeepInfra's public list prices (per million tokens) as of the
  3. // bundled snapshot; the conversations and people are made up.
  4. import type { ModelInfo } from '../gen/ModelInfo'
  5. import type { Provider } from '../gen/Provider'
  6. const m = (
  7. provider_id: string,
  8. id: string,
  9. input: number,
  10. output: number,
  11. context: number | null,
  12. tags: string[],
  13. cache: number | null = null,
  14. ): ModelInfo => ({
  15. provider_id,
  16. id,
  17. prices: { input_per_m: input, output_per_m: output, cache_read_per_m: cache },
  18. context_length: context,
  19. max_tokens: null,
  20. tags,
  21. })
  22. export const providers: Provider[] = [
  23. {
  24. id: 'deepinfra',
  25. kind: 'deepinfra',
  26. name: 'DeepInfra',
  27. base_url: 'https://api.deepinfra.com/v1/openai',
  28. requires_key: true,
  29. },
  30. {
  31. id: 'ollama',
  32. kind: 'openai_compatible',
  33. name: 'Ollama',
  34. base_url: 'http://localhost:11434/v1',
  35. requires_key: false,
  36. },
  37. ]
  38. export const models: Record<string, ModelInfo[]> = {
  39. deepinfra: [
  40. m('deepinfra', 'deepseek-ai/DeepSeek-V3.1', 0.25, 0.95, 163840, ['chat', 'prompt_cache', 'reasoning'], 0.13),
  41. m('deepinfra', 'deepseek-ai/DeepSeek-V3.2', 0.26, 0.38, 163840, ['chat', 'prompt_cache'], 0.13),
  42. m('deepinfra', 'google/gemma-3-12b-it', 0.05, 0.15, 131072, ['chat', 'vlm', 'vision']),
  43. m('deepinfra', 'google/gemma-3-27b-it', 0.08, 0.16, 131072, ['chat', 'vlm', 'vision']),
  44. m('deepinfra', 'mistralai/Mistral-Small-3.2-24B-Instruct-2506', 0.075, 0.2, 128000, ['chat', 'vlm', 'vision']),
  45. m(
  46. 'deepinfra',
  47. 'moonshotai/Kimi-K2.6',
  48. 0.75,
  49. 3.5,
  50. 262144,
  51. ['chat', 'vlm', 'vision', 'prompt_cache', 'reasoning'],
  52. 0.15,
  53. ),
  54. m('deepinfra', 'Qwen/Qwen3-235B-A22B-Instruct-2507', 0.09, 0.55, 262144, ['chat']),
  55. m('deepinfra', 'Qwen/Qwen3-VL-30B-A3B-Instruct', 0.15, 0.6, 262144, ['chat', 'vlm', 'vision']),
  56. m(
  57. 'deepinfra',
  58. 'zai-org/GLM-5.3-Flash',
  59. 0.15,
  60. 0.5,
  61. 1048576,
  62. ['chat', 'vlm', 'vision', 'prompt_cache', 'reasoning'],
  63. 0.03,
  64. ),
  65. ],
  66. ollama: [
  67. m('ollama', 'llama3.2', 0, 0, null, ['chat', 'local']),
  68. m('ollama', 'qwen3:8b', 0, 0, null, ['chat', 'local']),
  69. ],
  70. }
  71. const HOUR = 3_600_000
  72. const DAY = 24 * HOUR
  73. export interface FixtureTurn {
  74. user: string
  75. assistant: string
  76. reasoning?: string
  77. prompt: number
  78. completion: number
  79. estimated?: boolean
  80. image?: { filename: string; width: number; height: number }
  81. }
  82. export interface FixtureChat {
  83. title: string
  84. provider: string
  85. model: string
  86. system: string
  87. ageMs: number
  88. pinned?: boolean
  89. turns: FixtureTurn[]
  90. }
  91. export const chats: FixtureChat[] = [
  92. {
  93. title: 'Tidy a bash backup script',
  94. provider: 'deepinfra',
  95. model: 'Qwen/Qwen3-235B-A22B-Instruct-2507',
  96. system: 'You are a careful shell reviewer. Prefer small, safe changes.',
  97. ageMs: 2 * HOUR,
  98. pinned: true,
  99. turns: [
  100. {
  101. user: 'Can you tidy this up? It copies my notes folder to an external drive every night.\n\ncp -r ~/notes /Volumes/Backup/notes-$(date +%F)',
  102. assistant:
  103. 'Three changes make it safer and quieter:\n\n1. **Quote every path**, so a space in a folder name cannot split it.\n2. **Stop early** when the drive is not mounted, instead of creating a folder on your internal disk.\n3. **Use `rsync`**, which copies only what changed and keeps timestamps.\n\n```bash\n#!/usr/bin/env bash\nset -euo pipefail\n\nsrc="$HOME/notes/"\ndest="/Volumes/Backup/notes"\n\nif [[ ! -d /Volumes/Backup ]]; then\n echo "Backup drive not mounted; skipping." >&2\n exit 0\nfi\n\nrsync -a --delete "$src" "$dest/"\n```\n\n`--delete` keeps the copy an exact mirror. Leave it off if you want deleted notes to survive on the drive.',
  104. prompt: 318,
  105. completion: 196,
  106. },
  107. {
  108. user: 'Keep a dated copy each week as well?',
  109. assistant:
  110. 'Add a weekly snapshot with hard links, so unchanged files take no extra space:\n\n```bash\nweek=$(date +%G-W%V)\nrsync -a --link-dest=\"$dest\" \"$src\" \"/Volumes/Backup/weekly/$week/\"\n```\n\nRun it from the same script on Sundays: `[[ $(date +%u) == 7 ]] && ...`.',
  111. prompt: 548,
  112. completion: 104,
  113. },
  114. ],
  115. },
  116. {
  117. title: 'How FTS5 bm25 ranking works',
  118. provider: 'deepinfra',
  119. model: 'deepseek-ai/DeepSeek-V3.2',
  120. system: '',
  121. ageMs: 26 * HOUR,
  122. turns: [
  123. {
  124. user: 'In SQLite FTS5, why does bm25() return negative numbers, and how do I weight the title column higher?',
  125. assistant:
  126. "FTS5 negates the classic BM25 score so that **better matches sort first with `ORDER BY rank`** (ascending). More negative means more relevant.\n\nTo weight columns, pass one weight per column in table order:\n\n```sql\nSELECT title, bm25(docs, 10.0, 1.0) AS score\nFROM docs\nWHERE docs MATCH 'backup*'\nORDER BY score;\n```\n\nHere a hit in `title` counts ten times as much as one in `body`.",
  127. prompt: 412,
  128. completion: 1093,
  129. },
  130. ],
  131. },
  132. {
  133. title: 'Compare two pricing tiers',
  134. provider: 'deepinfra',
  135. model: 'google/gemma-3-27b-it',
  136. system: 'Answer with a small table first, then one sentence.',
  137. ageMs: 3 * DAY,
  138. turns: [
  139. {
  140. user: 'Which of these plans is cheaper for a team of eight?',
  141. image: { filename: 'plans.png', width: 1200, height: 675 },
  142. assistant:
  143. '| Plan | Per seat | Eight seats |\n|---|---|---|\n| Studio | $12 | $96 |\n| Team | $9 + $20 base | $92 |\n\nTeam is $4 a month cheaper at eight seats, and the gap grows with every seat you add.',
  144. prompt: 1308,
  145. completion: 88,
  146. },
  147. ],
  148. },
  149. {
  150. title: 'Weekend sourdough schedule',
  151. provider: 'ollama',
  152. model: 'llama3.2',
  153. system: '',
  154. ageMs: 9 * DAY,
  155. turns: [
  156. {
  157. user: 'I want bread out of the oven by Sunday noon. When do I feed the starter?',
  158. assistant:
  159. 'Work backwards from noon on Sunday:\n\n- **Saturday 9:00**: feed the starter.\n- **Saturday 14:00**: mix the dough, then four sets of folds over two hours.\n- **Saturday 20:00**: shape, cover, and refrigerate overnight.\n- **Sunday 10:00**: bake straight from the fridge, 45 minutes.',
  160. prompt: 240,
  161. completion: 131,
  162. estimated: true,
  163. },
  164. ],
  165. },
  166. {
  167. title: 'Shorter note about a leaking radiator',
  168. provider: 'deepinfra',
  169. model: 'moonshotai/Kimi-K2.6',
  170. system: "Edit for brevity. Keep the writer's voice. Prefer short sentences.",
  171. ageMs: 16 * DAY,
  172. turns: [
  173. {
  174. user: 'Make this two sentences: "Hi, I wanted to let you know that the radiator in the back bedroom has started leaking again, it is the same one that was repaired in March, and there is a small puddle under it most mornings now."',
  175. reasoning:
  176. 'The core facts: the back bedroom radiator, leaking again, repaired in March, a puddle most mornings. Drop the throat-clearing.',
  177. assistant:
  178. 'The radiator in the back bedroom is leaking again, the same one that was repaired in March. There is a small puddle under it most mornings.',
  179. prompt: 164,
  180. completion: 38,
  181. },
  182. ],
  183. },
  184. ]
  185. /** Canned replies for the mock stream, picked by keywords in the prompt. */
  186. export function cannedReply(text: string, images: number): string {
  187. const t = text.toLowerCase()
  188. if (images > 0)
  189. return `I can see ${images === 1 ? 'the image' : `${images} images`}. The layout reads left to right, with the totals in the last column.`
  190. if (t.includes('sql') || t.includes('index'))
  191. return 'Add an index on the column you filter by most:\n\n```sql\nCREATE INDEX messages_created ON messages (created_at);\n```\n\nThen check the plan with `EXPLAIN QUERY PLAN`.'
  192. if (t.includes('hello') || t.length < 12) return 'Hello. What are you working on?'
  193. return `Here is a short answer.\n\n- It depends on what you need most: speed, cost, or quality.\n- For quick questions, a small model is usually enough and costs a fraction of a cent.\n- For long documents, pick a model with a larger context.\n\nYou asked: "${text.trim().slice(0, 80)}"`
  194. }
  195. /** A made-up two-plan chart, shown as the image attachment. */
  196. export const PLANS_SVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 675"><rect width="1200" height="675" fill="#f7f5fb"/><text x="60" y="90" font-family="sans-serif" font-size="44" fill="#2a2440">Plans</text><rect x="60" y="150" width="500" height="440" rx="24" fill="#fff" stroke="#d9d2ee" stroke-width="4"/><text x="100" y="230" font-family="sans-serif" font-size="40" fill="#3b2d6e">Studio</text><text x="100" y="320" font-family="sans-serif" font-size="72" fill="#2a2440">$12</text><text x="100" y="370" font-family="sans-serif" font-size="28" fill="#6b6385">per seat, per month</text><rect x="640" y="150" width="500" height="440" rx="24" fill="#fff" stroke="#9fe3d6" stroke-width="4"/><text x="680" y="230" font-family="sans-serif" font-size="40" fill="#0e6f6a">Team</text><text x="680" y="320" font-family="sans-serif" font-size="72" fill="#2a2440">$9</text><text x="680" y="370" font-family="sans-serif" font-size="28" fill="#6b6385">per seat, plus $20 a month</text></svg>`