sla-wizard-plugin-custom-baseurl 1.0.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.
- package/.github/workflows/npm-publish.yml +20 -0
- package/LICENSE +674 -0
- package/README.md +404 -0
- package/index.js +101 -0
- package/package.json +18 -0
- package/src/commands.js +32 -0
- package/src/nginx-transform.js +117 -0
- package/src/sanitize.js +9 -0
- package/test-specs/hpc-oas.yaml +246 -0
- package/test-specs/slas/sla_dgalvan_us_es.yaml +31 -0
- package/test-specs/slas/sla_japarejo_us_es.yaml +31 -0
- package/test-specs/slas/sla_pablofm_us_es.yaml +31 -0
- package/tests/cli-with-plugin.js +13 -0
- package/tests/tests.js +826 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
openapi: 3.0.3
|
|
2
|
+
info:
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
title: LLM-mock API
|
|
5
|
+
description: LLM-mock API with SLA for researchers (normal vs premium).
|
|
6
|
+
contact:
|
|
7
|
+
name: piyook llm-mock
|
|
8
|
+
url: https://github.com/piyook/llm-mock?tab=readme-ov-file
|
|
9
|
+
servers:
|
|
10
|
+
- url: http://localhost:8000
|
|
11
|
+
paths:
|
|
12
|
+
/models/qwen/v1/chat/completions:
|
|
13
|
+
x-nginx-strip: "/models/qwen"
|
|
14
|
+
post:
|
|
15
|
+
summary: Sends a prompt and gets the response
|
|
16
|
+
description: >
|
|
17
|
+
It needs a body with the same OpenAI API format for Chat Completions
|
|
18
|
+
(`model`, `messages`, `temperature`, etc.) y and returns an object containing the response.
|
|
19
|
+
operationId: postChatCompletion
|
|
20
|
+
requestBody:
|
|
21
|
+
required: true
|
|
22
|
+
content:
|
|
23
|
+
application/json:
|
|
24
|
+
schema:
|
|
25
|
+
$ref: '#/components/schemas/ChatCompletionRequest'
|
|
26
|
+
example:
|
|
27
|
+
model: "claude-sonnet-4.6"
|
|
28
|
+
messages:
|
|
29
|
+
- role: "user"
|
|
30
|
+
content: "Hello, how are you?"
|
|
31
|
+
temperature: 1
|
|
32
|
+
top_p: 1
|
|
33
|
+
frequency_penalty: 0
|
|
34
|
+
presence_penalty: 0
|
|
35
|
+
n: 1
|
|
36
|
+
stream: false
|
|
37
|
+
responses:
|
|
38
|
+
'200':
|
|
39
|
+
description: Response of the LLM
|
|
40
|
+
content:
|
|
41
|
+
application/json:
|
|
42
|
+
schema:
|
|
43
|
+
$ref: '#/components/schemas/ChatCompletionResponse'
|
|
44
|
+
default:
|
|
45
|
+
description: Unexpected Error
|
|
46
|
+
content:
|
|
47
|
+
application/json:
|
|
48
|
+
schema:
|
|
49
|
+
$ref: '#/components/schemas/Error'
|
|
50
|
+
/models/chatgpt/v1/chat/completions:
|
|
51
|
+
x-nginx-strip: "/models/chatgpt"
|
|
52
|
+
x-nginx-server-baseurl: http://localhost:8001
|
|
53
|
+
post:
|
|
54
|
+
summary: Sends a prompt and gets the response
|
|
55
|
+
description: >
|
|
56
|
+
It needs a body with the same OpenAI API format for Chat Completions
|
|
57
|
+
(`model`, `messages`, `temperature`, etc.) y and returns an object containing the response.
|
|
58
|
+
operationId: postChatCompletion
|
|
59
|
+
requestBody:
|
|
60
|
+
required: true
|
|
61
|
+
content:
|
|
62
|
+
application/json:
|
|
63
|
+
schema:
|
|
64
|
+
$ref: '#/components/schemas/ChatCompletionRequest'
|
|
65
|
+
example:
|
|
66
|
+
model: "gpt-3.5-turbo"
|
|
67
|
+
messages:
|
|
68
|
+
- role: "user"
|
|
69
|
+
content: "Hello, how are you?"
|
|
70
|
+
temperature: 1
|
|
71
|
+
top_p: 1
|
|
72
|
+
frequency_penalty: 0
|
|
73
|
+
presence_penalty: 0
|
|
74
|
+
n: 1
|
|
75
|
+
stream: false
|
|
76
|
+
responses:
|
|
77
|
+
'200':
|
|
78
|
+
description: Response of the LLM
|
|
79
|
+
content:
|
|
80
|
+
application/json:
|
|
81
|
+
schema:
|
|
82
|
+
$ref: '#/components/schemas/ChatCompletionResponse'
|
|
83
|
+
default:
|
|
84
|
+
description: Unexpected Error
|
|
85
|
+
content:
|
|
86
|
+
application/json:
|
|
87
|
+
schema:
|
|
88
|
+
$ref: '#/components/schemas/Error'
|
|
89
|
+
|
|
90
|
+
/models/claude/v1/chat/completions:
|
|
91
|
+
x-nginx-strip: "/models/claude"
|
|
92
|
+
x-nginx-server-baseurl: http://localhost:8002
|
|
93
|
+
post:
|
|
94
|
+
summary: Sends a prompt and gets the response
|
|
95
|
+
description: >
|
|
96
|
+
It needs a body with the same OpenAI API format for Chat Completions
|
|
97
|
+
(`model`, `messages`, `temperature`, etc.) y and returns an object containing the response.
|
|
98
|
+
operationId: postChatCompletion
|
|
99
|
+
requestBody:
|
|
100
|
+
required: true
|
|
101
|
+
content:
|
|
102
|
+
application/json:
|
|
103
|
+
schema:
|
|
104
|
+
$ref: '#/components/schemas/ChatCompletionRequest'
|
|
105
|
+
example:
|
|
106
|
+
model: "claude-sonnet-4.6"
|
|
107
|
+
messages:
|
|
108
|
+
- role: "user"
|
|
109
|
+
content: "Hello, how are you?"
|
|
110
|
+
temperature: 1
|
|
111
|
+
top_p: 1
|
|
112
|
+
frequency_penalty: 0
|
|
113
|
+
presence_penalty: 0
|
|
114
|
+
n: 1
|
|
115
|
+
stream: false
|
|
116
|
+
responses:
|
|
117
|
+
'200':
|
|
118
|
+
description: Response of the LLM
|
|
119
|
+
content:
|
|
120
|
+
application/json:
|
|
121
|
+
schema:
|
|
122
|
+
$ref: '#/components/schemas/ChatCompletionResponse'
|
|
123
|
+
default:
|
|
124
|
+
description: Unexpected Error
|
|
125
|
+
content:
|
|
126
|
+
application/json:
|
|
127
|
+
schema:
|
|
128
|
+
$ref: '#/components/schemas/Error'
|
|
129
|
+
components:
|
|
130
|
+
schemas:
|
|
131
|
+
ChatCompletionRequest:
|
|
132
|
+
type: object
|
|
133
|
+
required:
|
|
134
|
+
- model
|
|
135
|
+
- messages
|
|
136
|
+
properties:
|
|
137
|
+
model:
|
|
138
|
+
type: string
|
|
139
|
+
example: "Qwen/Qwen2.5-Coder-32B-Instruct"
|
|
140
|
+
messages:
|
|
141
|
+
type: array
|
|
142
|
+
items:
|
|
143
|
+
type: object
|
|
144
|
+
required:
|
|
145
|
+
- role
|
|
146
|
+
- content
|
|
147
|
+
properties:
|
|
148
|
+
role:
|
|
149
|
+
type: string
|
|
150
|
+
enum: [system, user, assistant]
|
|
151
|
+
example: "user"
|
|
152
|
+
content:
|
|
153
|
+
type: string
|
|
154
|
+
example: "Hello, how are you?"
|
|
155
|
+
temperature:
|
|
156
|
+
type: number
|
|
157
|
+
format: float
|
|
158
|
+
example: 1
|
|
159
|
+
top_p:
|
|
160
|
+
type: number
|
|
161
|
+
format: float
|
|
162
|
+
example: 1
|
|
163
|
+
n:
|
|
164
|
+
type: integer
|
|
165
|
+
example: 1
|
|
166
|
+
stream:
|
|
167
|
+
type: boolean
|
|
168
|
+
example: false
|
|
169
|
+
stop:
|
|
170
|
+
oneOf:
|
|
171
|
+
- type: string
|
|
172
|
+
- type: array
|
|
173
|
+
items:
|
|
174
|
+
type: string
|
|
175
|
+
max_tokens:
|
|
176
|
+
type: integer
|
|
177
|
+
example: 100
|
|
178
|
+
presence_penalty:
|
|
179
|
+
type: number
|
|
180
|
+
format: float
|
|
181
|
+
example: 0
|
|
182
|
+
frequency_penalty:
|
|
183
|
+
type: number
|
|
184
|
+
format: float
|
|
185
|
+
example: 0
|
|
186
|
+
|
|
187
|
+
ChatCompletionResponse:
|
|
188
|
+
type: object
|
|
189
|
+
properties:
|
|
190
|
+
id:
|
|
191
|
+
type: string
|
|
192
|
+
example: "chatcmpl-6sf37lXn5paUcuf8UaurpMIKRMsTe"
|
|
193
|
+
object:
|
|
194
|
+
type: string
|
|
195
|
+
example: "chat.completion"
|
|
196
|
+
created:
|
|
197
|
+
type: integer
|
|
198
|
+
format: int64
|
|
199
|
+
example: 1678485525
|
|
200
|
+
model:
|
|
201
|
+
type: string
|
|
202
|
+
example: "Qwen/Qwen2.5-Coder-32B-Instruct"
|
|
203
|
+
usage:
|
|
204
|
+
type: object
|
|
205
|
+
properties:
|
|
206
|
+
prompt_tokens:
|
|
207
|
+
type: integer
|
|
208
|
+
example: 12
|
|
209
|
+
completion_tokens:
|
|
210
|
+
type: integer
|
|
211
|
+
example: 99
|
|
212
|
+
total_tokens:
|
|
213
|
+
type: integer
|
|
214
|
+
example: 111
|
|
215
|
+
choices:
|
|
216
|
+
type: array
|
|
217
|
+
items:
|
|
218
|
+
type: object
|
|
219
|
+
properties:
|
|
220
|
+
index:
|
|
221
|
+
type: integer
|
|
222
|
+
example: 0
|
|
223
|
+
message:
|
|
224
|
+
type: object
|
|
225
|
+
properties:
|
|
226
|
+
role:
|
|
227
|
+
type: string
|
|
228
|
+
example: "assistant"
|
|
229
|
+
content:
|
|
230
|
+
type: string
|
|
231
|
+
example: "Lorem Ipsum text..."
|
|
232
|
+
finish_reason:
|
|
233
|
+
type: string
|
|
234
|
+
example: "stop"
|
|
235
|
+
|
|
236
|
+
Error:
|
|
237
|
+
type: object
|
|
238
|
+
required:
|
|
239
|
+
- code
|
|
240
|
+
- message
|
|
241
|
+
properties:
|
|
242
|
+
code:
|
|
243
|
+
type: integer
|
|
244
|
+
format: int32
|
|
245
|
+
message:
|
|
246
|
+
type: string
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
sla4oas: 1.0.0
|
|
2
|
+
context:
|
|
3
|
+
id: sla-dgalvan_us_es
|
|
4
|
+
type: agreement
|
|
5
|
+
api:
|
|
6
|
+
$ref: ../hpc-oas.yaml
|
|
7
|
+
provider: ISAGroup
|
|
8
|
+
customer: NormalUser S.L
|
|
9
|
+
apikeys:
|
|
10
|
+
- 1b0e1bfa203530d43a0bd8461aa018b7
|
|
11
|
+
validity:
|
|
12
|
+
from: '2025-01-01T00:00:00+00:00'
|
|
13
|
+
to: '2026-01-01T00:00:00+00:00'
|
|
14
|
+
metrics:
|
|
15
|
+
requests:
|
|
16
|
+
type: integer
|
|
17
|
+
format: int64
|
|
18
|
+
description: Number of requests
|
|
19
|
+
plan:
|
|
20
|
+
name: normal
|
|
21
|
+
pricing:
|
|
22
|
+
cost: 0
|
|
23
|
+
currency: EUR
|
|
24
|
+
billing: monthly
|
|
25
|
+
availability: R/00:00:00Z/23:59:59Z
|
|
26
|
+
rates:
|
|
27
|
+
/v1/chat/completions:
|
|
28
|
+
post:
|
|
29
|
+
requests:
|
|
30
|
+
- max: 5
|
|
31
|
+
period: minute
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
sla4oas: 1.0.0
|
|
2
|
+
context:
|
|
3
|
+
id: sla-japarejo_us_es
|
|
4
|
+
type: agreement
|
|
5
|
+
api:
|
|
6
|
+
$ref: ../hpc-oas.yaml
|
|
7
|
+
provider: ISAGroup
|
|
8
|
+
customer: ProUser S.L
|
|
9
|
+
apikeys:
|
|
10
|
+
- 6121788b3c78f416a5b10627edf417dd
|
|
11
|
+
validity:
|
|
12
|
+
from: '2025-01-01T00:00:00+00:00'
|
|
13
|
+
to: '2026-01-01T00:00:00+00:00'
|
|
14
|
+
metrics:
|
|
15
|
+
requests:
|
|
16
|
+
type: integer
|
|
17
|
+
format: int64
|
|
18
|
+
description: Number of requests
|
|
19
|
+
plan:
|
|
20
|
+
name: pro
|
|
21
|
+
pricing:
|
|
22
|
+
cost: 3
|
|
23
|
+
currency: EUR
|
|
24
|
+
billing: monthly
|
|
25
|
+
availability: R/00:00:00Z/23:59:59Z
|
|
26
|
+
rates:
|
|
27
|
+
/v1/chat/completions:
|
|
28
|
+
post:
|
|
29
|
+
requests:
|
|
30
|
+
- max: 10
|
|
31
|
+
period: minute
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
sla4oas: 1.0.0
|
|
2
|
+
context:
|
|
3
|
+
id: sla-pablofm_us_es
|
|
4
|
+
type: agreement
|
|
5
|
+
api:
|
|
6
|
+
$ref: ../hpc-oas.yaml
|
|
7
|
+
provider: ISAGroup
|
|
8
|
+
customer: ProUser S.L
|
|
9
|
+
apikeys:
|
|
10
|
+
- a57d42342af87c26180dd7820178cb9f
|
|
11
|
+
validity:
|
|
12
|
+
from: '2025-01-01T00:00:00+00:00'
|
|
13
|
+
to: '2026-01-01T00:00:00+00:00'
|
|
14
|
+
metrics:
|
|
15
|
+
requests:
|
|
16
|
+
type: integer
|
|
17
|
+
format: int64
|
|
18
|
+
description: Number of requests
|
|
19
|
+
plan:
|
|
20
|
+
name: pro
|
|
21
|
+
pricing:
|
|
22
|
+
cost: 3
|
|
23
|
+
currency: EUR
|
|
24
|
+
billing: monthly
|
|
25
|
+
availability: R/00:00:00Z/23:59:59Z
|
|
26
|
+
rates:
|
|
27
|
+
/v1/chat/completions:
|
|
28
|
+
post:
|
|
29
|
+
requests:
|
|
30
|
+
- max: 10
|
|
31
|
+
period: minute
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI wrapper for tests: loads sla-wizard, registers the custom-baseUrl plugin,
|
|
4
|
+
* then delegates to sla-wizard's CLI runner.
|
|
5
|
+
*
|
|
6
|
+
* Usage: node cli-with-plugin.js <command> [options]
|
|
7
|
+
*/
|
|
8
|
+
const slaWizard = require("sla-wizard");
|
|
9
|
+
const customBaseUrlPlugin = require("../index.js");
|
|
10
|
+
|
|
11
|
+
slaWizard.use(customBaseUrlPlugin);
|
|
12
|
+
|
|
13
|
+
slaWizard.program.parse(process.argv);
|