llm-switcher 1.1.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.
Files changed (51) hide show
  1. package/.gitattributes +16 -0
  2. package/LICENSE +21 -0
  3. package/README.md +587 -0
  4. package/README.vi.md +585 -0
  5. package/blindfold/blindfold.mjs +633 -0
  6. package/blindfold/make-certs.sh +88 -0
  7. package/blindfold/wsframe.mjs +176 -0
  8. package/codex-catalog-template.json +1 -0
  9. package/config.example.json +84 -0
  10. package/contract-exclusions.json +41 -0
  11. package/contract.mjs +561 -0
  12. package/docs/LLM-RESPONSE-MATRIX.md +165 -0
  13. package/docs/TOKEN-OPTIMIZER-INTEROP.md +110 -0
  14. package/docs/codex-blindfold.md +214 -0
  15. package/docs/cross-platform.md +136 -0
  16. package/docs/diagrams/blindfold-request-routing.html +14972 -0
  17. package/docs/diagrams/blindfold-request-routing.sequence.json +175 -0
  18. package/docs/diagrams/blindfold-switch-lifecycle.html +14958 -0
  19. package/docs/diagrams/blindfold-switch-lifecycle.lifecycle.json +159 -0
  20. package/docs/diagrams/codex-model-name-resolution.html +15005 -0
  21. package/docs/diagrams/codex-model-name-resolution.workflow.json +71 -0
  22. package/docs/response-matrix.json +1131 -0
  23. package/formats.mjs +2308 -0
  24. package/mcp.mjs +340 -0
  25. package/package.json +36 -0
  26. package/proxy.mjs +1743 -0
  27. package/service.mjs +132 -0
  28. package/shim.mjs +292 -0
  29. package/skills/llm-switcher/SKILL.md +88 -0
  30. package/state.mjs +978 -0
  31. package/switch +5 -0
  32. package/switch.cmd +2 -0
  33. package/switch.mjs +930 -0
  34. package/tests/blindfold.test.mjs +307 -0
  35. package/tests/blindfold.wire.test.mjs +170 -0
  36. package/tests/contract/run.test.mjs +214 -0
  37. package/tests/contract-check.test.mjs +458 -0
  38. package/tests/contract-lab.test.mjs +755 -0
  39. package/tests/datadir.test.mjs +37 -0
  40. package/tests/formats.test.mjs +794 -0
  41. package/tests/gateway.e2e.test.mjs +999 -0
  42. package/tests/helpers.mjs +24 -0
  43. package/tests/lifecycle.test.mjs +416 -0
  44. package/tests/live-optimizer-interop.mjs +205 -0
  45. package/tests/mcp.test.mjs +91 -0
  46. package/tests/service.test.mjs +69 -0
  47. package/tests/shim.test.mjs +228 -0
  48. package/tests/state.test.mjs +675 -0
  49. package/tests/switch.test.mjs +156 -0
  50. package/tests/wsframe.test.mjs +154 -0
  51. package/ui.html +2234 -0
@@ -0,0 +1,71 @@
1
+ {
2
+ "schema_version": 2,
3
+ "diagram_type": "workflow",
4
+ "meta": {
5
+ "title": "Codex Model Name Resolution",
6
+ "quality_profile": "showcase",
7
+ "output": "docs/diagrams/codex-model-name-resolution.html"
8
+ },
9
+ "lanes": [
10
+ { "id": "profile", "label": "Profile (config.json)" },
11
+ { "id": "switcher", "label": "Switcher" },
12
+ { "id": "cli", "label": "Codex CLI" },
13
+ { "id": "gateway", "label": "Gateway" }
14
+ ],
15
+ "phases": [
16
+ { "id": "declared", "label": "Declared", "fromCol": 0, "toCol": 1 },
17
+ { "id": "generated", "label": "Generated on every switch", "fromCol": 2, "toCol": 3, "variant": "emphasis" },
18
+ { "id": "runtime", "label": "Request path", "fromCol": 4, "toCol": 5, "variant": "dashed" }
19
+ ],
20
+ "mainPath": ["pub", "resolve", "catalog", "picker", "request", "mapmodel"],
21
+ "nodes": [
22
+ { "id": "pub", "lane": "profile", "col": 0, "type": "database", "label": "publicModels", "sublabel": "official names, in role order", "width": 148 },
23
+ { "id": "roles", "lane": "profile", "col": 1, "type": "database", "label": "codexRoles", "sublabel": "per-role override", "tag": "wins over position", "width": 148 },
24
+ { "id": "resolve", "lane": "switcher", "col": 1, "type": "backend", "label": "codexPublicModel", "sublabel": "slot to official name", "width": 148 },
25
+ { "id": "catalog", "lane": "switcher", "col": 2, "type": "database", "label": "model-catalog.json", "sublabel": "official slugs only", "width": 148 },
26
+ { "id": "envfile", "lane": "switcher", "col": 3, "type": "database", "label": "env.cmd / env.sh", "sublabel": "role names only", "tag": "unsafe name dropped", "width": 148 },
27
+ { "id": "picker", "lane": "cli", "col": 3, "type": "frontend", "label": "/model picker", "sublabel": "reads the local catalog", "width": 148 },
28
+ { "id": "request", "lane": "cli", "col": 4, "type": "frontend", "label": "API request", "sublabel": "sends an official name", "width": 148 },
29
+ { "id": "slots", "lane": "gateway", "col": 4, "type": "database", "label": "defaultModels", "sublabel": "upstream IDs", "width": 148 },
30
+ { "id": "mapmodel", "lane": "gateway", "col": 5, "type": "backend", "label": "mapModel", "sublabel": "official name to slot", "width": 148 }
31
+ ],
32
+ "edges": [
33
+ { "id": "pub-resolve", "from": "pub", "to": "resolve", "label": "position sets the role", "variant": "emphasis" },
34
+ { "id": "roles-resolve", "from": "roles", "to": "resolve", "label": "override", "variant": "dashed", "role": "branch" },
35
+ { "id": "resolve-catalog", "from": "resolve", "to": "catalog", "variant": "emphasis" },
36
+ { "id": "resolve-env", "from": "resolve", "to": "envfile", "label": "review + subagent", "variant": "default" },
37
+ { "id": "catalog-picker", "from": "catalog", "to": "picker", "label": "the picker never calls /v1/models", "variant": "emphasis" },
38
+ { "id": "env-request", "from": "envfile", "to": "request", "label": "--config", "variant": "default" },
39
+ { "id": "picker-request", "from": "picker", "to": "request", "variant": "emphasis" },
40
+ { "id": "request-map", "from": "request", "to": "mapmodel", "label": "official name over the wire", "variant": "emphasis" },
41
+ { "id": "map-slots", "from": "mapmodel", "to": "slots", "label": "upstream ID stays server side", "variant": "security", "role": "return" }
42
+ ],
43
+ "cards": [
44
+ {
45
+ "dot": "cyan",
46
+ "title": "One direction only",
47
+ "items": [
48
+ "Official names travel out to the CLI",
49
+ "The slot aliases main, review and subagent never leave the gateway",
50
+ "mapModel resolves an official name before the gpt-* fail-closed rule"
51
+ ]
52
+ },
53
+ {
54
+ "dot": "rose",
55
+ "title": "What the picker reads",
56
+ "items": [
57
+ "The /model screen renders the local catalog file",
58
+ "That file is rebuilt from publicModels on every profile switch",
59
+ "A stale catalog cannot survive a switch"
60
+ ]
61
+ },
62
+ {
63
+ "dot": "amber",
64
+ "title": "Two guards on the names",
65
+ "items": [
66
+ "A blank entry means no override for that slot, and shifts nothing",
67
+ "A name outside [A-Za-z0-9._:/-] is dropped before it reaches env.cmd"
68
+ ]
69
+ }
70
+ ]
71
+ }