vibeoscore 1.0.2
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/.env.example +5 -0
- package/README.md +29 -0
- package/client.js +257 -0
- package/client.ts +334 -0
- package/dashboard/dist/assets/index-BnPt1Fii.js +1 -0
- package/dashboard/dist/assets/index-CfH00tOL.css +1 -0
- package/dashboard/dist/index.html +3 -0
- package/lib/blackbox-rf.js +1099 -0
- package/lib/blackbox.js +137 -0
- package/lib/compression.js +119 -0
- package/lib/db.js +106 -0
- package/lib/db.ts +113 -0
- package/lib/delegation.js +137 -0
- package/lib/meta-controller.js +418 -0
- package/lib/meta-controller.mjs +499 -0
- package/lib/patterns.js +150 -0
- package/lib/resolution-tracker.js +486 -0
- package/lib/stress.js +84 -0
- package/lib/tdd.js +218 -0
- package/lib/tier-routing.js +48 -0
- package/mcp-server.js +370 -0
- package/mcp-server.ts +364 -0
- package/middleware/auth.js +75 -0
- package/middleware/auth.ts +87 -0
- package/middleware/usage-logging.js +29 -0
- package/middleware/usage-logging.ts +41 -0
- package/nginx-vibetheog-api.conf +64 -0
- package/package.json +66 -0
- package/routes/admin.js +93 -0
- package/routes/admin.ts +107 -0
- package/routes/blackbox.js +463 -0
- package/routes/compression.js +12 -0
- package/routes/delegation.js +30 -0
- package/routes/patterns.js +53 -0
- package/routes/pricing.js +62 -0
- package/routes/stress.js +30 -0
- package/routes/tdd.js +68 -0
- package/routes/tier-routing.js +31 -0
- package/scripts/dashboard-server.mjs +246 -0
- package/scripts/deploy-zero-downtime.sh +77 -0
- package/scripts/deploy.sh +68 -0
- package/scripts/release.mjs +30 -0
- package/scripts/seed-master-token.js +29 -0
- package/scripts/start-all.mjs +34 -0
- package/server.js +88 -0
- package/vibeos-api.service +19 -0
package/.env.example
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# vibeOScore
|
|
2
|
+
|
|
3
|
+
## Tech Stack
|
|
4
|
+
|
|
5
|
+
`typescript`, `javascript`
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
(Feature list maintained by vibeOS — run `trinity guard` to refresh)
|
|
10
|
+
|
|
11
|
+
## Getting Started
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Clone and install dependencies
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## API Token (Alpha)
|
|
18
|
+
|
|
19
|
+
This is the vibeOScore API token. It can be revoked and will be replaced with auto-generated tokens in a future release.
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
VIBEOS_API_TOKEN=vos_59d73aa4b7838a7ca9dafe957993177b5629c7954091db3350b4150882ff7064
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Set this as an environment variable or add it to `~/.claude/.env.production`:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
export VIBEOS_API_TOKEN=vos_59d73aa4b7838a7ca9dafe957993177b5629c7954091db3350b4150882ff7064
|
|
29
|
+
```
|
package/client.js
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// SPDX-FileCopyrightText: 2026 vibeOS <https://github.com/DrunkkToys/vibeOS>
|
|
3
|
+
const DEFAULT_API_URL = "https://api.vibetheog.com";
|
|
4
|
+
const REQUEST_TIMEOUT = 10000;
|
|
5
|
+
const MAX_RETRIES = 3;
|
|
6
|
+
const BASE_RETRY_DELAY = 1000;
|
|
7
|
+
class VibeOSApiClient {
|
|
8
|
+
baseUrl;
|
|
9
|
+
apiToken;
|
|
10
|
+
masterKey;
|
|
11
|
+
timeout;
|
|
12
|
+
fallbackMode;
|
|
13
|
+
fallbackStubs;
|
|
14
|
+
constructor(options = {}) {
|
|
15
|
+
this.baseUrl = options.baseUrl || process.env.VIBEOS_API_URL || DEFAULT_API_URL;
|
|
16
|
+
this.apiToken = options.apiToken || process.env.VIBEOS_API_TOKEN || null;
|
|
17
|
+
this.masterKey = options.masterKey || process.env.VIBEOS_API_MASTER_KEY || null;
|
|
18
|
+
this.timeout = options.timeout || REQUEST_TIMEOUT;
|
|
19
|
+
this.fallbackMode = false;
|
|
20
|
+
this.fallbackStubs = options.fallbackStubs || null;
|
|
21
|
+
}
|
|
22
|
+
async request(path, body = null, isAdmin = false) {
|
|
23
|
+
if (!this.apiToken && !isAdmin) {
|
|
24
|
+
throw new Error("VIBEOS_API_TOKEN is not set");
|
|
25
|
+
}
|
|
26
|
+
const url = this.baseUrl + path;
|
|
27
|
+
const headers = {
|
|
28
|
+
"Content-Type": "application/json",
|
|
29
|
+
Authorization: "Bearer " + (isAdmin ? this.masterKey : this.apiToken),
|
|
30
|
+
};
|
|
31
|
+
let lastError = null;
|
|
32
|
+
let attempt = 0;
|
|
33
|
+
while (attempt <= MAX_RETRIES) {
|
|
34
|
+
if (attempt > 0) {
|
|
35
|
+
const delay = BASE_RETRY_DELAY * Math.pow(2, attempt - 1);
|
|
36
|
+
await new Promise(r => setTimeout(r, delay));
|
|
37
|
+
}
|
|
38
|
+
attempt++;
|
|
39
|
+
try {
|
|
40
|
+
const controller = new AbortController();
|
|
41
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
42
|
+
const res = await fetch(url, {
|
|
43
|
+
method: body ? "POST" : "GET",
|
|
44
|
+
headers,
|
|
45
|
+
body: body ? JSON.stringify(body) : null,
|
|
46
|
+
signal: controller.signal,
|
|
47
|
+
});
|
|
48
|
+
clearTimeout(timeoutId);
|
|
49
|
+
if (res.status === 401 || res.status === 403) {
|
|
50
|
+
const errorBody = await res.json().catch(() => ({}));
|
|
51
|
+
this.fallbackMode = true;
|
|
52
|
+
throw new VibeOSAuthError(errorBody.message || "Authentication failed", res.status, errorBody.code);
|
|
53
|
+
}
|
|
54
|
+
if (!res.ok) {
|
|
55
|
+
const errorBody = await res.json().catch(() => ({}));
|
|
56
|
+
if (res.status >= 500 && attempt <= MAX_RETRIES) {
|
|
57
|
+
lastError = new Error("API error " + res.status + ": " + (errorBody.error || res.statusText));
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
throw new Error("API error " + res.status + ": " + (errorBody.error || res.statusText));
|
|
61
|
+
}
|
|
62
|
+
this.fallbackMode = false;
|
|
63
|
+
return res.json();
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
if (err instanceof VibeOSAuthError)
|
|
67
|
+
throw err;
|
|
68
|
+
const error = err;
|
|
69
|
+
if (error.name === "AbortError") {
|
|
70
|
+
if (attempt <= MAX_RETRIES) {
|
|
71
|
+
lastError = new VibeOSTimeoutError("Request to " + url + " timed out after " + this.timeout + "ms");
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
this.fallbackMode = true;
|
|
75
|
+
throw new VibeOSTimeoutError("Request to " + url + " timed out after " + this.timeout + "ms");
|
|
76
|
+
}
|
|
77
|
+
lastError = err;
|
|
78
|
+
if (attempt <= MAX_RETRIES && error.message && (error.message.includes("fetch") || error.message.includes("network") || error.message.includes("ECONNREFUSED"))) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
this.fallbackMode = true;
|
|
84
|
+
throw new VibeOSNetworkError("Failed to reach API after " + MAX_RETRIES + " retries: " + (lastError ? lastError.message : "unknown error"));
|
|
85
|
+
}
|
|
86
|
+
async delegateCheck(tool, tier, model, prompt, dynamicCache = {}) {
|
|
87
|
+
return this.request("/api/v1/delegate/check", { tool, tier, model, prompt, dynamic_cache: dynamicCache });
|
|
88
|
+
}
|
|
89
|
+
async delegateSoftQuota(tool, currentCount, limit = 5) {
|
|
90
|
+
return this.request("/api/v1/delegate/soft-quota", { tool, current_count: currentCount, limit });
|
|
91
|
+
}
|
|
92
|
+
async delegateCost(model, dynamicCache = {}) {
|
|
93
|
+
return this.request("/api/v1/delegation/cost", { model, dynamic_cache: dynamicCache });
|
|
94
|
+
}
|
|
95
|
+
async routeModel(prompt, currentTier, trinityCheap, trinityMedium, learnedExploratory = [], stressScore = 0) {
|
|
96
|
+
return this.request("/api/v1/route/model", {
|
|
97
|
+
prompt,
|
|
98
|
+
current_tier: currentTier,
|
|
99
|
+
trinity_cheap: trinityCheap,
|
|
100
|
+
trinity_medium: trinityMedium,
|
|
101
|
+
learned_exploratory: learnedExploratory,
|
|
102
|
+
stress_score: stressScore,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
async classifyTier(model, customRegex = null) {
|
|
106
|
+
return this.request("/api/v1/tier/classify", { model, custom_regex: customRegex });
|
|
107
|
+
}
|
|
108
|
+
async isExploratory(prompt, learnedExploratory = []) {
|
|
109
|
+
return this.request("/api/v1/tier/exploratory", { prompt, learned_exploratory: learnedExploratory });
|
|
110
|
+
}
|
|
111
|
+
async scoreStress(text) {
|
|
112
|
+
return this.request("/api/v1/stress/score", { text });
|
|
113
|
+
}
|
|
114
|
+
async stressLevel(score) {
|
|
115
|
+
return this.request("/api/v1/stress/level", { score });
|
|
116
|
+
}
|
|
117
|
+
async blackboxAnalyze(sessionId, entry) {
|
|
118
|
+
return this.request("/api/v1/blackbox/analyze", {
|
|
119
|
+
session_id: sessionId,
|
|
120
|
+
project_id: entry.project_id || null,
|
|
121
|
+
user_text: entry.userText || "",
|
|
122
|
+
features: entry.features || {},
|
|
123
|
+
action: entry.action || "explore",
|
|
124
|
+
entropy: entry.entropy ?? 1.0,
|
|
125
|
+
uncertainty: entry.uncertainty ?? 50,
|
|
126
|
+
embedding: entry.embedding || null,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
async blackboxState(sessionId) {
|
|
130
|
+
return this.request("/api/v1/blackbox/state", { session_id: sessionId });
|
|
131
|
+
}
|
|
132
|
+
async blackboxReset(sessionId) {
|
|
133
|
+
return this.request("/api/v1/blackbox/reset", { session_id: sessionId });
|
|
134
|
+
}
|
|
135
|
+
async blackboxOutcome(sessionId, outcome) {
|
|
136
|
+
return this.request("/api/v1/blackbox/outcome", { session_id: sessionId, outcome });
|
|
137
|
+
}
|
|
138
|
+
async blackboxCalibrate(projectId) {
|
|
139
|
+
return this.request("/api/v1/blackbox/calibrate", { project_id: projectId || "global" });
|
|
140
|
+
}
|
|
141
|
+
async blackboxCalibration(projectId) {
|
|
142
|
+
return this.request("/api/v1/blackbox/calibration?project_id=" + (projectId || "global"), null);
|
|
143
|
+
}
|
|
144
|
+
async blackboxControlVector(state, action, optimizationMode) {
|
|
145
|
+
return this.request("/api/v1/blackbox/control-vector", { ...state, action, optimization_mode: optimizationMode });
|
|
146
|
+
}
|
|
147
|
+
async blackboxSelectMode(subRegime, stressMultiplier) {
|
|
148
|
+
return this.request("/api/v1/blackbox/select-mode", { sub_regime: subRegime, stress_multiplier: stressMultiplier });
|
|
149
|
+
}
|
|
150
|
+
async tddExports(sourceContent, ext) {
|
|
151
|
+
return this.request("/api/v1/tdd/exports", { source_content: sourceContent, ext });
|
|
152
|
+
}
|
|
153
|
+
async tddParams(sourceContent, funcName) {
|
|
154
|
+
return this.request("/api/v1/tdd/params", { source_content: sourceContent, func_name: funcName });
|
|
155
|
+
}
|
|
156
|
+
async tddInferType(paramName, defaultValue) {
|
|
157
|
+
return this.request("/api/v1/tdd/infer-type", { param_name: paramName, default_value: defaultValue });
|
|
158
|
+
}
|
|
159
|
+
async tddSkeleton(language, fileName, exports, options = {}) {
|
|
160
|
+
return this.request("/api/v1/tdd/skeleton", { language, file_name: fileName, exports, options });
|
|
161
|
+
}
|
|
162
|
+
async patternsObserve(sessionId, toolName, input, output, directory) {
|
|
163
|
+
return this.request("/api/v1/patterns/observe", {
|
|
164
|
+
session_id: sessionId,
|
|
165
|
+
tool_name: toolName,
|
|
166
|
+
input,
|
|
167
|
+
output,
|
|
168
|
+
directory,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
async patternsRecord(sessionId, kind, key, summary, meta = {}) {
|
|
172
|
+
return this.request("/api/v1/patterns/record", {
|
|
173
|
+
session_id: sessionId,
|
|
174
|
+
kind,
|
|
175
|
+
key,
|
|
176
|
+
summary,
|
|
177
|
+
meta,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
async patternsQuery(sessionId, kind = null) {
|
|
181
|
+
return this.request("/api/v1/patterns/query?kind=" + (kind || ""), null);
|
|
182
|
+
}
|
|
183
|
+
async patternsExploratoryWords(sessionId) {
|
|
184
|
+
return this.request("/api/v1/patterns/exploratory-words", null);
|
|
185
|
+
}
|
|
186
|
+
async patternsClear(sessionId) {
|
|
187
|
+
return this.request("/api/v1/patterns/clear", { session_id: sessionId });
|
|
188
|
+
}
|
|
189
|
+
async pricingFetch(openrouterKey, force = false) {
|
|
190
|
+
return this.request("/api/v1/pricing/fetch", { openrouter_key: openrouterKey, force });
|
|
191
|
+
}
|
|
192
|
+
async pricingLookup(model) {
|
|
193
|
+
return this.request("/api/v1/pricing/lookup", { model });
|
|
194
|
+
}
|
|
195
|
+
async pricingStatic() {
|
|
196
|
+
return this.request("/api/v1/pricing/static", null);
|
|
197
|
+
}
|
|
198
|
+
async compressContext(text, threshold = 2000) {
|
|
199
|
+
return this.request("/api/v1/compress/context", { text, threshold });
|
|
200
|
+
}
|
|
201
|
+
async adminCreateSeat(name, email) {
|
|
202
|
+
return this.request("/admin/seats", { name, email }, true);
|
|
203
|
+
}
|
|
204
|
+
async adminCreateSeatWithToken(name, email, tokenLabel = null) {
|
|
205
|
+
return this.request("/admin/seats", { name, email, with_token: tokenLabel || true }, true);
|
|
206
|
+
}
|
|
207
|
+
async adminListSeats() {
|
|
208
|
+
return this.request("/admin/seats", null, true);
|
|
209
|
+
}
|
|
210
|
+
async adminUpdateSeat(seatId, status) {
|
|
211
|
+
return this.request("/admin/seats/" + seatId, { status }, true);
|
|
212
|
+
}
|
|
213
|
+
async adminCreateToken(seatId, label, expiresAt) {
|
|
214
|
+
return this.request("/admin/tokens", { seat_id: seatId, label, expires_at: expiresAt }, true);
|
|
215
|
+
}
|
|
216
|
+
async adminListTokens() {
|
|
217
|
+
return this.request("/admin/tokens", null, true);
|
|
218
|
+
}
|
|
219
|
+
async adminUpdateToken(tokenId, status) {
|
|
220
|
+
return this.request("/admin/tokens/" + tokenId, { status }, true);
|
|
221
|
+
}
|
|
222
|
+
async adminDeleteToken(tokenId) {
|
|
223
|
+
return this.request("/admin/tokens/" + tokenId, null, true);
|
|
224
|
+
}
|
|
225
|
+
async adminUsage(days = 30) {
|
|
226
|
+
return this.request("/admin/usage?days=" + days, null, true);
|
|
227
|
+
}
|
|
228
|
+
async health() {
|
|
229
|
+
return this.request("/health", null, false);
|
|
230
|
+
}
|
|
231
|
+
isFallback() {
|
|
232
|
+
return this.fallbackMode;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
class VibeOSAuthError extends Error {
|
|
236
|
+
statusCode;
|
|
237
|
+
code;
|
|
238
|
+
constructor(message, statusCode, code) {
|
|
239
|
+
super(message);
|
|
240
|
+
this.name = "VibeOSAuthError";
|
|
241
|
+
this.statusCode = statusCode;
|
|
242
|
+
this.code = code;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
class VibeOSTimeoutError extends Error {
|
|
246
|
+
constructor(message) {
|
|
247
|
+
super(message);
|
|
248
|
+
this.name = "VibeOSTimeoutError";
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
class VibeOSNetworkError extends Error {
|
|
252
|
+
constructor(message) {
|
|
253
|
+
super(message);
|
|
254
|
+
this.name = "VibeOSNetworkError";
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
export { VibeOSApiClient, VibeOSAuthError, VibeOSTimeoutError, VibeOSNetworkError };
|
package/client.ts
ADDED
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// SPDX-FileCopyrightText: 2026 vibeOS <https://github.com/DrunkkToys/vibeOS>
|
|
3
|
+
|
|
4
|
+
const DEFAULT_API_URL = "https://api.vibetheog.com"
|
|
5
|
+
const REQUEST_TIMEOUT = 10000
|
|
6
|
+
const MAX_RETRIES = 3
|
|
7
|
+
const BASE_RETRY_DELAY = 1000
|
|
8
|
+
|
|
9
|
+
type ApiClientOptions = {
|
|
10
|
+
baseUrl?: string
|
|
11
|
+
apiToken?: string
|
|
12
|
+
masterKey?: string
|
|
13
|
+
timeout?: number
|
|
14
|
+
fallbackStubs?: unknown
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
type BlackboxEntry = {
|
|
18
|
+
project_id?: string | null
|
|
19
|
+
userText?: string
|
|
20
|
+
features?: Record<string, unknown>
|
|
21
|
+
action?: string
|
|
22
|
+
entropy?: number
|
|
23
|
+
uncertainty?: number
|
|
24
|
+
embedding?: unknown
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
class VibeOSApiClient {
|
|
28
|
+
baseUrl: string
|
|
29
|
+
apiToken: string | null
|
|
30
|
+
masterKey: string | null
|
|
31
|
+
timeout: number
|
|
32
|
+
fallbackMode: boolean
|
|
33
|
+
fallbackStubs: unknown
|
|
34
|
+
|
|
35
|
+
constructor(options: ApiClientOptions = {}) {
|
|
36
|
+
this.baseUrl = options.baseUrl || process.env.VIBEOS_API_URL || DEFAULT_API_URL
|
|
37
|
+
this.apiToken = options.apiToken || process.env.VIBEOS_API_TOKEN || null
|
|
38
|
+
this.masterKey = options.masterKey || process.env.VIBEOS_API_MASTER_KEY || null
|
|
39
|
+
this.timeout = options.timeout || REQUEST_TIMEOUT
|
|
40
|
+
this.fallbackMode = false
|
|
41
|
+
this.fallbackStubs = options.fallbackStubs || null
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async request(path: string, body: Record<string, unknown> | null = null, isAdmin = false): Promise<unknown> {
|
|
45
|
+
if (!this.apiToken && !isAdmin) {
|
|
46
|
+
throw new Error("VIBEOS_API_TOKEN is not set")
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const url = this.baseUrl + path
|
|
50
|
+
const headers: Record<string, string> = {
|
|
51
|
+
"Content-Type": "application/json",
|
|
52
|
+
Authorization: "Bearer " + (isAdmin ? this.masterKey : this.apiToken),
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let lastError: Error | null = null
|
|
56
|
+
let attempt = 0
|
|
57
|
+
|
|
58
|
+
while (attempt <= MAX_RETRIES) {
|
|
59
|
+
if (attempt > 0) {
|
|
60
|
+
const delay = BASE_RETRY_DELAY * Math.pow(2, attempt - 1)
|
|
61
|
+
await new Promise(r => setTimeout(r, delay))
|
|
62
|
+
}
|
|
63
|
+
attempt++
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
const controller = new AbortController()
|
|
67
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout)
|
|
68
|
+
|
|
69
|
+
const res = await fetch(url, {
|
|
70
|
+
method: body ? "POST" : "GET",
|
|
71
|
+
headers,
|
|
72
|
+
body: body ? JSON.stringify(body) : null,
|
|
73
|
+
signal: controller.signal,
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
clearTimeout(timeoutId)
|
|
77
|
+
|
|
78
|
+
if (res.status === 401 || res.status === 403) {
|
|
79
|
+
const errorBody = await res.json().catch(() => ({})) as { message?: string; code?: string }
|
|
80
|
+
this.fallbackMode = true
|
|
81
|
+
throw new VibeOSAuthError(errorBody.message || "Authentication failed", res.status, errorBody.code)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (!res.ok) {
|
|
85
|
+
const errorBody = await res.json().catch(() => ({})) as { error?: string }
|
|
86
|
+
if (res.status >= 500 && attempt <= MAX_RETRIES) {
|
|
87
|
+
lastError = new Error("API error " + res.status + ": " + (errorBody.error || res.statusText))
|
|
88
|
+
continue
|
|
89
|
+
}
|
|
90
|
+
throw new Error("API error " + res.status + ": " + (errorBody.error || res.statusText))
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
this.fallbackMode = false
|
|
94
|
+
return res.json()
|
|
95
|
+
} catch (err: unknown) {
|
|
96
|
+
if (err instanceof VibeOSAuthError) throw err
|
|
97
|
+
const error = err as { name?: string; message?: string }
|
|
98
|
+
if (error.name === "AbortError") {
|
|
99
|
+
if (attempt <= MAX_RETRIES) {
|
|
100
|
+
lastError = new VibeOSTimeoutError("Request to " + url + " timed out after " + this.timeout + "ms")
|
|
101
|
+
continue
|
|
102
|
+
}
|
|
103
|
+
this.fallbackMode = true
|
|
104
|
+
throw new VibeOSTimeoutError("Request to " + url + " timed out after " + this.timeout + "ms")
|
|
105
|
+
}
|
|
106
|
+
lastError = err as Error
|
|
107
|
+
if (attempt <= MAX_RETRIES && error.message && (
|
|
108
|
+
error.message.includes("fetch") || error.message.includes("network") || error.message.includes("ECONNREFUSED")
|
|
109
|
+
)) {
|
|
110
|
+
continue
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
this.fallbackMode = true
|
|
116
|
+
throw new VibeOSNetworkError("Failed to reach API after " + MAX_RETRIES + " retries: " + (lastError ? lastError.message : "unknown error"))
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async delegateCheck(tool: string, tier: string, model: string, prompt: string, dynamicCache: Record<string, unknown> = {}): Promise<unknown> {
|
|
120
|
+
return this.request("/api/v1/delegate/check", { tool, tier, model, prompt, dynamic_cache: dynamicCache })
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async delegateSoftQuota(tool: string, currentCount: number, limit = 5): Promise<unknown> {
|
|
124
|
+
return this.request("/api/v1/delegate/soft-quota", { tool, current_count: currentCount, limit })
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async delegateCost(model: string, dynamicCache: Record<string, unknown> = {}): Promise<unknown> {
|
|
128
|
+
return this.request("/api/v1/delegation/cost", { model, dynamic_cache: dynamicCache })
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async routeModel(prompt: string, currentTier: string, trinityCheap: string, trinityMedium: string, learnedExploratory: string[] = [], stressScore = 0): Promise<unknown> {
|
|
132
|
+
return this.request("/api/v1/route/model", {
|
|
133
|
+
prompt,
|
|
134
|
+
current_tier: currentTier,
|
|
135
|
+
trinity_cheap: trinityCheap,
|
|
136
|
+
trinity_medium: trinityMedium,
|
|
137
|
+
learned_exploratory: learnedExploratory,
|
|
138
|
+
stress_score: stressScore,
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async classifyTier(model: string, customRegex: string | null = null): Promise<unknown> {
|
|
143
|
+
return this.request("/api/v1/tier/classify", { model, custom_regex: customRegex })
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async isExploratory(prompt: string, learnedExploratory: string[] = []): Promise<unknown> {
|
|
147
|
+
return this.request("/api/v1/tier/exploratory", { prompt, learned_exploratory: learnedExploratory })
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async scoreStress(text: string): Promise<unknown> {
|
|
151
|
+
return this.request("/api/v1/stress/score", { text })
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async stressLevel(score: number): Promise<unknown> {
|
|
155
|
+
return this.request("/api/v1/stress/level", { score })
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async blackboxAnalyze(sessionId: string, entry: BlackboxEntry): Promise<unknown> {
|
|
159
|
+
return this.request("/api/v1/blackbox/analyze", {
|
|
160
|
+
session_id: sessionId,
|
|
161
|
+
project_id: entry.project_id || null,
|
|
162
|
+
user_text: entry.userText || "",
|
|
163
|
+
features: entry.features || {},
|
|
164
|
+
action: entry.action || "explore",
|
|
165
|
+
entropy: entry.entropy ?? 1.0,
|
|
166
|
+
uncertainty: entry.uncertainty ?? 50,
|
|
167
|
+
embedding: entry.embedding || null,
|
|
168
|
+
})
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async blackboxState(sessionId: string): Promise<unknown> {
|
|
172
|
+
return this.request("/api/v1/blackbox/state", { session_id: sessionId })
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
async blackboxReset(sessionId: string): Promise<unknown> {
|
|
176
|
+
return this.request("/api/v1/blackbox/reset", { session_id: sessionId })
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async blackboxOutcome(sessionId: string, outcome: unknown): Promise<unknown> {
|
|
180
|
+
return this.request("/api/v1/blackbox/outcome", { session_id: sessionId, outcome })
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async blackboxCalibrate(projectId: string): Promise<unknown> {
|
|
184
|
+
return this.request("/api/v1/blackbox/calibrate", { project_id: projectId || "global" })
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async blackboxCalibration(projectId: string): Promise<unknown> {
|
|
188
|
+
return this.request("/api/v1/blackbox/calibration?project_id=" + (projectId || "global"), null)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
async blackboxControlVector(state: unknown, action: unknown, optimizationMode: string): Promise<unknown> {
|
|
192
|
+
return this.request("/api/v1/blackbox/control-vector", { ...(state as Record<string, unknown>), action, optimization_mode: optimizationMode })
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async blackboxSelectMode(subRegime: string, stressMultiplier: number): Promise<unknown> {
|
|
196
|
+
return this.request("/api/v1/blackbox/select-mode", { sub_regime: subRegime, stress_multiplier: stressMultiplier })
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
async tddExports(sourceContent: string, ext: string): Promise<unknown> {
|
|
200
|
+
return this.request("/api/v1/tdd/exports", { source_content: sourceContent, ext })
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async tddParams(sourceContent: string, funcName: string): Promise<unknown> {
|
|
204
|
+
return this.request("/api/v1/tdd/params", { source_content: sourceContent, func_name: funcName })
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async tddInferType(paramName: string, defaultValue: unknown): Promise<unknown> {
|
|
208
|
+
return this.request("/api/v1/tdd/infer-type", { param_name: paramName, default_value: defaultValue })
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
async tddSkeleton(language: string, fileName: string, exports: unknown[], options: Record<string, unknown> = {}): Promise<unknown> {
|
|
212
|
+
return this.request("/api/v1/tdd/skeleton", { language, file_name: fileName, exports, options })
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
async patternsObserve(sessionId: string, toolName: string, input: unknown, output: unknown, directory: string): Promise<unknown> {
|
|
216
|
+
return this.request("/api/v1/patterns/observe", {
|
|
217
|
+
session_id: sessionId,
|
|
218
|
+
tool_name: toolName,
|
|
219
|
+
input,
|
|
220
|
+
output,
|
|
221
|
+
directory,
|
|
222
|
+
})
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async patternsRecord(sessionId: string, kind: string, key: string, summary: string, meta: Record<string, unknown> = {}): Promise<unknown> {
|
|
226
|
+
return this.request("/api/v1/patterns/record", {
|
|
227
|
+
session_id: sessionId,
|
|
228
|
+
kind,
|
|
229
|
+
key,
|
|
230
|
+
summary,
|
|
231
|
+
meta,
|
|
232
|
+
})
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async patternsQuery(sessionId: string, kind: string | null = null): Promise<unknown> {
|
|
236
|
+
return this.request("/api/v1/patterns/query?kind=" + (kind || ""), null)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async patternsExploratoryWords(sessionId: string): Promise<unknown> {
|
|
240
|
+
return this.request("/api/v1/patterns/exploratory-words", null)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
async patternsClear(sessionId: string): Promise<unknown> {
|
|
244
|
+
return this.request("/api/v1/patterns/clear", { session_id: sessionId })
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
async pricingFetch(openrouterKey: string, force = false): Promise<unknown> {
|
|
248
|
+
return this.request("/api/v1/pricing/fetch", { openrouter_key: openrouterKey, force })
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
async pricingLookup(model: string): Promise<unknown> {
|
|
252
|
+
return this.request("/api/v1/pricing/lookup", { model })
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
async pricingStatic(): Promise<unknown> {
|
|
256
|
+
return this.request("/api/v1/pricing/static", null)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async compressContext(text: string, threshold = 2000): Promise<unknown> {
|
|
260
|
+
return this.request("/api/v1/compress/context", { text, threshold })
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
async adminCreateSeat(name: string, email: string): Promise<unknown> {
|
|
264
|
+
return this.request("/admin/seats", { name, email }, true)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
async adminCreateSeatWithToken(name: string, email: string, tokenLabel: string | null = null): Promise<unknown> {
|
|
268
|
+
return this.request("/admin/seats", { name, email, with_token: tokenLabel || true }, true)
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async adminListSeats(): Promise<unknown> {
|
|
272
|
+
return this.request("/admin/seats", null, true)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
async adminUpdateSeat(seatId: string, status: string): Promise<unknown> {
|
|
276
|
+
return this.request("/admin/seats/" + seatId, { status }, true)
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
async adminCreateToken(seatId: string, label: string, expiresAt: string): Promise<unknown> {
|
|
280
|
+
return this.request("/admin/tokens", { seat_id: seatId, label, expires_at: expiresAt }, true)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
async adminListTokens(): Promise<unknown> {
|
|
284
|
+
return this.request("/admin/tokens", null, true)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
async adminUpdateToken(tokenId: string, status: string): Promise<unknown> {
|
|
288
|
+
return this.request("/admin/tokens/" + tokenId, { status }, true)
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
async adminDeleteToken(tokenId: string): Promise<unknown> {
|
|
292
|
+
return this.request("/admin/tokens/" + tokenId, null, true)
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
async adminUsage(days = 30): Promise<unknown> {
|
|
296
|
+
return this.request("/admin/usage?days=" + days, null, true)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
async health(): Promise<unknown> {
|
|
300
|
+
return this.request("/health", null, false)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
isFallback(): boolean {
|
|
304
|
+
return this.fallbackMode
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
class VibeOSAuthError extends Error {
|
|
309
|
+
statusCode: number
|
|
310
|
+
code?: string
|
|
311
|
+
|
|
312
|
+
constructor(message: string, statusCode: number, code?: string) {
|
|
313
|
+
super(message)
|
|
314
|
+
this.name = "VibeOSAuthError"
|
|
315
|
+
this.statusCode = statusCode
|
|
316
|
+
this.code = code
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
class VibeOSTimeoutError extends Error {
|
|
321
|
+
constructor(message: string) {
|
|
322
|
+
super(message)
|
|
323
|
+
this.name = "VibeOSTimeoutError"
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
class VibeOSNetworkError extends Error {
|
|
328
|
+
constructor(message: string) {
|
|
329
|
+
super(message)
|
|
330
|
+
this.name = "VibeOSNetworkError"
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export { VibeOSApiClient, VibeOSAuthError, VibeOSTimeoutError, VibeOSNetworkError }
|