@brainervirus/opencode-commandcode 0.6.1 → 0.7.1

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/CHANGELOG.md CHANGED
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.7.1] - 2026-08-29
11
+
12
+ ### Changed
13
+
14
+ - Catalog refresh and post-release manifest PRs auto-merge when required CI is green.
15
+
16
+ ### Fixed
17
+
18
+ - Startup summary test reads the bundled command-code version from the manifest instead of pinning one release.
19
+
20
+ ## [0.7.0] - 2026-08-28
21
+
22
+ ### Changed
23
+
24
+ - npm publishes only when plugin or catalog files change since the last tag — CI, tests, and scripts-only merges skip a release.
25
+
26
+ ### Added
27
+
28
+ - Catalog models include vision vs text-only from the Command Code CLI `inputModalities` field on every SKU. models.dev only adds extra inputs (video/audio/pdf) on matches.
29
+
10
30
  ## [0.6.1] - 2026-08-28
11
31
 
12
32
  ### Added
package/README.md CHANGED
@@ -19,6 +19,7 @@ This package is based on **[FanFan4204/opencode-commandcode-provider](https://gi
19
19
  - Bundled `models.json` is the default runtime catalog (no local CLI scrape).
20
20
  - CLI cost extraction can fail (as on `command-code@1.38.x`) without dropping models.
21
21
  - Official docs fill missing costs; remaining paid gaps use [models.dev](https://models.dev) as a reference. Command Code free SKUs stay `$0`.
22
+ - Vision vs text-only comes from the Command Code CLI catalog (`inputModalities` on every SKU). [models.dev](https://models.dev) only adds extra inputs (video/audio/pdf) when it matches.
22
23
  - Reasoning effort **variants** on models that declare `reasoningEfforts`.
23
24
  - Quiet OpenCode startup (diagnostics go to `startup.json`, not stdout).
24
25
 
@@ -83,7 +84,7 @@ bun run check # oxlint + oxfmt + bun test + tsc (same stack as workit
83
84
  bun run sync -- --remote # refresh models.json + manifest.json from command-code@latest
84
85
  ```
85
86
 
86
- CI (`.github/workflows/catalog-sync.yml`) opens a PR every 6 hours when Command Code ships a new catalog. Merge after **check (test)**, **check (typecheck)**, **check (lint)**, **check (format)**, and **check (pack)** are green. `.github/workflows/release.yml` then runs **semantic-release** (npm publish + GitHub Release + tag). Do not push to `main`.
87
+ CI (`.github/workflows/catalog-sync.yml`) opens a PR every 6 hours when Command Code ships a new catalog. That PR, and the post-release `chore/manifest-sync-v*` PR, auto-merge after **check (test)**, **check (typecheck)**, **check (lint)**, **check (format)**, and **check (pack)** are green. `.github/workflows/release.yml` then runs **semantic-release** (npm publish + GitHub Release + tag). Do not push to `main`.
87
88
 
88
89
  The GitHub Actions secret name is `NPMJS` (same as workit). It is mapped to both `NPM_TOKEN` and `NODE_AUTH_TOKEN`. Use an npm **Automation** token (bypasses 2FA). A login token from `~/.npmrc` fails CI with `EOTP`. Catalog PRs get a real CI run when `RELEASE_SYNC_TOKEN` (or `CATALOG_PUSH_TOKEN`) is a PAT; `GITHUB_TOKEN` can open the PR but GitHub will not start workflows from that event.
89
90
 
package/_version.txt CHANGED
@@ -1 +1 @@
1
- 1.38.1
1
+ 1.38.2
package/manifest.json CHANGED
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "generatedAt": "2026-08-28T19:50:57.386Z",
4
- "pluginVersion": "0.6.0",
5
- "commandCodeVersion": "1.38.1",
6
- "commandCodeTarball": "https://registry.npmjs.org/command-code/-/command-code-1.38.1.tgz",
3
+ "generatedAt": "2026-08-29T17:07:34.207Z",
4
+ "pluginVersion": "0.7.0",
5
+ "commandCodeVersion": "1.38.2",
6
+ "commandCodeTarball": "https://registry.npmjs.org/command-code/-/command-code-1.38.2.tgz",
7
7
  "modelCount": 65,
8
8
  "reasoningModelCount": 54,
9
9
  "extraction": {
10
10
  "modelCatalog": "ok",
11
- "costCatalog": "docs",
11
+ "costCatalog": "cli",
12
12
  "costCatalogError": null
13
13
  },
14
14
  "costSources": {
15
- "cli": 0,
16
- "officialDocs": 60,
15
+ "cli": 20,
16
+ "officialDocs": 40,
17
17
  "thirdParty": 0,
18
18
  "free": 5,
19
19
  "fallback": 0,
package/models.json CHANGED
@@ -21,6 +21,16 @@
21
21
  "limit": {
22
22
  "context": 1000000,
23
23
  "output": 65536
24
+ },
25
+ "attachment": true,
26
+ "modalities": {
27
+ "input": [
28
+ "text",
29
+ "image"
30
+ ],
31
+ "output": [
32
+ "text"
33
+ ]
24
34
  }
25
35
  },
26
36
  {
@@ -38,6 +48,17 @@
38
48
  "limit": {
39
49
  "context": 200000,
40
50
  "output": 8192
51
+ },
52
+ "attachment": true,
53
+ "modalities": {
54
+ "input": [
55
+ "text",
56
+ "image",
57
+ "pdf"
58
+ ],
59
+ "output": [
60
+ "text"
61
+ ]
41
62
  }
42
63
  },
43
64
  {
@@ -62,6 +83,17 @@
62
83
  "limit": {
63
84
  "context": 1000000,
64
85
  "output": 32000
86
+ },
87
+ "attachment": true,
88
+ "modalities": {
89
+ "input": [
90
+ "text",
91
+ "image",
92
+ "pdf"
93
+ ],
94
+ "output": [
95
+ "text"
96
+ ]
65
97
  }
66
98
  },
67
99
  {
@@ -86,6 +118,16 @@
86
118
  "limit": {
87
119
  "context": 1000000,
88
120
  "output": 65536
121
+ },
122
+ "attachment": true,
123
+ "modalities": {
124
+ "input": [
125
+ "text",
126
+ "image"
127
+ ],
128
+ "output": [
129
+ "text"
130
+ ]
89
131
  }
90
132
  },
91
133
  {
@@ -110,6 +152,16 @@
110
152
  "limit": {
111
153
  "context": 1000000,
112
154
  "output": 65536
155
+ },
156
+ "attachment": true,
157
+ "modalities": {
158
+ "input": [
159
+ "text",
160
+ "image"
161
+ ],
162
+ "output": [
163
+ "text"
164
+ ]
113
165
  }
114
166
  },
115
167
  {
@@ -134,6 +186,17 @@
134
186
  "limit": {
135
187
  "context": 1000000,
136
188
  "output": 16000
189
+ },
190
+ "attachment": true,
191
+ "modalities": {
192
+ "input": [
193
+ "text",
194
+ "image",
195
+ "pdf"
196
+ ],
197
+ "output": [
198
+ "text"
199
+ ]
137
200
  }
138
201
  },
139
202
  {
@@ -158,6 +221,16 @@
158
221
  "limit": {
159
222
  "context": 1000000,
160
223
  "output": 65536
224
+ },
225
+ "attachment": true,
226
+ "modalities": {
227
+ "input": [
228
+ "text",
229
+ "image"
230
+ ],
231
+ "output": [
232
+ "text"
233
+ ]
161
234
  }
162
235
  },
163
236
  {
@@ -180,6 +253,16 @@
180
253
  "limit": {
181
254
  "context": 400000,
182
255
  "output": 128000
256
+ },
257
+ "attachment": true,
258
+ "modalities": {
259
+ "input": [
260
+ "text",
261
+ "image"
262
+ ],
263
+ "output": [
264
+ "text"
265
+ ]
183
266
  }
184
267
  },
185
268
  {
@@ -202,6 +285,17 @@
202
285
  "limit": {
203
286
  "context": 400000,
204
287
  "output": 128000
288
+ },
289
+ "attachment": true,
290
+ "modalities": {
291
+ "input": [
292
+ "text",
293
+ "image",
294
+ "pdf"
295
+ ],
296
+ "output": [
297
+ "text"
298
+ ]
205
299
  }
206
300
  },
207
301
  {
@@ -223,6 +317,16 @@
223
317
  "limit": {
224
318
  "context": 400000,
225
319
  "output": 128000
320
+ },
321
+ "attachment": true,
322
+ "modalities": {
323
+ "input": [
324
+ "text",
325
+ "image"
326
+ ],
327
+ "output": [
328
+ "text"
329
+ ]
226
330
  }
227
331
  },
228
332
  {
@@ -245,6 +349,16 @@
245
349
  "limit": {
246
350
  "context": 400000,
247
351
  "output": 128000
352
+ },
353
+ "attachment": true,
354
+ "modalities": {
355
+ "input": [
356
+ "text",
357
+ "image"
358
+ ],
359
+ "output": [
360
+ "text"
361
+ ]
248
362
  }
249
363
  },
250
364
  {
@@ -265,6 +379,15 @@
265
379
  "limit": {
266
380
  "context": 1000000,
267
381
  "output": 384000
382
+ },
383
+ "attachment": false,
384
+ "modalities": {
385
+ "input": [
386
+ "text"
387
+ ],
388
+ "output": [
389
+ "text"
390
+ ]
268
391
  }
269
392
  },
270
393
  {
@@ -285,6 +408,16 @@
285
408
  "limit": {
286
409
  "context": 1000000,
287
410
  "output": 65536
411
+ },
412
+ "attachment": true,
413
+ "modalities": {
414
+ "input": [
415
+ "text",
416
+ "image"
417
+ ],
418
+ "output": [
419
+ "text"
420
+ ]
288
421
  }
289
422
  },
290
423
  {
@@ -305,6 +438,15 @@
305
438
  "limit": {
306
439
  "context": 1000000,
307
440
  "output": 384000
441
+ },
442
+ "attachment": false,
443
+ "modalities": {
444
+ "input": [
445
+ "text"
446
+ ],
447
+ "output": [
448
+ "text"
449
+ ]
308
450
  }
309
451
  },
310
452
  {
@@ -325,6 +467,16 @@
325
467
  "limit": {
326
468
  "context": 1000000,
327
469
  "output": 65536
470
+ },
471
+ "attachment": true,
472
+ "modalities": {
473
+ "input": [
474
+ "text",
475
+ "image"
476
+ ],
477
+ "output": [
478
+ "text"
479
+ ]
328
480
  }
329
481
  },
330
482
  {
@@ -346,6 +498,19 @@
346
498
  "limit": {
347
499
  "context": 1000000,
348
500
  "output": 65536
501
+ },
502
+ "attachment": true,
503
+ "modalities": {
504
+ "input": [
505
+ "text",
506
+ "image",
507
+ "video",
508
+ "audio",
509
+ "pdf"
510
+ ],
511
+ "output": [
512
+ "text"
513
+ ]
349
514
  }
350
515
  },
351
516
  {
@@ -367,6 +532,19 @@
367
532
  "limit": {
368
533
  "context": 1000000,
369
534
  "output": 65536
535
+ },
536
+ "attachment": true,
537
+ "modalities": {
538
+ "input": [
539
+ "text",
540
+ "image",
541
+ "video",
542
+ "audio",
543
+ "pdf"
544
+ ],
545
+ "output": [
546
+ "text"
547
+ ]
370
548
  }
371
549
  },
372
550
  {
@@ -388,6 +566,19 @@
388
566
  "limit": {
389
567
  "context": 1000000,
390
568
  "output": 65536
569
+ },
570
+ "attachment": true,
571
+ "modalities": {
572
+ "input": [
573
+ "text",
574
+ "image",
575
+ "video",
576
+ "audio",
577
+ "pdf"
578
+ ],
579
+ "output": [
580
+ "text"
581
+ ]
391
582
  }
392
583
  },
393
584
  {
@@ -409,6 +600,19 @@
409
600
  "limit": {
410
601
  "context": 1000000,
411
602
  "output": 65536
603
+ },
604
+ "attachment": true,
605
+ "modalities": {
606
+ "input": [
607
+ "text",
608
+ "image",
609
+ "video",
610
+ "audio",
611
+ "pdf"
612
+ ],
613
+ "output": [
614
+ "text"
615
+ ]
412
616
  }
413
617
  },
414
618
  {
@@ -423,14 +627,27 @@
423
627
  ],
424
628
  "tool_call": true,
425
629
  "cost": {
426
- "input": 0.75,
427
- "output": 3.75,
428
- "cache_read": 0.075,
429
- "cache_write": 0.04167
630
+ "input": 1.5,
631
+ "output": 7.5,
632
+ "cache_read": 0.15,
633
+ "cache_write": 0.08334
430
634
  },
431
635
  "limit": {
432
636
  "context": 1048576,
433
637
  "output": 65536
638
+ },
639
+ "attachment": true,
640
+ "modalities": {
641
+ "input": [
642
+ "text",
643
+ "image",
644
+ "video",
645
+ "audio",
646
+ "pdf"
647
+ ],
648
+ "output": [
649
+ "text"
650
+ ]
434
651
  }
435
652
  },
436
653
  {
@@ -440,13 +657,21 @@
440
657
  "reasoning": false,
441
658
  "tool_call": true,
442
659
  "cost": {
443
- "input": 1,
444
- "output": 3.2,
445
- "cache_read": 0.2
660
+ "input": 0.95,
661
+ "output": 3.15
446
662
  },
447
663
  "limit": {
448
664
  "context": 200000,
449
665
  "output": 131072
666
+ },
667
+ "attachment": false,
668
+ "modalities": {
669
+ "input": [
670
+ "text"
671
+ ],
672
+ "output": [
673
+ "text"
674
+ ]
450
675
  }
451
676
  },
452
677
  {
@@ -463,6 +688,15 @@
463
688
  "limit": {
464
689
  "context": 200000,
465
690
  "output": 131072
691
+ },
692
+ "attachment": false,
693
+ "modalities": {
694
+ "input": [
695
+ "text"
696
+ ],
697
+ "output": [
698
+ "text"
699
+ ]
466
700
  }
467
701
  },
468
702
  {
@@ -483,6 +717,15 @@
483
717
  "limit": {
484
718
  "context": 1000000,
485
719
  "output": 65536
720
+ },
721
+ "attachment": false,
722
+ "modalities": {
723
+ "input": [
724
+ "text"
725
+ ],
726
+ "output": [
727
+ "text"
728
+ ]
486
729
  }
487
730
  },
488
731
  {
@@ -499,6 +742,16 @@
499
742
  "limit": {
500
743
  "context": 1000000,
501
744
  "output": 65536
745
+ },
746
+ "attachment": true,
747
+ "modalities": {
748
+ "input": [
749
+ "text",
750
+ "image"
751
+ ],
752
+ "output": [
753
+ "text"
754
+ ]
502
755
  }
503
756
  },
504
757
  {
@@ -520,6 +773,15 @@
520
773
  "limit": {
521
774
  "context": 1000000,
522
775
  "output": 65536
776
+ },
777
+ "attachment": false,
778
+ "modalities": {
779
+ "input": [
780
+ "text"
781
+ ],
782
+ "output": [
783
+ "text"
784
+ ]
523
785
  }
524
786
  },
525
787
  {
@@ -540,7 +802,18 @@
540
802
  },
541
803
  "limit": {
542
804
  "context": 1048576,
543
- "output": 65536
805
+ "output": 131072
806
+ },
807
+ "attachment": true,
808
+ "modalities": {
809
+ "input": [
810
+ "text",
811
+ "image",
812
+ "video"
813
+ ],
814
+ "output": [
815
+ "text"
816
+ ]
544
817
  }
545
818
  },
546
819
  {
@@ -565,6 +838,16 @@
565
838
  "limit": {
566
839
  "context": 1050000,
567
840
  "output": 65536
841
+ },
842
+ "attachment": true,
843
+ "modalities": {
844
+ "input": [
845
+ "text",
846
+ "image"
847
+ ],
848
+ "output": [
849
+ "text"
850
+ ]
568
851
  }
569
852
  },
570
853
  {
@@ -589,6 +872,16 @@
589
872
  "limit": {
590
873
  "context": 1050000,
591
874
  "output": 65536
875
+ },
876
+ "attachment": true,
877
+ "modalities": {
878
+ "input": [
879
+ "text",
880
+ "image"
881
+ ],
882
+ "output": [
883
+ "text"
884
+ ]
592
885
  }
593
886
  },
594
887
  {
@@ -613,6 +906,16 @@
613
906
  "limit": {
614
907
  "context": 1050000,
615
908
  "output": 65536
909
+ },
910
+ "attachment": true,
911
+ "modalities": {
912
+ "input": [
913
+ "text",
914
+ "image"
915
+ ],
916
+ "output": [
917
+ "text"
918
+ ]
616
919
  }
617
920
  },
618
921
  {
@@ -634,6 +937,16 @@
634
937
  "limit": {
635
938
  "context": 500000,
636
939
  "output": 65536
940
+ },
941
+ "attachment": true,
942
+ "modalities": {
943
+ "input": [
944
+ "text",
945
+ "image"
946
+ ],
947
+ "output": [
948
+ "text"
949
+ ]
637
950
  }
638
951
  },
639
952
  {
@@ -656,6 +969,16 @@
656
969
  "limit": {
657
970
  "context": 500000,
658
971
  "output": 65536
972
+ },
973
+ "attachment": true,
974
+ "modalities": {
975
+ "input": [
976
+ "text",
977
+ "image"
978
+ ],
979
+ "output": [
980
+ "text"
981
+ ]
659
982
  }
660
983
  },
661
984
  {
@@ -672,6 +995,16 @@
672
995
  "limit": {
673
996
  "context": 256000,
674
997
  "output": 65536
998
+ },
999
+ "attachment": true,
1000
+ "modalities": {
1001
+ "input": [
1002
+ "text",
1003
+ "image"
1004
+ ],
1005
+ "output": [
1006
+ "text"
1007
+ ]
675
1008
  }
676
1009
  },
677
1010
  {
@@ -688,6 +1021,16 @@
688
1021
  "limit": {
689
1022
  "context": 1000000,
690
1023
  "output": 65536
1024
+ },
1025
+ "attachment": true,
1026
+ "modalities": {
1027
+ "input": [
1028
+ "text",
1029
+ "image"
1030
+ ],
1031
+ "output": [
1032
+ "text"
1033
+ ]
691
1034
  }
692
1035
  },
693
1036
  {
@@ -698,12 +1041,21 @@
698
1041
  "tool_call": true,
699
1042
  "cost": {
700
1043
  "input": 0.6,
701
- "output": 3,
702
- "cache_read": 0.1
1044
+ "output": 3
703
1045
  },
704
1046
  "limit": {
705
1047
  "context": 256000,
706
1048
  "output": 131072
1049
+ },
1050
+ "attachment": true,
1051
+ "modalities": {
1052
+ "input": [
1053
+ "text",
1054
+ "image"
1055
+ ],
1056
+ "output": [
1057
+ "text"
1058
+ ]
707
1059
  }
708
1060
  },
709
1061
  {
@@ -720,6 +1072,17 @@
720
1072
  "limit": {
721
1073
  "context": 256000,
722
1074
  "output": 131072
1075
+ },
1076
+ "attachment": true,
1077
+ "modalities": {
1078
+ "input": [
1079
+ "text",
1080
+ "image",
1081
+ "video"
1082
+ ],
1083
+ "output": [
1084
+ "text"
1085
+ ]
723
1086
  }
724
1087
  },
725
1088
  {
@@ -736,6 +1099,17 @@
736
1099
  "limit": {
737
1100
  "context": 256000,
738
1101
  "output": 65536
1102
+ },
1103
+ "attachment": true,
1104
+ "modalities": {
1105
+ "input": [
1106
+ "text",
1107
+ "image",
1108
+ "video"
1109
+ ],
1110
+ "output": [
1111
+ "text"
1112
+ ]
739
1113
  }
740
1114
  },
741
1115
  {
@@ -752,6 +1126,16 @@
752
1126
  "limit": {
753
1127
  "context": 262000,
754
1128
  "output": 65536
1129
+ },
1130
+ "attachment": true,
1131
+ "modalities": {
1132
+ "input": [
1133
+ "text",
1134
+ "image"
1135
+ ],
1136
+ "output": [
1137
+ "text"
1138
+ ]
755
1139
  }
756
1140
  },
757
1141
  {
@@ -768,6 +1152,17 @@
768
1152
  "limit": {
769
1153
  "context": 1000000,
770
1154
  "output": 65536
1155
+ },
1156
+ "attachment": true,
1157
+ "modalities": {
1158
+ "input": [
1159
+ "text",
1160
+ "image",
1161
+ "video"
1162
+ ],
1163
+ "output": [
1164
+ "text"
1165
+ ]
771
1166
  }
772
1167
  },
773
1168
  {
@@ -783,7 +1178,16 @@
783
1178
  },
784
1179
  "limit": {
785
1180
  "context": 256000,
786
- "output": 65536
1181
+ "output": 32768
1182
+ },
1183
+ "attachment": false,
1184
+ "modalities": {
1185
+ "input": [
1186
+ "text"
1187
+ ],
1188
+ "output": [
1189
+ "text"
1190
+ ]
787
1191
  }
788
1192
  },
789
1193
  {
@@ -798,7 +1202,16 @@
798
1202
  },
799
1203
  "limit": {
800
1204
  "context": 256000,
801
- "output": 65536
1205
+ "output": 32768
1206
+ },
1207
+ "attachment": false,
1208
+ "modalities": {
1209
+ "input": [
1210
+ "text"
1211
+ ],
1212
+ "output": [
1213
+ "text"
1214
+ ]
802
1215
  }
803
1216
  },
804
1217
  {
@@ -815,6 +1228,18 @@
815
1228
  "limit": {
816
1229
  "context": 1000000,
817
1230
  "output": 65536
1231
+ },
1232
+ "attachment": true,
1233
+ "modalities": {
1234
+ "input": [
1235
+ "text",
1236
+ "image",
1237
+ "audio",
1238
+ "video"
1239
+ ],
1240
+ "output": [
1241
+ "text"
1242
+ ]
818
1243
  }
819
1244
  },
820
1245
  {
@@ -831,6 +1256,15 @@
831
1256
  "limit": {
832
1257
  "context": 1000000,
833
1258
  "output": 65536
1259
+ },
1260
+ "attachment": false,
1261
+ "modalities": {
1262
+ "input": [
1263
+ "text"
1264
+ ],
1265
+ "output": [
1266
+ "text"
1267
+ ]
834
1268
  }
835
1269
  },
836
1270
  {
@@ -840,13 +1274,21 @@
840
1274
  "reasoning": false,
841
1275
  "tool_call": true,
842
1276
  "cost": {
843
- "input": 0.3,
844
- "output": 1.2,
845
- "cache_read": 0.03
1277
+ "input": 0.5,
1278
+ "output": 2
846
1279
  },
847
1280
  "limit": {
848
1281
  "context": 200000,
849
1282
  "output": 131072
1283
+ },
1284
+ "attachment": false,
1285
+ "modalities": {
1286
+ "input": [
1287
+ "text"
1288
+ ],
1289
+ "output": [
1290
+ "text"
1291
+ ]
850
1292
  }
851
1293
  },
852
1294
  {
@@ -863,6 +1305,15 @@
863
1305
  "limit": {
864
1306
  "context": 1000000,
865
1307
  "output": 131072
1308
+ },
1309
+ "attachment": false,
1310
+ "modalities": {
1311
+ "input": [
1312
+ "text"
1313
+ ],
1314
+ "output": [
1315
+ "text"
1316
+ ]
866
1317
  }
867
1318
  },
868
1319
  {
@@ -878,6 +1329,15 @@
878
1329
  "limit": {
879
1330
  "context": 197000,
880
1331
  "output": 65536
1332
+ },
1333
+ "attachment": false,
1334
+ "modalities": {
1335
+ "input": [
1336
+ "text"
1337
+ ],
1338
+ "output": [
1339
+ "text"
1340
+ ]
881
1341
  }
882
1342
  },
883
1343
  {
@@ -894,6 +1354,17 @@
894
1354
  "limit": {
895
1355
  "context": 1000000,
896
1356
  "output": 65536
1357
+ },
1358
+ "attachment": true,
1359
+ "modalities": {
1360
+ "input": [
1361
+ "text",
1362
+ "image",
1363
+ "video"
1364
+ ],
1365
+ "output": [
1366
+ "text"
1367
+ ]
897
1368
  }
898
1369
  },
899
1370
  {
@@ -909,6 +1380,17 @@
909
1380
  "limit": {
910
1381
  "context": 1000000,
911
1382
  "output": 65536
1383
+ },
1384
+ "attachment": true,
1385
+ "modalities": {
1386
+ "input": [
1387
+ "text",
1388
+ "image",
1389
+ "video"
1390
+ ],
1391
+ "output": [
1392
+ "text"
1393
+ ]
912
1394
  }
913
1395
  },
914
1396
  {
@@ -924,6 +1406,16 @@
924
1406
  "limit": {
925
1407
  "context": 1000000,
926
1408
  "output": 65536
1409
+ },
1410
+ "attachment": true,
1411
+ "modalities": {
1412
+ "input": [
1413
+ "text",
1414
+ "image"
1415
+ ],
1416
+ "output": [
1417
+ "text"
1418
+ ]
927
1419
  }
928
1420
  },
929
1421
  {
@@ -940,6 +1432,19 @@
940
1432
  "limit": {
941
1433
  "context": 1048576,
942
1434
  "output": 65536
1435
+ },
1436
+ "attachment": true,
1437
+ "modalities": {
1438
+ "input": [
1439
+ "text",
1440
+ "image",
1441
+ "video",
1442
+ "pdf",
1443
+ "audio"
1444
+ ],
1445
+ "output": [
1446
+ "text"
1447
+ ]
943
1448
  }
944
1449
  },
945
1450
  {
@@ -956,6 +1461,19 @@
956
1461
  "limit": {
957
1462
  "context": 1048576,
958
1463
  "output": 65536
1464
+ },
1465
+ "attachment": true,
1466
+ "modalities": {
1467
+ "input": [
1468
+ "text",
1469
+ "image",
1470
+ "video",
1471
+ "pdf",
1472
+ "audio"
1473
+ ],
1474
+ "output": [
1475
+ "text"
1476
+ ]
959
1477
  }
960
1478
  },
961
1479
  {
@@ -972,6 +1490,19 @@
972
1490
  "limit": {
973
1491
  "context": 1048576,
974
1492
  "output": 65536
1493
+ },
1494
+ "attachment": true,
1495
+ "modalities": {
1496
+ "input": [
1497
+ "text",
1498
+ "image",
1499
+ "video",
1500
+ "pdf",
1501
+ "audio"
1502
+ ],
1503
+ "output": [
1504
+ "text"
1505
+ ]
975
1506
  }
976
1507
  },
977
1508
  {
@@ -988,6 +1519,15 @@
988
1519
  "limit": {
989
1520
  "context": 1000000,
990
1521
  "output": 65536
1522
+ },
1523
+ "attachment": false,
1524
+ "modalities": {
1525
+ "input": [
1526
+ "text"
1527
+ ],
1528
+ "output": [
1529
+ "text"
1530
+ ]
991
1531
  }
992
1532
  },
993
1533
  {
@@ -1005,6 +1545,15 @@
1005
1545
  "limit": {
1006
1546
  "context": 1000000,
1007
1547
  "output": 131072
1548
+ },
1549
+ "attachment": false,
1550
+ "modalities": {
1551
+ "input": [
1552
+ "text"
1553
+ ],
1554
+ "output": [
1555
+ "text"
1556
+ ]
1008
1557
  }
1009
1558
  },
1010
1559
  {
@@ -1021,6 +1570,17 @@
1021
1570
  "limit": {
1022
1571
  "context": 1000000,
1023
1572
  "output": 131072
1573
+ },
1574
+ "attachment": true,
1575
+ "modalities": {
1576
+ "input": [
1577
+ "text",
1578
+ "image",
1579
+ "video"
1580
+ ],
1581
+ "output": [
1582
+ "text"
1583
+ ]
1024
1584
  }
1025
1585
  },
1026
1586
  {
@@ -1038,6 +1598,17 @@
1038
1598
  "limit": {
1039
1599
  "context": 1000000,
1040
1600
  "output": 65536
1601
+ },
1602
+ "attachment": true,
1603
+ "modalities": {
1604
+ "input": [
1605
+ "text",
1606
+ "image",
1607
+ "video"
1608
+ ],
1609
+ "output": [
1610
+ "text"
1611
+ ]
1041
1612
  }
1042
1613
  },
1043
1614
  {
@@ -1055,6 +1626,15 @@
1055
1626
  "limit": {
1056
1627
  "context": 1000000,
1057
1628
  "output": 131072
1629
+ },
1630
+ "attachment": false,
1631
+ "modalities": {
1632
+ "input": [
1633
+ "text"
1634
+ ],
1635
+ "output": [
1636
+ "text"
1637
+ ]
1058
1638
  }
1059
1639
  },
1060
1640
  {
@@ -1072,6 +1652,17 @@
1072
1652
  "limit": {
1073
1653
  "context": 1000000,
1074
1654
  "output": 65536
1655
+ },
1656
+ "attachment": true,
1657
+ "modalities": {
1658
+ "input": [
1659
+ "text",
1660
+ "image",
1661
+ "video"
1662
+ ],
1663
+ "output": [
1664
+ "text"
1665
+ ]
1075
1666
  }
1076
1667
  },
1077
1668
  {
@@ -1092,7 +1683,17 @@
1092
1683
  },
1093
1684
  "limit": {
1094
1685
  "context": 262144,
1095
- "output": 65536
1686
+ "output": 32768
1687
+ },
1688
+ "attachment": true,
1689
+ "modalities": {
1690
+ "input": [
1691
+ "text",
1692
+ "image"
1693
+ ],
1694
+ "output": [
1695
+ "text"
1696
+ ]
1096
1697
  }
1097
1698
  },
1098
1699
  {
@@ -1114,6 +1715,17 @@
1114
1715
  "limit": {
1115
1716
  "context": 1000000,
1116
1717
  "output": 65536
1718
+ },
1719
+ "attachment": true,
1720
+ "modalities": {
1721
+ "input": [
1722
+ "text",
1723
+ "image",
1724
+ "video"
1725
+ ],
1726
+ "output": [
1727
+ "text"
1728
+ ]
1117
1729
  }
1118
1730
  },
1119
1731
  {
@@ -1136,6 +1748,17 @@
1136
1748
  "limit": {
1137
1749
  "context": 1000000,
1138
1750
  "output": 65536
1751
+ },
1752
+ "attachment": true,
1753
+ "modalities": {
1754
+ "input": [
1755
+ "text",
1756
+ "image",
1757
+ "video"
1758
+ ],
1759
+ "output": [
1760
+ "text"
1761
+ ]
1139
1762
  }
1140
1763
  },
1141
1764
  {
@@ -1152,6 +1775,15 @@
1152
1775
  "limit": {
1153
1776
  "context": 1000000,
1154
1777
  "output": 131072
1778
+ },
1779
+ "attachment": false,
1780
+ "modalities": {
1781
+ "input": [
1782
+ "text"
1783
+ ],
1784
+ "output": [
1785
+ "text"
1786
+ ]
1155
1787
  }
1156
1788
  },
1157
1789
  {
@@ -1168,6 +1800,17 @@
1168
1800
  "limit": {
1169
1801
  "context": 256000,
1170
1802
  "output": 65536
1803
+ },
1804
+ "attachment": true,
1805
+ "modalities": {
1806
+ "input": [
1807
+ "text",
1808
+ "image",
1809
+ "video"
1810
+ ],
1811
+ "output": [
1812
+ "text"
1813
+ ]
1171
1814
  }
1172
1815
  },
1173
1816
  {
@@ -1184,6 +1827,15 @@
1184
1827
  "limit": {
1185
1828
  "context": 262144,
1186
1829
  "output": 65536
1830
+ },
1831
+ "attachment": false,
1832
+ "modalities": {
1833
+ "input": [
1834
+ "text"
1835
+ ],
1836
+ "output": [
1837
+ "text"
1838
+ ]
1187
1839
  }
1188
1840
  },
1189
1841
  {
@@ -1199,6 +1851,15 @@
1199
1851
  "limit": {
1200
1852
  "context": 262144,
1201
1853
  "output": 65536
1854
+ },
1855
+ "attachment": false,
1856
+ "modalities": {
1857
+ "input": [
1858
+ "text"
1859
+ ],
1860
+ "output": [
1861
+ "text"
1862
+ ]
1202
1863
  }
1203
1864
  },
1204
1865
  {
@@ -1220,6 +1881,15 @@
1220
1881
  "limit": {
1221
1882
  "context": 1048576,
1222
1883
  "output": 65536
1884
+ },
1885
+ "attachment": false,
1886
+ "modalities": {
1887
+ "input": [
1888
+ "text"
1889
+ ],
1890
+ "output": [
1891
+ "text"
1892
+ ]
1223
1893
  }
1224
1894
  }
1225
1895
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/opencode-commandcode",
3
- "version": "0.6.1",
3
+ "version": "0.7.1",
4
4
  "description": "Command Code API provider for opencode — use Claude, GPT, Gemini, DeepSeek, Qwen, Kimi, GLM, MiniMax, and Step models via Command Code",
5
5
  "keywords": [
6
6
  "ai",
@@ -69,7 +69,7 @@
69
69
  "catalog:ci": "bun run scripts/catalog-sync-ci.ts"
70
70
  },
71
71
  "devDependencies": {
72
- "@semantic-release/commit-analyzer": "13.0.1",
72
+ "@semantic-release/exec": "7.1.0",
73
73
  "@semantic-release/github": "12.0.9",
74
74
  "@semantic-release/npm": "13.1.5",
75
75
  "@semantic-release/release-notes-generator": "14.1.1",
package/src/catalog.ts CHANGED
@@ -15,6 +15,8 @@ export interface ModelEntry {
15
15
  tool_call: boolean;
16
16
  cost: { input: number; output: number; cache_read?: number; cache_write?: number };
17
17
  limit: { context: number; output: number };
18
+ attachment?: boolean;
19
+ modalities?: { input: string[]; output: string[] };
18
20
  }
19
21
 
20
22
  export interface CostEntry {
@@ -38,6 +40,8 @@ export interface SnEntry {
38
40
  reasoning?: boolean;
39
41
  reasoningEfforts?: string[];
40
42
  contextWindow?: number;
43
+ inputModalities?: string[];
44
+ maxOutputTokens?: number;
41
45
  }
42
46
 
43
47
  export interface ResolvedCommandCodePackage {
@@ -484,11 +488,21 @@ export function buildModelEntry(
484
488
  cost = { input: 0.5, output: 2 };
485
489
  }
486
490
 
487
- const limit = entry.contextWindow
488
- ? { context: entry.contextWindow, output: FALLBACK_LIMITS[entry.id]?.output ?? 65536 }
489
- : (FALLBACK_LIMITS[entry.id] ?? { context: 200000, output: 65536 });
491
+ const fallback = FALLBACK_LIMITS[entry.id];
492
+ const limit = {
493
+ context: entry.contextWindow ?? fallback?.context ?? 200000,
494
+ output: entry.maxOutputTokens ?? fallback?.output ?? 65536,
495
+ };
490
496
 
491
497
  const efforts = entry.reasoningEfforts?.length ? [...entry.reasoningEfforts] : undefined;
498
+ const input = entry.inputModalities?.filter((x) => typeof x === "string") ?? [];
499
+ const fromCli =
500
+ input.length > 0
501
+ ? {
502
+ attachment: input.includes("image"),
503
+ modalities: { input: [...input], output: ["text"] },
504
+ }
505
+ : {};
492
506
 
493
507
  return {
494
508
  id: entry.id,
@@ -499,6 +513,7 @@ export function buildModelEntry(
499
513
  tool_call: true,
500
514
  cost,
501
515
  limit,
516
+ ...fromCli,
502
517
  };
503
518
  }
504
519
 
@@ -740,6 +755,8 @@ export function generateOpencodeModels(entries: ModelEntry[]): Record<string, un
740
755
  name: entry.name,
741
756
  reasoning: entry.reasoning,
742
757
  tool_call: entry.tool_call,
758
+ attachment: entry.attachment ?? false,
759
+ modalities: entry.modalities ?? { input: ["text"], output: ["text"] },
743
760
  cost: costObj,
744
761
  limit: entry.limit,
745
762
  };
@@ -2,17 +2,22 @@ import type { ModelEntry } from "./catalog.js";
2
2
 
3
3
  export const MODELS_DEV_URL = "https://models.dev/api.json";
4
4
  export const FREE_COST = { input: 0, output: 0 } as const;
5
+ export const TEXT_ONLY_MODALITIES = { input: ["text"], output: ["text"] } as const;
5
6
 
6
7
  export type ModelsDevRow = {
7
8
  id: string;
8
9
  name: string;
9
10
  cost: { input: number; output: number; cache_read?: number; cache_write?: number };
11
+ attachment?: boolean;
12
+ modalities?: { input: string[]; output: string[] };
10
13
  };
11
14
 
12
15
  type ModelsDevModel = {
13
16
  id?: string;
14
17
  name?: string;
15
18
  cost?: { input?: number; output?: number; cache_read?: number; cache_write?: number };
19
+ attachment?: boolean;
20
+ modalities?: { input?: string[]; output?: string[] };
16
21
  };
17
22
 
18
23
  type ModelsDevProvider = { models?: Record<string, ModelsDevModel> };
@@ -42,7 +47,17 @@ export function parseModelsDev(json: string): ModelsDevRow[] {
42
47
  const cost: ModelsDevRow["cost"] = { input: model.cost.input, output: model.cost.output };
43
48
  if (model.cost.cache_read !== undefined) cost.cache_read = model.cost.cache_read;
44
49
  if (model.cost.cache_write !== undefined) cost.cache_write = model.cost.cache_write;
45
- rows.push({ id: model.id, name: model.name ?? model.id, cost });
50
+ const row: ModelsDevRow = { id: model.id, name: model.name ?? model.id, cost };
51
+ if (typeof model.attachment === "boolean") row.attachment = model.attachment;
52
+ const input = model.modalities?.input?.filter((x) => typeof x === "string");
53
+ const output = model.modalities?.output?.filter((x) => typeof x === "string");
54
+ if (input?.length || output?.length) {
55
+ row.modalities = {
56
+ input: input?.length ? input : [...TEXT_ONLY_MODALITIES.input],
57
+ output: output?.length ? output : [...TEXT_ONLY_MODALITIES.output],
58
+ };
59
+ }
60
+ rows.push(row);
46
61
  }
47
62
  }
48
63
  return rows;
@@ -86,6 +101,43 @@ export function applyFreeCosts(
86
101
  return filled;
87
102
  }
88
103
 
104
+ function textOnly(): { input: string[]; output: string[] } {
105
+ return { input: [...TEXT_ONLY_MODALITIES.input], output: [...TEXT_ONLY_MODALITIES.output] };
106
+ }
107
+
108
+ export function applyModelsDevModalities(models: ModelEntry[], rows: ModelsDevRow[]): number {
109
+ const index = indexRows(rows);
110
+ let filled = 0;
111
+ for (const model of models) {
112
+ const row = findRow(model, index);
113
+ const current = model.modalities;
114
+ if (current && model.attachment !== undefined) {
115
+ const extra = row?.modalities?.input?.filter((x) => !current.input.includes(x)) ?? [];
116
+ if (extra.length > 0) {
117
+ model.modalities = {
118
+ input: [...current.input, ...extra],
119
+ output: [...current.output],
120
+ };
121
+ if (model.modalities.input.includes("image")) model.attachment = true;
122
+ filled++;
123
+ }
124
+ continue;
125
+ }
126
+ if (row && (row.modalities || row.attachment !== undefined)) {
127
+ const modalities = row.modalities
128
+ ? { input: [...row.modalities.input], output: [...row.modalities.output] }
129
+ : textOnly();
130
+ model.modalities = modalities;
131
+ model.attachment = row.attachment ?? modalities.input.includes("image");
132
+ filled++;
133
+ } else {
134
+ model.attachment = false;
135
+ model.modalities = textOnly();
136
+ }
137
+ }
138
+ return filled;
139
+ }
140
+
89
141
  export function applyModelsDevCosts(
90
142
  models: ModelEntry[],
91
143
  rows: ModelsDevRow[],