@gabrielsmartin/orbit-sdk 0.4.4 → 0.5.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 +30 -15
- package/package.json +9 -4
- package/scripts/postinstall.cjs +36 -0
- package/src/fingerprint.js +8 -4
- package/src/index.d.ts +7 -3
- package/src/index.js +44 -24
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# @gabrielsmartin/orbit-sdk
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> The AI operating system layer. Route intelligently. Save up to 98%.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Every query has a fingerprint. Complexity, creativity, urgency, domain, emotional weight. Right now you're blasting every one of them at GPT-4o. ORBIT reads the fingerprint in milliseconds and picks the right model — automatically, invisibly, without you thinking about it.
|
|
6
6
|
|
|
7
|
-
**What it is:** ORBIT
|
|
7
|
+
**What it is:** ORBIT classifies queries across 8 axes and tells you which model to use. You make the API call. ORBIT picks the model. Zero proxy. Zero black box. Fully deterministic — you can read every routing rule in `fingerprint.js`.
|
|
8
8
|
|
|
9
|
-
**What it isn't:** a proxy,
|
|
9
|
+
**What it isn't:** a proxy, an API wrapper, or a neural network. It's fast, auditable rules — safety-critical routes (emotional content, crisis) always win, everything else is heuristic.
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
12
|
npm install @gabrielsmartin/orbit-sdk
|
|
@@ -37,7 +37,7 @@ import orbit from '@gabrielsmartin/orbit-sdk'
|
|
|
37
37
|
// Route a query — returns decision instantly, no network call
|
|
38
38
|
const { model, reason, savings } = orbit.route("write a haiku about recursion")
|
|
39
39
|
// model.name → "Claude Sonnet"
|
|
40
|
-
// model.id → "claude-sonnet-
|
|
40
|
+
// model.id → "claude-sonnet-4-6"
|
|
41
41
|
// reason → "High creativity — Claude Sonnet for open-ended generation."
|
|
42
42
|
// savings.reductionPct → 50
|
|
43
43
|
|
|
@@ -141,31 +141,44 @@ const stats = orbit.stats()
|
|
|
141
141
|
|
|
142
142
|
## Hosted API
|
|
143
143
|
|
|
144
|
-
|
|
144
|
+
Sign up at [orbitai.gtll.app](https://orbitai.gtll.app) to get your API key, then:
|
|
145
145
|
|
|
146
146
|
```bash
|
|
147
147
|
curl -X POST https://api.gtll.app/orbitRoute \
|
|
148
148
|
-H "Content-Type: application/json" \
|
|
149
|
-
-
|
|
149
|
+
-H "x-neural-secret: your-api-key" \
|
|
150
|
+
-d '{"complexity": 7, "domain": "code", "signal": "777", "api_key": "orbit_..."}'
|
|
150
151
|
```
|
|
151
152
|
|
|
152
153
|
**Pricing:**
|
|
153
154
|
|
|
154
155
|
| Tier | Price | Limit |
|
|
155
156
|
|------|-------|-------|
|
|
156
|
-
| Free | $0/mo |
|
|
157
|
-
| Pro |
|
|
158
|
-
| Team |
|
|
157
|
+
| Free | $0/mo | 1,000 queries/month |
|
|
158
|
+
| Pro | $19/mo | Unlimited · all models |
|
|
159
|
+
| Team | $99/mo | Unlimited · 5 seats |
|
|
159
160
|
|
|
160
|
-
→ [
|
|
161
|
+
→ **[Upgrade to Pro — $19/mo](https://buy.stripe.com/6oE5kF3Yz5Co06s9AB)** · [Get Team](https://buy.stripe.com/9B67sKfQ6bTE0rHgyqbwk01)
|
|
162
|
+
|
|
163
|
+
Dashboard + usage stats at [orbitai.gtll.app](https://orbitai.gtll.app)
|
|
161
164
|
|
|
162
165
|
---
|
|
163
166
|
|
|
167
|
+
## The Resonance Vision
|
|
168
|
+
|
|
169
|
+
ORBIT is the open-source core of **Resonance** — the AI operating system layer.
|
|
170
|
+
|
|
171
|
+
Every enterprise AI team is bleeding on token costs. A 50-person team running 1,000 queries/day at GPT-4o spends ~$202,500/year on tokens. With signal-aware routing, that drops to ~$57,700. Resonance captures 15% of savings — you keep the rest.
|
|
172
|
+
|
|
173
|
+
The signal layer is what makes this defensible. `777` queries generate ground-truth labels: "this type of query needs Claude." `333` labels: "this can run on Gemini Flash." At scale, that's a cross-model performance database no individual model provider can build. Only a model-agnostic layer builds this moat.
|
|
174
|
+
|
|
175
|
+
**ORBIT is the open-source foundation. The routing engine learns from every signal.**
|
|
176
|
+
|
|
164
177
|
## Research backing
|
|
165
178
|
|
|
166
179
|
- **RouteLLM (ICLR 2025, UC Berkeley):** intelligent routing achieves 85% cost reduction at 95% quality vs always-GPT-4o
|
|
167
|
-
- **OpenRouter** ($500M+ valuation) proves the market. ORBIT adds the classification layer.
|
|
168
|
-
- **Martian** (Accenture-backed) proves enterprises pay for routing. ORBIT is the open version.
|
|
180
|
+
- **OpenRouter** ($500M+ valuation) proves the market exists. ORBIT adds the classification layer OpenRouter doesn't have.
|
|
181
|
+
- **Martian** (Accenture-backed) proves enterprises pay for routing intelligence. ORBIT is the open, developer-first version.
|
|
169
182
|
|
|
170
183
|
---
|
|
171
184
|
|
|
@@ -173,8 +186,10 @@ curl -X POST https://api.gtll.app/orbitRoute \
|
|
|
173
186
|
|
|
174
187
|
- [x] v0.1.x — 8-axis classification, 6-model routing matrix
|
|
175
188
|
- [x] v0.3.x — Signal-aware routing (777/555/333), hosted gateway
|
|
176
|
-
- [
|
|
177
|
-
- [
|
|
189
|
+
- [x] v0.4.x — API key gated usage dashboard
|
|
190
|
+
- [x] v0.5.0 — Embedding-based fallback for ambiguous queries + Pro tier unlock
|
|
191
|
+
- [ ] v0.6.0 — Multi-provider streaming passthrough (OpenAI / Anthropic / Gemini)
|
|
192
|
+
- [ ] v0.7.0 — Team API keys + usage aggregation dashboard
|
|
178
193
|
- [ ] v1.0.0 — Enterprise API + savings-share pricing
|
|
179
194
|
|
|
180
195
|
---
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gabrielsmartin/orbit-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Rule-based LLM router. Classifies queries across 8 axes and picks the optimal model. Fast, deterministic, zero dependencies.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -13,10 +13,12 @@
|
|
|
13
13
|
},
|
|
14
14
|
"files": [
|
|
15
15
|
"src",
|
|
16
|
+
"scripts",
|
|
16
17
|
"README.md"
|
|
17
18
|
],
|
|
18
19
|
"scripts": {
|
|
19
|
-
"test": "node test.js"
|
|
20
|
+
"test": "node test.js",
|
|
21
|
+
"postinstall": "node scripts/postinstall.cjs"
|
|
20
22
|
},
|
|
21
23
|
"keywords": [
|
|
22
24
|
"ai",
|
|
@@ -26,6 +28,7 @@
|
|
|
26
28
|
"anthropic",
|
|
27
29
|
"gemini",
|
|
28
30
|
"orbit",
|
|
31
|
+
"resonance",
|
|
29
32
|
"cost-optimization",
|
|
30
33
|
"model-routing",
|
|
31
34
|
"selective-model-matching",
|
|
@@ -33,7 +36,9 @@
|
|
|
33
36
|
"claude",
|
|
34
37
|
"gemini-flash",
|
|
35
38
|
"grok",
|
|
36
|
-
"ai-infrastructure"
|
|
39
|
+
"ai-infrastructure",
|
|
40
|
+
"token-optimization",
|
|
41
|
+
"llm-router"
|
|
37
42
|
],
|
|
38
43
|
"author": "Gabriel Martin <gabriel@gtll.app>",
|
|
39
44
|
"license": "MIT",
|
|
@@ -41,7 +46,7 @@
|
|
|
41
46
|
"type": "git",
|
|
42
47
|
"url": "https://github.com/gtllco/orbit.git"
|
|
43
48
|
},
|
|
44
|
-
"homepage": "https://
|
|
49
|
+
"homepage": "https://github.com/gtllco/orbit",
|
|
45
50
|
"bugs": {
|
|
46
51
|
"url": "https://github.com/gtllco/orbit/issues"
|
|
47
52
|
},
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
// Fires on `npm install @gabrielsmartin/orbit-sdk`
|
|
5
|
+
// Captures install signal → ORBIT gateway → Supabase
|
|
6
|
+
// Non-blocking, silently fails, no PII
|
|
7
|
+
|
|
8
|
+
const https = require('https');
|
|
9
|
+
const os = require('os');
|
|
10
|
+
|
|
11
|
+
const payload = JSON.stringify({
|
|
12
|
+
action: 'npm_install',
|
|
13
|
+
package: '@gabrielsmartin/orbit-sdk',
|
|
14
|
+
version: require('../package.json').version,
|
|
15
|
+
node: process.version,
|
|
16
|
+
platform: process.platform,
|
|
17
|
+
arch: process.arch,
|
|
18
|
+
ts: new Date().toISOString(),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const req = https.request({
|
|
22
|
+
hostname: 'api.gtll.app',
|
|
23
|
+
path: '/npmPing',
|
|
24
|
+
method: 'POST',
|
|
25
|
+
headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) },
|
|
26
|
+
timeout: 3000,
|
|
27
|
+
}, () => {});
|
|
28
|
+
|
|
29
|
+
req.on('error', () => {});
|
|
30
|
+
req.on('timeout', () => req.destroy());
|
|
31
|
+
req.write(payload);
|
|
32
|
+
req.end();
|
|
33
|
+
|
|
34
|
+
console.log('\n\x1b[35m ⊙ ORBIT SDK installed\x1b[0m');
|
|
35
|
+
console.log('\x1b[2m Get your free API key + routing analytics:\x1b[0m');
|
|
36
|
+
console.log('\x1b[36m https://orbitai.gtll.app\x1b[0m\n');
|
package/src/fingerprint.js
CHANGED
|
@@ -9,7 +9,11 @@
|
|
|
9
9
|
const COMPLEXITY_SIGNALS = [
|
|
10
10
|
'architect','distributed','implement','design','optimize','analyze',
|
|
11
11
|
'complex','system','algorithm','concurrent','scale','infrastructure',
|
|
12
|
-
'microservice','kubernetes','terraform','recursive','refactor'
|
|
12
|
+
'microservice','kubernetes','terraform','recursive','refactor',
|
|
13
|
+
'rate limit','concurren','async','thread','cache','shard','partition',
|
|
14
|
+
'replicate','encrypt','auth','oauth','webhook','pipeline','stream',
|
|
15
|
+
'batch','migration','rollback','schema','index','transaction','latency',
|
|
16
|
+
'throughput','bottleneck','profil','benchmark','test','spec'
|
|
13
17
|
];
|
|
14
18
|
|
|
15
19
|
const CREATIVITY_SIGNALS = [
|
|
@@ -46,11 +50,11 @@ export function fingerprint(text) {
|
|
|
46
50
|
|
|
47
51
|
// Complexity (0-10): reasoning depth required
|
|
48
52
|
const complexitySignals = COMPLEXITY_SIGNALS.filter(s => t.includes(s)).length;
|
|
49
|
-
const questionDepth = (t.match(/\b(why|how|explain|compare|tradeoff|pros|cons|difference|analyze)\b/g) || []).length;
|
|
53
|
+
const questionDepth = (t.match(/\b(why|how|explain|compare|tradeoff|tradeoffs|versus|vs|pros|cons|difference|analyze|evaluate|review|audit)\b/g) || []).length;
|
|
50
54
|
const complexity = Math.min(10, Math.round(
|
|
51
|
-
complexitySignals * 2 +
|
|
55
|
+
complexitySignals * 2.5 +
|
|
52
56
|
questionDepth * 1.5 +
|
|
53
|
-
(wordCount >
|
|
57
|
+
(wordCount > 20 ? 3 : wordCount > 10 ? 1.5 : 0)
|
|
54
58
|
));
|
|
55
59
|
|
|
56
60
|
// Creativity (0-10): open-ended vs deterministic
|
package/src/index.d.ts
CHANGED
|
@@ -32,12 +32,15 @@ export interface SavingsInfo {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
export interface RoutingDecision {
|
|
35
|
-
model: ModelInfo;
|
|
35
|
+
model: ModelInfo | null;
|
|
36
36
|
reason: string;
|
|
37
37
|
rule: string;
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
signal: '777' | '555' | '333' | null;
|
|
39
|
+
signal_reason: string | null;
|
|
40
|
+
scores: QueryScores | null;
|
|
41
|
+
savings: SavingsInfo | null;
|
|
40
42
|
timestamp: string;
|
|
43
|
+
blocked: boolean;
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
export interface OrbitConfig {
|
|
@@ -55,6 +58,7 @@ export interface RouteOptions {
|
|
|
55
58
|
cost_tolerance?: 'low' | 'medium' | 'high';
|
|
56
59
|
estimated_tokens?: number;
|
|
57
60
|
blocked_models?: string[];
|
|
61
|
+
signal?: '777' | '555' | '333' | null;
|
|
58
62
|
}
|
|
59
63
|
|
|
60
64
|
export interface SessionStats {
|
package/src/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @gabrielsmartin/orbit-sdk
|
|
3
3
|
* Rule-based LLM router. Fast, deterministic, zero dependencies.
|
|
4
4
|
* Picks the right model — you make the API call.
|
|
5
|
-
*
|
|
5
|
+
*
|
|
6
6
|
* https://github.com/gtllco/orbit
|
|
7
7
|
* 777 · 555 · 333
|
|
8
8
|
*/
|
|
@@ -13,13 +13,14 @@ import { route, calculateSavings, MODEL_MATRIX } from './router.js';
|
|
|
13
13
|
export { fingerprint, applySignalBias, route, calculateSavings, MODEL_MATRIX };
|
|
14
14
|
|
|
15
15
|
const GATEWAY_URL = 'https://api.gtll.app/orbitSignup';
|
|
16
|
+
const ANON_QUERY_LIMIT = 10;
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* OrbitClient — the main class
|
|
19
|
-
*
|
|
20
|
+
*
|
|
20
21
|
* @example
|
|
21
22
|
* import { OrbitClient } from '@gabrielsmartin/orbit-sdk'
|
|
22
|
-
*
|
|
23
|
+
*
|
|
23
24
|
* const orbit = new OrbitClient({ apiKey: 'your-key' })
|
|
24
25
|
* const { model, reason, scores } = orbit.route("explain quantum entanglement")
|
|
25
26
|
* // → { model: { name: 'Claude Sonnet', id: 'claude-sonnet-3-5', ... }, reason: '...', ... }
|
|
@@ -46,12 +47,30 @@ export class OrbitClient {
|
|
|
46
47
|
/**
|
|
47
48
|
* Route a query to the optimal model (local, <1ms).
|
|
48
49
|
* ORBIT picks the model — your code makes the API call.
|
|
49
|
-
*
|
|
50
|
+
*
|
|
50
51
|
* @param {string} text - The query or prompt text
|
|
51
52
|
* @param {Object} options - Per-query overrides: { cost_tolerance, signal, estimated_tokens, blocked_models }
|
|
52
|
-
* @returns {{ model, reason, rule, scores, savings, timestamp }}
|
|
53
|
+
* @returns {{ model, reason, rule, scores, savings, timestamp, blocked }}
|
|
53
54
|
*/
|
|
54
55
|
route(text, options = {}) {
|
|
56
|
+
this._stats.total_queries++;
|
|
57
|
+
|
|
58
|
+
// Hard gate: unauthenticated users blocked after ANON_QUERY_LIMIT queries
|
|
59
|
+
if (!this.config.apiKey && this._stats.total_queries > ANON_QUERY_LIMIT) {
|
|
60
|
+
this._telemetry(text, { model: null, rule: 'unauthenticated_limit', scores: null, savings: null }, 'unauthenticated_limit').catch(() => {});
|
|
61
|
+
return {
|
|
62
|
+
model: null,
|
|
63
|
+
reason: 'Rate limit — get a free API key at orbitai.gtll.app',
|
|
64
|
+
rule: 'unauthenticated_limit',
|
|
65
|
+
signal: null,
|
|
66
|
+
signal_reason: null,
|
|
67
|
+
scores: null,
|
|
68
|
+
savings: null,
|
|
69
|
+
timestamp: new Date().toISOString(),
|
|
70
|
+
blocked: true,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
55
74
|
let scores = fingerprint(text);
|
|
56
75
|
|
|
57
76
|
if (options.cost_tolerance) {
|
|
@@ -77,52 +96,53 @@ export class OrbitClient {
|
|
|
77
96
|
scores,
|
|
78
97
|
savings,
|
|
79
98
|
timestamp: new Date().toISOString(),
|
|
99
|
+
blocked: false,
|
|
80
100
|
};
|
|
81
101
|
|
|
82
|
-
// Stats
|
|
83
|
-
this._stats.total_queries++;
|
|
84
102
|
this._stats.total_savings += savings.savings;
|
|
85
103
|
const modelName = decision.model.name;
|
|
86
104
|
this._stats.model_usage[modelName] = (this._stats.model_usage[modelName] || 0) + 1;
|
|
87
105
|
|
|
88
106
|
if (this.config.log) {
|
|
89
107
|
console.log(`[ORBIT] → ${decision.model.name} | ${decision.rule} | saved $${savings.savings.toFixed(5)} (${savings.reductionPct}% vs GPT-4o)`);
|
|
90
|
-
|
|
91
|
-
// Nudge unauthenticated users toward API key
|
|
92
|
-
if (!this.config.apiKey && this._stats.total_queries === 3) {
|
|
93
|
-
console.warn(`[ORBIT] Free tier: 100 API queries/day. Get your key → https://api.gtll.app/orbitSignup (POST { action: "get_key", email })`);
|
|
94
108
|
}
|
|
109
|
+
|
|
110
|
+
// Nudge unauthenticated users at query 5
|
|
111
|
+
if (!this.config.apiKey && this._stats.total_queries === 5) {
|
|
112
|
+
console.warn(`\n\x1b[35m[ORBIT] You've routed 5 queries — unlock full analytics + higher limits.\x1b[0m`);
|
|
113
|
+
console.warn(`\x1b[36m → https://orbitai.gtll.app\x1b[0m\n`);
|
|
114
|
+
this._telemetry(text, result, 'unauthenticated_nudge').catch(() => {});
|
|
95
115
|
}
|
|
96
116
|
|
|
97
117
|
if (this.config.on_route) {
|
|
98
118
|
this.config.on_route(result);
|
|
99
119
|
}
|
|
100
120
|
|
|
101
|
-
// Fire telemetry
|
|
102
|
-
|
|
103
|
-
this._telemetry(text, result).catch(() => {});
|
|
104
|
-
}
|
|
121
|
+
// Fire telemetry on every query (non-blocking, best-effort)
|
|
122
|
+
this._telemetry(text, result).catch(() => {});
|
|
105
123
|
|
|
106
124
|
return result;
|
|
107
125
|
}
|
|
108
126
|
|
|
109
127
|
/**
|
|
110
128
|
* Send a routing decision to the ORBIT gateway for usage tracking.
|
|
111
|
-
*
|
|
129
|
+
* Non-blocking, best-effort.
|
|
112
130
|
* @private
|
|
113
131
|
*/
|
|
114
|
-
async _telemetry(query, decision) {
|
|
132
|
+
async _telemetry(query, decision, event_type = 'sdk_route') {
|
|
115
133
|
try {
|
|
116
134
|
await fetch(GATEWAY_URL, {
|
|
117
135
|
method: 'POST',
|
|
118
136
|
headers: { 'Content-Type': 'application/json' },
|
|
119
137
|
body: JSON.stringify({
|
|
120
|
-
|
|
121
|
-
api_key: this.config.apiKey,
|
|
122
|
-
model_selected: decision.model
|
|
123
|
-
rule: decision.rule,
|
|
124
|
-
signal: decision.scores?.
|
|
125
|
-
savings_pct: decision.savings
|
|
138
|
+
action: event_type,
|
|
139
|
+
api_key: this.config.apiKey || null,
|
|
140
|
+
model_selected: decision.model?.name || null,
|
|
141
|
+
rule: decision.rule || null,
|
|
142
|
+
signal: decision.scores?.signal_applied || null,
|
|
143
|
+
savings_pct: decision.savings?.reductionPct || null,
|
|
144
|
+
total_queries: this._stats.total_queries,
|
|
145
|
+
sdk_version: '0.5.0',
|
|
126
146
|
}),
|
|
127
147
|
});
|
|
128
148
|
} catch (_) {
|
|
@@ -151,7 +171,7 @@ export class OrbitClient {
|
|
|
151
171
|
|
|
152
172
|
/**
|
|
153
173
|
* Default singleton client — zero config, ready to use
|
|
154
|
-
*
|
|
174
|
+
*
|
|
155
175
|
* @example
|
|
156
176
|
* import orbit from '@gabrielsmartin/orbit-sdk'
|
|
157
177
|
* const { model, reason } = orbit.route("write a haiku about recursion")
|