mcp-jev 1.1.2 → 2.0.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/README.md +171 -212
- package/dist/adapters/factory.d.ts +10 -0
- package/dist/adapters/factory.d.ts.map +1 -0
- package/dist/adapters/factory.js +34 -0
- package/dist/adapters/factory.js.map +1 -0
- package/dist/adapters/jev.d.ts +21 -0
- package/dist/adapters/jev.d.ts.map +1 -0
- package/dist/adapters/jev.js +88 -0
- package/dist/adapters/jev.js.map +1 -0
- package/dist/adapters/laya.d.ts +33 -0
- package/dist/adapters/laya.d.ts.map +1 -0
- package/dist/adapters/laya.js +125 -0
- package/dist/adapters/laya.js.map +1 -0
- package/dist/index.d.ts +10 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +155 -195
- package/dist/index.js.map +1 -1
- package/dist/lib.d.ts +101 -6
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +79 -12
- package/dist/lib.js.map +1 -1
- package/dist/presets.d.ts +15 -0
- package/dist/presets.d.ts.map +1 -0
- package/dist/presets.js +198 -0
- package/dist/presets.js.map +1 -0
- package/package.json +53 -53
package/README.md
CHANGED
|
@@ -1,212 +1,171 @@
|
|
|
1
|
-
# mcp-jev
|
|
2
|
-
|
|
3
|
-
MCP server
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
|
10
|
-
|
|
11
|
-
| `jev_decide` |
|
|
12
|
-
| `jev_list_models` |
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
|
21
|
-
|
|
22
|
-
| `
|
|
23
|
-
| `
|
|
24
|
-
| `
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"criteria": {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
|
163
|
-
|
|
164
|
-
|
|
|
165
|
-
| `
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
---
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
| HTTP code | Ý nghĩa | Behavior |
|
|
174
|
-
|-----------|---------|----------|
|
|
175
|
-
| 401 | API key sai / thiếu | Trả về `isError: true` ngay |
|
|
176
|
-
| 422 | Request body invalid | Trả về `isError: true` ngay + message chi tiết |
|
|
177
|
-
| 429 | Rate limit | Retry tối đa 3 lần, exponential backoff |
|
|
178
|
-
| 529 | Service overloaded | Retry tối đa 3 lần, exponential backoff |
|
|
179
|
-
|
|
180
|
-
Rate limits hiện tại: 250,000 tokens/s · 1,200 requests/min.
|
|
181
|
-
|
|
182
|
-
---
|
|
183
|
-
|
|
184
|
-
## Giới hạn Jev
|
|
185
|
-
|
|
186
|
-
- Chỉ nhận text (string, JSON object, JSON array) — không hỗ trợ image/audio/video
|
|
187
|
-
- Context budget: ~64,000 tokens cho toàn bộ state + questions
|
|
188
|
-
- Choice tối đa 255 options; Score 2–10 levels
|
|
189
|
-
- Không thể dùng cho System 2 tasks (lập luận đa bước, sinh code, giải thích)
|
|
190
|
-
- Model hiện tại: `jev-1.13.0` / alias `jev-latest`
|
|
191
|
-
|
|
192
|
-
---
|
|
193
|
-
|
|
194
|
-
## npx (khuyến nghị)
|
|
195
|
-
|
|
196
|
-
Không cần clone repo — dùng trực tiếp từ npm:
|
|
197
|
-
|
|
198
|
-
```json
|
|
199
|
-
{
|
|
200
|
-
"mcpServers": {
|
|
201
|
-
"jev": {
|
|
202
|
-
"command": "npx",
|
|
203
|
-
"args": ["-y", "mcp-jev"],
|
|
204
|
-
"env": {
|
|
205
|
-
"TYPESAFE_API_KEY": "your_key_here"
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
Source: [github.com/mndpjm/mcp-jev](https://github.com/mndpjm/mcp-jev)
|
|
1
|
+
# mcp-jev
|
|
2
|
+
|
|
3
|
+
MCP server for **System-1 decision models** — provider-agnostic. Routes to [TypeSafe Jev](https://typesafe.ai) (cloud) or [Laya](https://pypi.org/project/laya/) (local HTTP) via a single env var.
|
|
4
|
+
|
|
5
|
+
## Migration from v1 → v2
|
|
6
|
+
|
|
7
|
+
v2 replaces `jev_decide`/`jev_list_models` with a 4-tool provider-agnostic interface:
|
|
8
|
+
|
|
9
|
+
| v1 | v2 | Notes |
|
|
10
|
+
|----|----|----|
|
|
11
|
+
| `jev_decide` | `decide_predict` | Same question format (`questions[]` array) |
|
|
12
|
+
| `jev_list_models` | `decide_list_models` | Same return shape |
|
|
13
|
+
| — | `decide_status` | New: provider health info |
|
|
14
|
+
| — | `decide_preset` | New: named workflow presets |
|
|
15
|
+
|
|
16
|
+
**v2 env vars** (replaces `TYPESAFE_API_KEY` alone):
|
|
17
|
+
|
|
18
|
+
| Variable | Required | Default | Description |
|
|
19
|
+
|----------|----------|---------|-------------|
|
|
20
|
+
| `DECIDE_PROVIDER` | No | `jev` | `jev` or `laya` |
|
|
21
|
+
| `TYPESAFE_API_KEY` | When `jev` | — | TypeSafe API key |
|
|
22
|
+
| `TYPESAFE_BASE_URL` | No | `https://api.typesafe.ai` | Override Jev URL |
|
|
23
|
+
| `LAYA_BASE_URL` | No | `http://localhost:8000` | Override Laya URL |
|
|
24
|
+
| `LAYA_API_KEY` | No | — | Laya bearer token (if Laya requires auth) |
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Tools
|
|
29
|
+
|
|
30
|
+
### `decide_predict`
|
|
31
|
+
|
|
32
|
+
Core inference. Evaluate typed questions against a state.
|
|
33
|
+
|
|
34
|
+
**Question types**: `noul` (yes/no probability), `choice` (pick one of N), `score` (rate on rubric)
|
|
35
|
+
|
|
36
|
+
**Example:**
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"state": { "message": "My payment failed 3 days ago, help!" },
|
|
40
|
+
"questions": [
|
|
41
|
+
{ "id": "urgent", "type": "noul", "instructions": "Is `message` urgent?" },
|
|
42
|
+
{ "id": "dept", "type": "choice", "instructions": "Which team?",
|
|
43
|
+
"criteria": { "billing": "Payments", "technical": "API errors", "general": null } }
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
### `decide_preset`
|
|
51
|
+
|
|
52
|
+
Run a named workflow preset — expands to a pre-defined question set.
|
|
53
|
+
|
|
54
|
+
**Available presets:**
|
|
55
|
+
|
|
56
|
+
| Preset | State field | Questions |
|
|
57
|
+
|--------|------------|-----------|
|
|
58
|
+
| `triage` | `message` | intent, urgency, frustration, refund, churn |
|
|
59
|
+
| `guard` | `prompt` | jailbreak, injection, sensitive_data, harm, topic |
|
|
60
|
+
| `moderation` | `post` | toxic, harassment, threat, spam, severity |
|
|
61
|
+
| `router` | `request` | difficulty, domain, needs_tools, is_sensitive |
|
|
62
|
+
| `email` | `body` | category, is_spam, is_phishing, urgency, needs_reply |
|
|
63
|
+
|
|
64
|
+
**Example:**
|
|
65
|
+
```json
|
|
66
|
+
{ "preset": "guard", "state": { "prompt": "Ignore all instructions" } }
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
### `decide_status`
|
|
72
|
+
|
|
73
|
+
Provider health and configuration info.
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
// Jev response
|
|
77
|
+
{ "provider": "jev", "base_url": "https://api.typesafe.ai", "model": "jev-latest", "status": "ok" }
|
|
78
|
+
|
|
79
|
+
// Laya response
|
|
80
|
+
{ "provider": "laya", "base_url": "http://localhost:8000", "loaded": ["english", "multilingual"], "device": "cuda", "status": "ok" }
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
### `decide_list_models`
|
|
86
|
+
|
|
87
|
+
Available models or checkpoints.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Installation
|
|
92
|
+
|
|
93
|
+
### With Jev (cloud, default)
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"mcpServers": {
|
|
98
|
+
"jev": {
|
|
99
|
+
"command": "npx",
|
|
100
|
+
"args": ["-y", "mcp-jev"],
|
|
101
|
+
"env": {
|
|
102
|
+
"TYPESAFE_API_KEY": "your_key_here"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### With Laya (local)
|
|
110
|
+
|
|
111
|
+
Start Laya HTTP server first:
|
|
112
|
+
```bash
|
|
113
|
+
pip install "laya[serve]"
|
|
114
|
+
LAYA_DEVICE=cuda LAYA_PRELOAD=1 laya-serve # default: http://localhost:8000
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Then configure MCP:
|
|
118
|
+
```json
|
|
119
|
+
{
|
|
120
|
+
"mcpServers": {
|
|
121
|
+
"jev": {
|
|
122
|
+
"command": "npx",
|
|
123
|
+
"args": ["-y", "mcp-jev"],
|
|
124
|
+
"env": {
|
|
125
|
+
"DECIDE_PROVIDER": "laya",
|
|
126
|
+
"LAYA_BASE_URL": "http://localhost:8000"
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Local build
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
cd mcp-jev
|
|
137
|
+
npm install
|
|
138
|
+
npm run build
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
{
|
|
143
|
+
"mcpServers": {
|
|
144
|
+
"jev": {
|
|
145
|
+
"command": "node",
|
|
146
|
+
"args": ["d:/github/crhead/mcp-jev/dist/index.js"],
|
|
147
|
+
"env": {
|
|
148
|
+
"DECIDE_PROVIDER": "jev",
|
|
149
|
+
"TYPESAFE_API_KEY": "your_key_here"
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Provider Comparison
|
|
159
|
+
|
|
160
|
+
| | Jev (cloud) | Laya (local) |
|
|
161
|
+
|--|-------------|-------------|
|
|
162
|
+
| API key | Required (`TYPESAFE_API_KEY`) | Optional (`LAYA_API_KEY`) |
|
|
163
|
+
| Latency | Cloud (~200ms) | Local (~33ms GPU) |
|
|
164
|
+
| Routing metadata | None | Yes (language, checkpoint) |
|
|
165
|
+
| `/health` endpoint | No | Yes |
|
|
166
|
+
| Model list | `GET /v1/models` | Extracted from `GET /health` |
|
|
167
|
+
| Internet required | Yes | No |
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
Source: [github.com/mndpjm/mcp-jev](https://github.com/mndpjm/mcp-jev)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createAdapter — reads DECIDE_PROVIDER from environment and returns the
|
|
3
|
+
* appropriate ProviderAdapter implementation.
|
|
4
|
+
*
|
|
5
|
+
* Throws ConfigurationError (NOT process.exit) on invalid configuration.
|
|
6
|
+
* Callers (entry point) catch ConfigurationError and call process.exit(1).
|
|
7
|
+
*/
|
|
8
|
+
import { ProviderAdapter } from "../lib.js";
|
|
9
|
+
export declare function createAdapter(): ProviderAdapter;
|
|
10
|
+
//# sourceMappingURL=factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/adapters/factory.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAsB,eAAe,EAAE,MAAM,WAAW,CAAC;AAWhE,wBAAgB,aAAa,IAAI,eAAe,CA2B/C"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createAdapter — reads DECIDE_PROVIDER from environment and returns the
|
|
3
|
+
* appropriate ProviderAdapter implementation.
|
|
4
|
+
*
|
|
5
|
+
* Throws ConfigurationError (NOT process.exit) on invalid configuration.
|
|
6
|
+
* Callers (entry point) catch ConfigurationError and call process.exit(1).
|
|
7
|
+
*/
|
|
8
|
+
import { ConfigurationError } from "../lib.js";
|
|
9
|
+
import { JevAdapter } from "./jev.js";
|
|
10
|
+
import { LayaAdapter } from "./laya.js";
|
|
11
|
+
const VALID_PROVIDERS = ["jev", "laya"];
|
|
12
|
+
function isValidProvider(v) {
|
|
13
|
+
return VALID_PROVIDERS.includes(v);
|
|
14
|
+
}
|
|
15
|
+
export function createAdapter() {
|
|
16
|
+
const provider = (process.env.DECIDE_PROVIDER ?? "jev").trim().toLowerCase();
|
|
17
|
+
if (!isValidProvider(provider)) {
|
|
18
|
+
throw new ConfigurationError(`Invalid DECIDE_PROVIDER value "${provider}". Valid values: ${VALID_PROVIDERS.join(", ")}.`);
|
|
19
|
+
}
|
|
20
|
+
if (provider === "jev") {
|
|
21
|
+
const apiKey = process.env.TYPESAFE_API_KEY;
|
|
22
|
+
if (!apiKey) {
|
|
23
|
+
throw new ConfigurationError('TYPESAFE_API_KEY is required when DECIDE_PROVIDER=jev (or unset). ' +
|
|
24
|
+
'Set DECIDE_PROVIDER=laya to use a local Laya server without an API key.');
|
|
25
|
+
}
|
|
26
|
+
const baseUrl = process.env.TYPESAFE_BASE_URL?.replace(/\/$/, "") ?? "https://api.typesafe.ai";
|
|
27
|
+
return new JevAdapter(apiKey, baseUrl);
|
|
28
|
+
}
|
|
29
|
+
// provider === "laya"
|
|
30
|
+
const baseUrl = process.env.LAYA_BASE_URL?.replace(/\/$/, "") ?? "http://localhost:8000";
|
|
31
|
+
const apiKey = process.env.LAYA_API_KEY; // optional
|
|
32
|
+
return new LayaAdapter(baseUrl, apiKey);
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/adapters/factory.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,kBAAkB,EAAmB,MAAM,WAAW,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,MAAM,CAAU,CAAC;AAGjD,SAAS,eAAe,CAAC,CAAS;IAChC,OAAQ,eAAqC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,QAAQ,GAAW,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAErF,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,kBAAkB,CAC1B,kCAAkC,QAAQ,oBAAoB,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC5F,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;QAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,kBAAkB,CAC1B,oEAAoE;gBACpE,yEAAyE,CAC1E,CAAC;QACJ,CAAC;QACD,MAAM,OAAO,GACX,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,yBAAyB,CAAC;QACjF,OAAO,IAAI,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;IAED,sBAAsB;IACtB,MAAM,OAAO,GACX,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,uBAAuB,CAAC;IAC3E,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,WAAW;IACpD,OAAO,IAAI,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JevAdapter — routes requests to TypeSafe Jev cloud API.
|
|
3
|
+
*
|
|
4
|
+
* Env:
|
|
5
|
+
* TYPESAFE_API_KEY (required — caller must validate before constructing)
|
|
6
|
+
* TYPESAFE_BASE_URL (optional, default: https://api.typesafe.ai)
|
|
7
|
+
*/
|
|
8
|
+
import { ProviderAdapter, PredictRequest, PredictResponse, ModelEntry, StatusResponse } from "../lib.js";
|
|
9
|
+
export declare class JevAdapter implements ProviderAdapter {
|
|
10
|
+
private readonly apiKey;
|
|
11
|
+
private readonly baseUrl;
|
|
12
|
+
private readonly defaultModel;
|
|
13
|
+
constructor(apiKey: string, baseUrl: string, defaultModel?: string);
|
|
14
|
+
predict(req: PredictRequest): Promise<PredictResponse>;
|
|
15
|
+
listModels(): Promise<ModelEntry[]>;
|
|
16
|
+
/**
|
|
17
|
+
* Jev has no /health endpoint — synthesize status from environment config.
|
|
18
|
+
*/
|
|
19
|
+
status(): Promise<StatusResponse>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=jev.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jev.d.ts","sourceRoot":"","sources":["../../src/adapters/jev.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,eAAe,EACf,cAAc,EACd,eAAe,EACf,UAAU,EACV,cAAc,EAQf,MAAM,WAAW,CAAC;AAEnB,qBAAa,UAAW,YAAW,eAAe;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,SAAe;IAMlE,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAiCtD,UAAU,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAmCzC;;OAEG;IACH,MAAM,IAAI,OAAO,CAAC,cAAc,CAAC;CAQlC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JevAdapter — routes requests to TypeSafe Jev cloud API.
|
|
3
|
+
*
|
|
4
|
+
* Env:
|
|
5
|
+
* TYPESAFE_API_KEY (required — caller must validate before constructing)
|
|
6
|
+
* TYPESAFE_BASE_URL (optional, default: https://api.typesafe.ai)
|
|
7
|
+
*/
|
|
8
|
+
import { ParseError, fetchWithRetry, parseModelEntries, JevResponseSchema, JevModelsResponseSchema, } from "../lib.js";
|
|
9
|
+
export class JevAdapter {
|
|
10
|
+
apiKey;
|
|
11
|
+
baseUrl;
|
|
12
|
+
defaultModel;
|
|
13
|
+
constructor(apiKey, baseUrl, defaultModel = "jev-latest") {
|
|
14
|
+
this.apiKey = apiKey;
|
|
15
|
+
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
16
|
+
this.defaultModel = defaultModel;
|
|
17
|
+
}
|
|
18
|
+
async predict(req) {
|
|
19
|
+
const body = {
|
|
20
|
+
model: req.model ?? this.defaultModel,
|
|
21
|
+
state: req.state,
|
|
22
|
+
questions: req.questions,
|
|
23
|
+
};
|
|
24
|
+
const resp = await fetchWithRetry(`${this.baseUrl}/v1/systemone`, {
|
|
25
|
+
method: "POST",
|
|
26
|
+
headers: {
|
|
27
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
28
|
+
"Content-Type": "application/json",
|
|
29
|
+
},
|
|
30
|
+
body: JSON.stringify(body),
|
|
31
|
+
});
|
|
32
|
+
let raw;
|
|
33
|
+
try {
|
|
34
|
+
raw = await resp.json();
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
throw new ParseError(`Failed to parse Jev API response as JSON: ${e instanceof Error ? e.message : String(e)}`);
|
|
38
|
+
}
|
|
39
|
+
const parsed = JevResponseSchema.safeParse(raw);
|
|
40
|
+
if (!parsed.success) {
|
|
41
|
+
throw new ParseError(`Jev API response shape unexpected: ${parsed.error.message}`);
|
|
42
|
+
}
|
|
43
|
+
return parsed.data;
|
|
44
|
+
}
|
|
45
|
+
async listModels() {
|
|
46
|
+
const resp = await fetchWithRetry(`${this.baseUrl}/v1/models`, {
|
|
47
|
+
method: "GET",
|
|
48
|
+
headers: { Authorization: `Bearer ${this.apiKey}` },
|
|
49
|
+
});
|
|
50
|
+
let raw;
|
|
51
|
+
try {
|
|
52
|
+
raw = await resp.json();
|
|
53
|
+
}
|
|
54
|
+
catch (e) {
|
|
55
|
+
throw new ParseError(`Failed to parse Jev models response as JSON: ${e instanceof Error ? e.message : String(e)}`);
|
|
56
|
+
}
|
|
57
|
+
// Handle multiple response shapes:
|
|
58
|
+
// 1. Direct array: [{ id, aliases }, ...]
|
|
59
|
+
// 2. Wrapped object: { data: [...] } or { models: [...] }
|
|
60
|
+
let entries;
|
|
61
|
+
if (Array.isArray(raw)) {
|
|
62
|
+
entries = raw;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
const envelope = JevModelsResponseSchema.safeParse(raw);
|
|
66
|
+
if (!envelope.success) {
|
|
67
|
+
throw new ParseError(`Unexpected Jev models response shape: ${envelope.error.message}`);
|
|
68
|
+
}
|
|
69
|
+
entries = envelope.data.models ?? envelope.data.data ?? [];
|
|
70
|
+
if (!Array.isArray(entries)) {
|
|
71
|
+
throw new ParseError("Unexpected Jev models response shape — expected array");
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return parseModelEntries(entries);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Jev has no /health endpoint — synthesize status from environment config.
|
|
78
|
+
*/
|
|
79
|
+
status() {
|
|
80
|
+
return Promise.resolve({
|
|
81
|
+
provider: "jev",
|
|
82
|
+
base_url: this.baseUrl,
|
|
83
|
+
model: this.defaultModel,
|
|
84
|
+
status: "ok",
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=jev.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jev.js","sourceRoot":"","sources":["../../src/adapters/jev.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LayaAdapter — routes requests to a local Laya HTTP server.
|
|
3
|
+
*
|
|
4
|
+
* Laya HTTP server exposes POST /v1/systemone (Jev wire-compatible) and GET /health.
|
|
5
|
+
* Key differences from Jev:
|
|
6
|
+
* - `model` field should be OMITTED in predict request (Laya auto-routes)
|
|
7
|
+
* - GET /health (not /v1/models) for model list
|
|
8
|
+
* - Richer response: includes `routing` block, `latency_ms`, `device`
|
|
9
|
+
*
|
|
10
|
+
* Env:
|
|
11
|
+
* LAYA_BASE_URL (optional, default: http://localhost:8000)
|
|
12
|
+
* LAYA_API_KEY (optional) — bearer token if Laya is deployed with auth
|
|
13
|
+
*/
|
|
14
|
+
import { ProviderAdapter, PredictRequest, PredictResponse, ModelEntry, StatusResponse } from "../lib.js";
|
|
15
|
+
export declare class LayaAdapter implements ProviderAdapter {
|
|
16
|
+
private readonly baseUrl;
|
|
17
|
+
private readonly apiKey?;
|
|
18
|
+
constructor(baseUrl: string, apiKey?: string);
|
|
19
|
+
private get headers();
|
|
20
|
+
predict(req: PredictRequest): Promise<PredictResponse>;
|
|
21
|
+
listModels(): Promise<ModelEntry[]>;
|
|
22
|
+
status(): Promise<StatusResponse>;
|
|
23
|
+
/**
|
|
24
|
+
* Fetch GET /health. Returns null on unreachable — callers handle gracefully.
|
|
25
|
+
* Returns status: "unreachable" via StatusResponse when called from status().
|
|
26
|
+
*/
|
|
27
|
+
private _fetchHealth;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Build a StatusResponse for unreachable Laya health endpoint.
|
|
31
|
+
*/
|
|
32
|
+
export declare function layaUnreachableStatus(baseUrl: string, errorMsg: string): StatusResponse;
|
|
33
|
+
//# sourceMappingURL=laya.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"laya.d.ts","sourceRoot":"","sources":["../../src/adapters/laya.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,eAAe,EACf,cAAc,EACd,eAAe,EACf,UAAU,EACV,cAAc,EAQf,MAAM,WAAW,CAAC;AAEnB,qBAAa,WAAY,YAAW,eAAe;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;gBAErB,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;IAK5C,OAAO,KAAK,OAAO,GAMlB;IAEK,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAgCtD,UAAU,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAUnC,MAAM,IAAI,OAAO,CAAC,cAAc,CAAC;IAmBvC;;;OAGG;YACW,YAAY;CA+B3B;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,cAAc,CAOvF"}
|