@eduwork/dsh-oidc 0.2.3 → 0.3.0-dev.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.
Files changed (84) hide show
  1. package/CHANGELOG.en.md +6 -38
  2. package/CHANGELOG.md +7 -39
  3. package/CODE_OF_CONDUCT.en.md +1 -1
  4. package/CODE_OF_CONDUCT.md +1 -1
  5. package/CONTRIBUTING.en.md +1 -1
  6. package/CONTRIBUTING.md +1 -1
  7. package/README.md +21 -130
  8. package/README_EN.md +36 -0
  9. package/SECURITY.en.md +1 -1
  10. package/SECURITY.md +1 -1
  11. package/SUPPORT.en.md +1 -1
  12. package/SUPPORT.md +1 -1
  13. package/docs/EDUWORK-MIGRATION.en.md +3 -31
  14. package/docs/EDUWORK-MIGRATION.md +3 -31
  15. package/docs/account-extensions.en.md +6 -6
  16. package/docs/account-extensions.md +3 -3
  17. package/docs/architecture.en.md +12 -117
  18. package/docs/architecture.md +12 -118
  19. package/docs/compatibility.en.md +6 -62
  20. package/docs/compatibility.md +6 -62
  21. package/docs/decisions/0001-one-plugin-composition-boundary.en.md +2 -2
  22. package/docs/decisions/0001-one-plugin-composition-boundary.md +2 -2
  23. package/docs/desktop-host.en.md +54 -55
  24. package/docs/desktop-host.md +63 -64
  25. package/docs/development.en.md +44 -44
  26. package/docs/development.md +6 -6
  27. package/docs/dsh-integration.en.md +13 -48
  28. package/docs/dsh-integration.md +14 -49
  29. package/docs/ecnu-reference.en.md +4 -61
  30. package/docs/ecnu-reference.md +4 -61
  31. package/docs/enterprise-profile.en.md +10 -31
  32. package/docs/enterprise-profile.md +11 -32
  33. package/docs/gateway-auth/README.md +168 -0
  34. package/docs/gateway-auth/README_EN.md +70 -0
  35. package/docs/gateway-auth/experimental-oidc-llm.en.md +53 -0
  36. package/docs/gateway-auth/experimental-oidc-llm.md +53 -0
  37. package/docs/gateway-auth/litellm-setup.en.md +114 -0
  38. package/docs/gateway-auth/litellm-setup.md +114 -0
  39. package/docs/gateway-auth/oidc-llm-draft.en.md +141 -0
  40. package/docs/gateway-auth/oidc-llm-draft.md +141 -0
  41. package/docs/getting-started.en.md +17 -122
  42. package/docs/getting-started.md +16 -225
  43. package/docs/key-binding-protocol.en.md +10 -220
  44. package/docs/key-binding-protocol.md +10 -220
  45. package/docs/oidc-interoperability.en.md +1 -1
  46. package/docs/oidc-interoperability.md +1 -1
  47. package/docs/open-integration.en.md +11 -0
  48. package/docs/open-integration.md +11 -0
  49. package/docs/public-resource-protocol.en.md +8 -44
  50. package/docs/public-resource-protocol.md +8 -43
  51. package/docs/release-checklist.en.md +7 -61
  52. package/docs/release-checklist.md +7 -61
  53. package/docs/security-model.en.md +10 -132
  54. package/docs/security-model.md +10 -132
  55. package/docs/server-integration-contract.en.md +12 -811
  56. package/docs/server-integration-contract.md +12 -823
  57. package/examples/ecnu.enterprise-profile.example.json +14 -19
  58. package/examples/enterprise-profile.example.json +73 -78
  59. package/examples/identity-only.example.json +1 -1
  60. package/examples/litellm.enterprise-profile.example.json +9 -0
  61. package/examples/oidc-llm.enterprise-profile.example.json +12 -0
  62. package/examples/resources-discovery.example.json +6 -9
  63. package/lib/callback-page.js +5 -5
  64. package/lib/client.js +31 -48
  65. package/lib/desktop-oidc.js +7 -11
  66. package/lib/gateway-backend.js +443 -0
  67. package/lib/gateway-protocol.js +6 -0
  68. package/lib/index.js +14 -15
  69. package/lib/litellm-protocol.js +117 -0
  70. package/lib/model-resource-transport.js +19 -0
  71. package/lib/oidc-llm-protocol.js +88 -0
  72. package/lib/oidc.js +37 -323
  73. package/lib/profile.js +34 -40
  74. package/lib/provider/authorization-scope.js +46 -0
  75. package/lib/provider/index.js +11 -2
  76. package/lib/provider/transforms.js +0 -1
  77. package/lib/typert-schemas.js +1 -1
  78. package/lib/typert.host.js +38 -38
  79. package/lib/typert.remote-client.js +37 -37
  80. package/package.json +7 -6
  81. package/protocol/openapi.yaml +33 -240
  82. package/protocol/resources.openapi.yaml +8 -9
  83. package/schema/enterprise-profile.v1alpha1.schema.json +595 -193
  84. package/README.en.md +0 -186
@@ -1,193 +1,595 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://github.com/freedomkk-qfeng/dsh-oidc/schema/enterprise-profile.v1alpha1.schema.json",
4
- "title": "dsh-oidc Enterprise Profile v1alpha1",
5
- "type": "object",
6
- "additionalProperties": false,
7
- "required": ["schemaVersion", "id", "displayName", "oidc"],
8
- "dependentRequired": { "keyBinding": ["provider"], "provider": ["keyBinding"] },
9
- "properties": {
10
- "schemaVersion": { "const": "dsh-oidc/v1alpha1" },
11
- "id": { "$ref": "#/$defs/id" },
12
- "displayName": { "$ref": "#/$defs/nonEmpty120" },
13
- "organization": { "$ref": "#/$defs/nonEmpty120" },
14
- "nativeInstitutionID": { "type": "string", "minLength": 1, "maxLength": 64 },
15
- "allowInsecureDevelopment": { "type": "boolean", "default": false },
16
- "insecureDevelopmentOrigin": { "type": "string", "minLength": 8, "maxLength": 2048, "pattern": "^http://" },
17
- "brand": { "$ref": "#/$defs/brand" },
18
- "oidc": { "$ref": "#/$defs/oidc" },
19
- "keyBinding": { "$ref": "#/$defs/keyBinding" },
20
- "provider": { "$ref": "#/$defs/provider" }
21
- },
22
- "allOf": [
23
- {
24
- "if": {
25
- "not": {
26
- "type": "object",
27
- "properties": { "insecureDevelopmentOrigin": {} },
28
- "required": ["insecureDevelopmentOrigin"]
29
- }
30
- },
31
- "then": {
32
- "type": "object",
33
- "properties": {
34
- "oidc": { "type": "object", "properties": { "issuer": { "$ref": "#/$defs/secureEndpointURL" } } },
35
- "keyBinding": { "type": "object", "properties": { "baseURL": { "$ref": "#/$defs/secureEndpointURL" } } },
36
- "provider": { "type": "object", "properties": { "baseURL": { "$ref": "#/$defs/secureEndpointURL" } } }
37
- }
38
- }
39
- },
40
- {
41
- "if": {
42
- "type": "object",
43
- "properties": { "insecureDevelopmentOrigin": {} },
44
- "required": ["insecureDevelopmentOrigin"]
45
- },
46
- "then": { "type": "object", "properties": { "allowInsecureDevelopment": { "const": true } } }
47
- }
48
- ],
49
- "$defs": {
50
- "id": { "type": "string", "pattern": "^[a-z][a-z0-9-]{0,63}$" },
51
- "nonEmpty120": { "type": "string", "minLength": 1, "maxLength": 120, "pattern": "^\\S(?:.*\\S)?$" },
52
- "positiveInteger": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 },
53
- "httpsURL": { "type": "string", "minLength": 9, "maxLength": 2048, "pattern": "^https://" },
54
- "secureEndpointURL": { "type": "string", "minLength": 9, "maxLength": 2048, "pattern": "^(https://|http://(localhost|127\\.0\\.0\\.1|\\[::1\\])(?=[:/]))" },
55
- "endpointURL": { "type": "string", "minLength": 8, "maxLength": 2048, "pattern": "^(https://|http://)" },
56
- "brand": {
57
- "type": "object",
58
- "additionalProperties": false,
59
- "properties": {
60
- "productName": { "type": "string", "minLength": 1, "maxLength": 80 },
61
- "organizationName": { "$ref": "#/$defs/nonEmpty120" },
62
- "mark": { "type": "string", "minLength": 1, "maxLength": 4 },
63
- "logoURL": { "type": "string", "minLength": 9, "maxLength": 131072, "pattern": "^(https://|data:image/(png|webp);base64,)" },
64
- "primaryColor": { "type": "string", "pattern": "^#[0-9a-fA-F]{6}$" },
65
- "loginTitle": { "type": "string", "minLength": 1, "maxLength": 120 },
66
- "loginDescription": { "type": "string", "minLength": 1, "maxLength": 500 },
67
- "supportURL": { "$ref": "#/$defs/httpsURL" }
68
- }
69
- },
70
- "oidc": {
71
- "type": "object",
72
- "additionalProperties": false,
73
- "required": ["issuer", "clientId", "scopes"],
74
- "properties": {
75
- "issuer": { "$ref": "#/$defs/endpointURL" },
76
- "clientId": { "type": "string", "minLength": 1, "maxLength": 256 },
77
- "scopes": {
78
- "type": "array",
79
- "minItems": 2,
80
- "maxItems": 64,
81
- "uniqueItems": true,
82
- "allOf": [
83
- { "contains": { "const": "openid" } },
84
- { "contains": { "const": "profile" } }
85
- ],
86
- "items": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^\\S+$" }
87
- }
88
- }
89
- },
90
- "keyBinding": {
91
- "type": "object",
92
- "additionalProperties": false,
93
- "required": ["baseURL"],
94
- "properties": {
95
- "type": { "enum": ["worker-user-center-v1", "eduwork-resources-v1"], "default": "worker-user-center-v1" },
96
- "baseURL": { "$ref": "#/$defs/endpointURL" },
97
- "credentialRef": { "type": "string", "default": "EDUWORK_API_KEY", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "maxLength": 128 }
98
- }
99
- },
100
- "compat": {
101
- "type": "object",
102
- "additionalProperties": false,
103
- "properties": {
104
- "supportsDeveloperRole": { "type": "boolean" },
105
- "supportsStore": { "type": "boolean" },
106
- "supportsReasoningEffort": { "type": "boolean" },
107
- "supportsUsageInStreaming": { "type": "boolean" },
108
- "maxTokensField": { "enum": ["max_completion_tokens", "max_tokens"] },
109
- "supportsStrictMode": { "type": "boolean" },
110
- "supportsLongCacheRetention": { "type": "boolean" },
111
- "thinkingFormat": { "enum": ["openai", "deepseek", "openrouter", "together", "baseten", "zai", "qwen", "chat-template", "qwen-chat-template", "string-thinking", "ant-ling"] },
112
- "requiresReasoningContentOnAssistantMessages": { "type": "boolean" }
113
- }
114
- },
115
- "retryPolicy": {
116
- "type": "object",
117
- "additionalProperties": false,
118
- "required": ["mode"],
119
- "properties": {
120
- "mode": { "enum": ["normal", "always"] },
121
- "maxRetries": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
122
- "retryableCodes": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string", "minLength": 1, "maxLength": 128 } },
123
- "backoff": {
124
- "type": "object",
125
- "additionalProperties": false,
126
- "properties": {
127
- "initialDelayMs": { "type": "number", "exclusiveMinimum": 0, "maximum": 2147483647 },
128
- "maxDelayMs": { "type": "number", "exclusiveMinimum": 0, "maximum": 2147483647 },
129
- "jitterRatio": { "type": "number", "minimum": 0, "maximum": 1 }
130
- }
131
- }
132
- }
133
- },
134
- "model": {
135
- "type": "object",
136
- "additionalProperties": false,
137
- "required": ["id"],
138
- "properties": {
139
- "id": { "type": "string", "minLength": 1, "maxLength": 256 },
140
- "name": { "type": "string", "minLength": 1, "maxLength": 256 },
141
- "input": { "type": "array", "minItems": 1, "maxItems": 2, "uniqueItems": true, "items": { "enum": ["text", "image"] } },
142
- "contextWindow": { "$ref": "#/$defs/positiveInteger" },
143
- "maxTokens": { "$ref": "#/$defs/positiveInteger" },
144
- "reasoning": { "type": "boolean" },
145
- "defaultReasoningEffort": { "enum": ["off", "minimal", "low", "medium", "high", "xhigh", "max"] },
146
- "reasoningEfforts": {
147
- "oneOf": [
148
- { "const": false },
149
- {
150
- "type": "object",
151
- "minProperties": 1,
152
- "maxProperties": 7,
153
- "additionalProperties": false,
154
- "properties": {
155
- "off": { "type": ["string", "null"], "minLength": 1, "maxLength": 32 },
156
- "minimal": { "type": "string", "minLength": 1, "maxLength": 32 },
157
- "low": { "type": "string", "minLength": 1, "maxLength": 32 },
158
- "medium": { "type": "string", "minLength": 1, "maxLength": 32 },
159
- "high": { "type": "string", "minLength": 1, "maxLength": 32 },
160
- "xhigh": { "type": "string", "minLength": 1, "maxLength": 32 },
161
- "max": { "type": "string", "minLength": 1, "maxLength": 32 }
162
- }
163
- }
164
- ]
165
- },
166
- "compat": { "$ref": "#/$defs/compat" }
167
- }
168
- },
169
- "provider": {
170
- "type": "object",
171
- "additionalProperties": false,
172
- "required": ["id", "adapter", "baseURL"],
173
- "allOf": [{ "if": { "required": ["modelSource"], "properties": { "modelSource": { "const": "discovery" } } }, "else": { "required": ["models"], "properties": { "models": { "type": "array", "minItems": 1 } } } }],
174
- "properties": {
175
- "id": { "$ref": "#/$defs/id" },
176
- "displayName": { "$ref": "#/$defs/nonEmpty120" },
177
- "adapter": { "const": "openai-compatible" },
178
- "baseURL": { "$ref": "#/$defs/endpointURL" },
179
- "reasoning": { "enum": ["off", "minimal", "low", "medium", "high", "xhigh", "max"] },
180
- "defaultContextWindow": { "$ref": "#/$defs/positiveInteger" },
181
- "defaultMaxTokens": { "$ref": "#/$defs/positiveInteger" },
182
- "maxRequestImageBytes": { "$ref": "#/$defs/positiveInteger" },
183
- "requestImagePixelBudget": { "$ref": "#/$defs/positiveInteger" },
184
- "requestImageMaxBytes": { "$ref": "#/$defs/positiveInteger" },
185
- "streamIdleTimeoutMs": { "$ref": "#/$defs/positiveInteger" },
186
- "retryPolicy": { "$ref": "#/$defs/retryPolicy" },
187
- "compat": { "$ref": "#/$defs/compat" },
188
- "modelSource": { "enum": ["profile", "discovery"], "default": "profile" },
189
- "models": { "type": "array", "minItems": 0, "maxItems": 128, "items": { "$ref": "#/$defs/model" } }
190
- }
191
- }
192
- }
193
- }
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/ecnu/EduWork/schema/enterprise-profile.v1alpha1.schema.json",
4
+ "title": "dsh-oidc Enterprise Profile v1alpha1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "schemaVersion",
9
+ "id",
10
+ "displayName"
11
+ ],
12
+ "oneOf": [
13
+ {
14
+ "required": [
15
+ "oidc"
16
+ ],
17
+ "properties": {
18
+ "oidc": {},
19
+ "auth": false,
20
+ "provider": false
21
+ }
22
+ },
23
+ {
24
+ "required": [
25
+ "auth"
26
+ ],
27
+ "properties": {
28
+ "auth": {},
29
+ "oidc": false,
30
+ "provider": {
31
+ "$ref": "#/$defs/gatewayProvider"
32
+ }
33
+ }
34
+ }
35
+ ],
36
+ "properties": {
37
+ "schemaVersion": {
38
+ "const": "dsh-oidc/v1alpha1"
39
+ },
40
+ "id": {
41
+ "$ref": "#/$defs/id"
42
+ },
43
+ "displayName": {
44
+ "$ref": "#/$defs/nonEmpty120"
45
+ },
46
+ "organization": {
47
+ "$ref": "#/$defs/nonEmpty120"
48
+ },
49
+ "nativeInstitutionID": {
50
+ "type": "string",
51
+ "minLength": 1,
52
+ "maxLength": 64
53
+ },
54
+ "allowInsecureDevelopment": {
55
+ "type": "boolean",
56
+ "default": false
57
+ },
58
+ "insecureDevelopmentOrigin": {
59
+ "type": "string",
60
+ "minLength": 8,
61
+ "maxLength": 2048,
62
+ "pattern": "^http://"
63
+ },
64
+ "brand": {
65
+ "$ref": "#/$defs/brand"
66
+ },
67
+ "oidc": {
68
+ "$ref": "#/$defs/oidc"
69
+ },
70
+ "auth": {
71
+ "$ref": "#/$defs/gatewayAuth"
72
+ },
73
+ "provider": {
74
+ "type": "object"
75
+ }
76
+ },
77
+ "allOf": [
78
+ {
79
+ "if": {
80
+ "not": {
81
+ "type": "object",
82
+ "properties": {
83
+ "insecureDevelopmentOrigin": {}
84
+ },
85
+ "required": [
86
+ "insecureDevelopmentOrigin"
87
+ ]
88
+ }
89
+ },
90
+ "then": {
91
+ "type": "object",
92
+ "properties": {
93
+ "oidc": {
94
+ "type": "object",
95
+ "properties": {
96
+ "issuer": {
97
+ "$ref": "#/$defs/secureEndpointURL"
98
+ }
99
+ }
100
+ },
101
+ "auth": {
102
+ "type": "object",
103
+ "properties": {
104
+ "discoveryUrl": {
105
+ "$ref": "#/$defs/secureEndpointURL"
106
+ },
107
+ "expectedIssuer": {
108
+ "$ref": "#/$defs/secureEndpointURL"
109
+ }
110
+ }
111
+ },
112
+ "provider": {
113
+ "type": "object",
114
+ "properties": {
115
+ "baseURL": {
116
+ "$ref": "#/$defs/secureEndpointURL"
117
+ }
118
+ }
119
+ }
120
+ }
121
+ }
122
+ },
123
+ {
124
+ "if": {
125
+ "type": "object",
126
+ "properties": {
127
+ "insecureDevelopmentOrigin": {}
128
+ },
129
+ "required": [
130
+ "insecureDevelopmentOrigin"
131
+ ]
132
+ },
133
+ "then": {
134
+ "type": "object",
135
+ "properties": {
136
+ "allowInsecureDevelopment": {
137
+ "const": true
138
+ }
139
+ }
140
+ }
141
+ }
142
+ ],
143
+ "$defs": {
144
+ "gatewayAuth": {
145
+ "type": "object",
146
+ "additionalProperties": false,
147
+ "required": [
148
+ "discoveryUrl"
149
+ ],
150
+ "properties": {
151
+ "discoveryUrl": {
152
+ "$ref": "#/$defs/endpointURL"
153
+ },
154
+ "expectedIssuer": {
155
+ "$ref": "#/$defs/endpointURL"
156
+ },
157
+ "experimentalOidcLlm": {
158
+ "type": "boolean"
159
+ },
160
+ "clientId": {
161
+ "type": "string",
162
+ "minLength": 1,
163
+ "maxLength": 256
164
+ },
165
+ "identityMode": {
166
+ "enum": [
167
+ "oauth",
168
+ "oidc"
169
+ ]
170
+ }
171
+ },
172
+ "allOf": [
173
+ {
174
+ "if": {
175
+ "required": [
176
+ "experimentalOidcLlm"
177
+ ],
178
+ "properties": {
179
+ "experimentalOidcLlm": {
180
+ "const": true
181
+ }
182
+ }
183
+ },
184
+ "then": {
185
+ "required": [
186
+ "clientId",
187
+ "identityMode"
188
+ ],
189
+ "properties": {
190
+ "clientId": {},
191
+ "identityMode": {}
192
+ }
193
+ },
194
+ "else": {
195
+ "properties": {
196
+ "clientId": false,
197
+ "identityMode": false,
198
+ "discoveryUrl": {
199
+ "$ref": "#/$defs/secureEndpointURL"
200
+ },
201
+ "expectedIssuer": {
202
+ "$ref": "#/$defs/secureEndpointURL"
203
+ }
204
+ }
205
+ }
206
+ }
207
+ ]
208
+ },
209
+ "gatewayProvider": {
210
+ "type": "object",
211
+ "additionalProperties": false,
212
+ "properties": {
213
+ "id": {
214
+ "$ref": "#/$defs/id"
215
+ },
216
+ "displayName": {
217
+ "$ref": "#/$defs/nonEmpty120"
218
+ },
219
+ "adapter": {
220
+ "const": "openai-compatible"
221
+ },
222
+ "reasoning": {
223
+ "enum": [
224
+ "off",
225
+ "minimal",
226
+ "low",
227
+ "medium",
228
+ "high",
229
+ "xhigh",
230
+ "max"
231
+ ]
232
+ },
233
+ "defaultContextWindow": {
234
+ "$ref": "#/$defs/positiveInteger"
235
+ },
236
+ "defaultMaxTokens": {
237
+ "$ref": "#/$defs/positiveInteger"
238
+ },
239
+ "maxRequestImageBytes": {
240
+ "$ref": "#/$defs/positiveInteger"
241
+ },
242
+ "requestImagePixelBudget": {
243
+ "$ref": "#/$defs/positiveInteger"
244
+ },
245
+ "requestImageMaxBytes": {
246
+ "$ref": "#/$defs/positiveInteger"
247
+ },
248
+ "streamIdleTimeoutMs": {
249
+ "$ref": "#/$defs/positiveInteger"
250
+ },
251
+ "retryPolicy": {
252
+ "$ref": "#/$defs/retryPolicy"
253
+ },
254
+ "compat": {
255
+ "$ref": "#/$defs/compat"
256
+ },
257
+ "modelSource": {
258
+ "const": "discovery"
259
+ },
260
+ "models": {
261
+ "type": "array",
262
+ "minItems": 0,
263
+ "maxItems": 128,
264
+ "items": {
265
+ "$ref": "#/$defs/model"
266
+ }
267
+ }
268
+ }
269
+ },
270
+ "id": {
271
+ "type": "string",
272
+ "pattern": "^[a-z][a-z0-9-]{0,63}$"
273
+ },
274
+ "nonEmpty120": {
275
+ "type": "string",
276
+ "minLength": 1,
277
+ "maxLength": 120,
278
+ "pattern": "^\\S(?:.*\\S)?$"
279
+ },
280
+ "positiveInteger": {
281
+ "type": "integer",
282
+ "minimum": 1,
283
+ "maximum": 9007199254740991
284
+ },
285
+ "httpsURL": {
286
+ "type": "string",
287
+ "minLength": 9,
288
+ "maxLength": 2048,
289
+ "pattern": "^https://"
290
+ },
291
+ "secureEndpointURL": {
292
+ "type": "string",
293
+ "minLength": 9,
294
+ "maxLength": 2048,
295
+ "pattern": "^(https://|http://(localhost|127\\.0\\.0\\.1|\\[::1\\])(?=[:/]))"
296
+ },
297
+ "endpointURL": {
298
+ "type": "string",
299
+ "minLength": 8,
300
+ "maxLength": 2048,
301
+ "pattern": "^(https://|http://)"
302
+ },
303
+ "brand": {
304
+ "type": "object",
305
+ "additionalProperties": false,
306
+ "properties": {
307
+ "productName": {
308
+ "type": "string",
309
+ "minLength": 1,
310
+ "maxLength": 80
311
+ },
312
+ "organizationName": {
313
+ "$ref": "#/$defs/nonEmpty120"
314
+ },
315
+ "mark": {
316
+ "type": "string",
317
+ "minLength": 1,
318
+ "maxLength": 4
319
+ },
320
+ "logoURL": {
321
+ "type": "string",
322
+ "minLength": 9,
323
+ "maxLength": 131072,
324
+ "pattern": "^(https://|data:image/(png|webp);base64,)"
325
+ },
326
+ "primaryColor": {
327
+ "type": "string",
328
+ "pattern": "^#[0-9a-fA-F]{6}$"
329
+ },
330
+ "loginTitle": {
331
+ "type": "string",
332
+ "minLength": 1,
333
+ "maxLength": 120
334
+ },
335
+ "loginDescription": {
336
+ "type": "string",
337
+ "minLength": 1,
338
+ "maxLength": 500
339
+ },
340
+ "supportURL": {
341
+ "$ref": "#/$defs/httpsURL"
342
+ }
343
+ }
344
+ },
345
+ "oidc": {
346
+ "type": "object",
347
+ "additionalProperties": false,
348
+ "required": [
349
+ "issuer",
350
+ "clientId",
351
+ "scopes"
352
+ ],
353
+ "properties": {
354
+ "issuer": {
355
+ "$ref": "#/$defs/endpointURL"
356
+ },
357
+ "clientId": {
358
+ "type": "string",
359
+ "minLength": 1,
360
+ "maxLength": 256
361
+ },
362
+ "scopes": {
363
+ "type": "array",
364
+ "minItems": 2,
365
+ "maxItems": 64,
366
+ "uniqueItems": true,
367
+ "allOf": [
368
+ {
369
+ "contains": {
370
+ "const": "openid"
371
+ }
372
+ },
373
+ {
374
+ "contains": {
375
+ "const": "profile"
376
+ }
377
+ }
378
+ ],
379
+ "items": {
380
+ "type": "string",
381
+ "minLength": 1,
382
+ "maxLength": 128,
383
+ "pattern": "^\\S+$"
384
+ }
385
+ }
386
+ }
387
+ },
388
+ "compat": {
389
+ "type": "object",
390
+ "additionalProperties": false,
391
+ "properties": {
392
+ "supportsDeveloperRole": {
393
+ "type": "boolean"
394
+ },
395
+ "supportsStore": {
396
+ "type": "boolean"
397
+ },
398
+ "supportsReasoningEffort": {
399
+ "type": "boolean"
400
+ },
401
+ "supportsUsageInStreaming": {
402
+ "type": "boolean"
403
+ },
404
+ "maxTokensField": {
405
+ "enum": [
406
+ "max_completion_tokens",
407
+ "max_tokens"
408
+ ]
409
+ },
410
+ "supportsStrictMode": {
411
+ "type": "boolean"
412
+ },
413
+ "supportsLongCacheRetention": {
414
+ "type": "boolean"
415
+ },
416
+ "thinkingFormat": {
417
+ "enum": [
418
+ "openai",
419
+ "deepseek",
420
+ "openrouter",
421
+ "together",
422
+ "baseten",
423
+ "zai",
424
+ "qwen",
425
+ "chat-template",
426
+ "qwen-chat-template",
427
+ "string-thinking",
428
+ "ant-ling"
429
+ ]
430
+ },
431
+ "requiresReasoningContentOnAssistantMessages": {
432
+ "type": "boolean"
433
+ }
434
+ }
435
+ },
436
+ "retryPolicy": {
437
+ "type": "object",
438
+ "additionalProperties": false,
439
+ "required": [
440
+ "mode"
441
+ ],
442
+ "properties": {
443
+ "mode": {
444
+ "enum": [
445
+ "normal",
446
+ "always"
447
+ ]
448
+ },
449
+ "maxRetries": {
450
+ "type": "integer",
451
+ "minimum": 0,
452
+ "maximum": 9007199254740991
453
+ },
454
+ "retryableCodes": {
455
+ "type": "array",
456
+ "minItems": 1,
457
+ "uniqueItems": true,
458
+ "items": {
459
+ "type": "string",
460
+ "minLength": 1,
461
+ "maxLength": 128
462
+ }
463
+ },
464
+ "backoff": {
465
+ "type": "object",
466
+ "additionalProperties": false,
467
+ "properties": {
468
+ "initialDelayMs": {
469
+ "type": "number",
470
+ "exclusiveMinimum": 0,
471
+ "maximum": 2147483647
472
+ },
473
+ "maxDelayMs": {
474
+ "type": "number",
475
+ "exclusiveMinimum": 0,
476
+ "maximum": 2147483647
477
+ },
478
+ "jitterRatio": {
479
+ "type": "number",
480
+ "minimum": 0,
481
+ "maximum": 1
482
+ }
483
+ }
484
+ }
485
+ }
486
+ },
487
+ "model": {
488
+ "type": "object",
489
+ "additionalProperties": false,
490
+ "required": [
491
+ "id"
492
+ ],
493
+ "properties": {
494
+ "id": {
495
+ "type": "string",
496
+ "minLength": 1,
497
+ "maxLength": 256
498
+ },
499
+ "name": {
500
+ "type": "string",
501
+ "minLength": 1,
502
+ "maxLength": 256
503
+ },
504
+ "input": {
505
+ "type": "array",
506
+ "minItems": 1,
507
+ "maxItems": 2,
508
+ "uniqueItems": true,
509
+ "items": {
510
+ "enum": [
511
+ "text",
512
+ "image"
513
+ ]
514
+ }
515
+ },
516
+ "contextWindow": {
517
+ "$ref": "#/$defs/positiveInteger"
518
+ },
519
+ "maxTokens": {
520
+ "$ref": "#/$defs/positiveInteger"
521
+ },
522
+ "reasoning": {
523
+ "type": "boolean"
524
+ },
525
+ "defaultReasoningEffort": {
526
+ "enum": [
527
+ "off",
528
+ "minimal",
529
+ "low",
530
+ "medium",
531
+ "high",
532
+ "xhigh",
533
+ "max"
534
+ ]
535
+ },
536
+ "reasoningEfforts": {
537
+ "oneOf": [
538
+ {
539
+ "const": false
540
+ },
541
+ {
542
+ "type": "object",
543
+ "minProperties": 1,
544
+ "maxProperties": 7,
545
+ "additionalProperties": false,
546
+ "properties": {
547
+ "off": {
548
+ "type": [
549
+ "string",
550
+ "null"
551
+ ],
552
+ "minLength": 1,
553
+ "maxLength": 32
554
+ },
555
+ "minimal": {
556
+ "type": "string",
557
+ "minLength": 1,
558
+ "maxLength": 32
559
+ },
560
+ "low": {
561
+ "type": "string",
562
+ "minLength": 1,
563
+ "maxLength": 32
564
+ },
565
+ "medium": {
566
+ "type": "string",
567
+ "minLength": 1,
568
+ "maxLength": 32
569
+ },
570
+ "high": {
571
+ "type": "string",
572
+ "minLength": 1,
573
+ "maxLength": 32
574
+ },
575
+ "xhigh": {
576
+ "type": "string",
577
+ "minLength": 1,
578
+ "maxLength": 32
579
+ },
580
+ "max": {
581
+ "type": "string",
582
+ "minLength": 1,
583
+ "maxLength": 32
584
+ }
585
+ }
586
+ }
587
+ ]
588
+ },
589
+ "compat": {
590
+ "$ref": "#/$defs/compat"
591
+ }
592
+ }
593
+ }
594
+ }
595
+ }