@aexol/spectral 0.3.0 → 0.3.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/dist/relay/client.js
CHANGED
|
@@ -234,6 +234,17 @@ export class RelayClient extends EventEmitter {
|
|
|
234
234
|
this.exit(1);
|
|
235
235
|
return;
|
|
236
236
|
}
|
|
237
|
+
// Machine was revoked by the team admin from the Aexol Studio panel
|
|
238
|
+
// (backend sets `KnownMachine.revokedAt` and closes the socket with
|
|
239
|
+
// 4001 "machine-revoked"). Exit immediately — the machine JWT is now
|
|
240
|
+
// invalid and re-registration requires a fresh `spectral serve`.
|
|
241
|
+
if (code === 4001 && reasonStr === "machine-revoked") {
|
|
242
|
+
this.logger.error("\n✗ This machine has been disconnected from the Aexol Studio panel.");
|
|
243
|
+
this.logger.error(" Run `spectral serve` again to re-register.\n");
|
|
244
|
+
this.dispose();
|
|
245
|
+
this.exit(1);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
237
248
|
this.scheduleReconnect();
|
|
238
249
|
});
|
|
239
250
|
}
|
|
@@ -30,6 +30,7 @@ const KNOWN_KEYS = new Set([
|
|
|
30
30
|
"machineJwt",
|
|
31
31
|
"teamId",
|
|
32
32
|
"ownerId",
|
|
33
|
+
"visibility",
|
|
33
34
|
"registeredAt",
|
|
34
35
|
"hostname",
|
|
35
36
|
"version",
|
|
@@ -79,6 +80,7 @@ export async function loadMachine() {
|
|
|
79
80
|
machineJwt: parsed.machineJwt,
|
|
80
81
|
teamId: typeof parsed.teamId === "string" ? parsed.teamId : undefined,
|
|
81
82
|
ownerId: typeof parsed.ownerId === "string" ? parsed.ownerId : undefined,
|
|
83
|
+
visibility: typeof parsed.visibility === "string" ? parsed.visibility : undefined,
|
|
82
84
|
registeredAt: parsed.registeredAt,
|
|
83
85
|
hostname: parsed.hostname,
|
|
84
86
|
version: parsed.version,
|
|
@@ -109,6 +111,8 @@ export async function saveMachine(rec) {
|
|
|
109
111
|
toWrite.teamId = rec.teamId;
|
|
110
112
|
if (rec.ownerId !== undefined)
|
|
111
113
|
toWrite.ownerId = rec.ownerId;
|
|
114
|
+
if (rec.visibility !== undefined)
|
|
115
|
+
toWrite.visibility = rec.visibility;
|
|
112
116
|
if (rec.extra) {
|
|
113
117
|
for (const [k, v] of Object.entries(rec.extra))
|
|
114
118
|
toWrite[k] = v;
|
|
@@ -131,6 +131,7 @@ export async function ensureMachineRegistered(deps) {
|
|
|
131
131
|
machineJwt: obj.jwt,
|
|
132
132
|
teamId: typeof obj.teamId === "string" ? obj.teamId : undefined,
|
|
133
133
|
ownerId: typeof obj.ownerId === "string" ? obj.ownerId : undefined,
|
|
134
|
+
visibility: typeof obj.visibility === "string" ? obj.visibility : undefined,
|
|
134
135
|
registeredAt: Date.now(),
|
|
135
136
|
hostname: hostname(),
|
|
136
137
|
version: deps.version,
|
package/dist/server/pi-bridge.js
CHANGED
|
@@ -124,6 +124,12 @@ const MODEL_PRICING = [
|
|
|
124
124
|
{ prefix: "claude-3-sonnet", input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.30 },
|
|
125
125
|
{ prefix: "claude-3-haiku", input: 0.25, output: 1.25, cacheWrite: 1.25, cacheRead: 0.025 },
|
|
126
126
|
// OpenAI models
|
|
127
|
+
{ prefix: "gpt-5.5", input: 1.75, output: 14, cacheWrite: 14, cacheRead: 0.35 },
|
|
128
|
+
{ prefix: "gpt-5.4", input: 1.75, output: 14, cacheWrite: 14, cacheRead: 0.35 },
|
|
129
|
+
{ prefix: "gpt-5.3", input: 1.75, output: 14, cacheWrite: 14, cacheRead: 0.35 },
|
|
130
|
+
{ prefix: "gpt-5.2", input: 1.75, output: 14, cacheWrite: 14, cacheRead: 0.35 },
|
|
131
|
+
{ prefix: "gpt-5.1", input: 2, output: 8, cacheWrite: 8, cacheRead: 0.50 },
|
|
132
|
+
{ prefix: "gpt-5", input: 1.25, output: 10, cacheWrite: 10, cacheRead: 0.25 },
|
|
127
133
|
{ prefix: "gpt-4.1", input: 2, output: 8, cacheWrite: 8, cacheRead: 0.50 },
|
|
128
134
|
{ prefix: "gpt-4o", input: 2.50, output: 10, cacheWrite: 10, cacheRead: 1.25 },
|
|
129
135
|
{ prefix: "gpt-4-turbo", input: 10, output: 30, cacheWrite: 0, cacheRead: 0 },
|
|
@@ -144,10 +150,20 @@ const MODEL_PRICING = [
|
|
|
144
150
|
{ prefix: "meta-llama/llama-4", input: 0.20, output: 0.80, cacheWrite: 0, cacheRead: 0 },
|
|
145
151
|
{ prefix: "meta-llama/llama-3.3", input: 0.20, output: 0.50, cacheWrite: 0, cacheRead: 0 },
|
|
146
152
|
];
|
|
153
|
+
/**
|
|
154
|
+
* Strip vendor prefix to extract the bare model name.
|
|
155
|
+
* e.g. "openai/gpt-5.3-codex" → "gpt-5.3-codex".
|
|
156
|
+
* Returns the original string when no separator is present.
|
|
157
|
+
*/
|
|
158
|
+
function bareModelId(modelId) {
|
|
159
|
+
const idx = modelId.lastIndexOf("/");
|
|
160
|
+
return idx === -1 ? modelId : modelId.slice(idx + 1);
|
|
161
|
+
}
|
|
147
162
|
/** Look up pricing for a modelId. Returns null when unknown. */
|
|
148
163
|
function lookupPricing(modelId) {
|
|
164
|
+
const bare = bareModelId(modelId);
|
|
149
165
|
for (const entry of MODEL_PRICING) {
|
|
150
|
-
if (modelId.startsWith(entry.prefix)) {
|
|
166
|
+
if (modelId.startsWith(entry.prefix) || bare.startsWith(entry.prefix)) {
|
|
151
167
|
return {
|
|
152
168
|
input: entry.input,
|
|
153
169
|
output: entry.output,
|
|
@@ -158,6 +174,22 @@ function lookupPricing(modelId) {
|
|
|
158
174
|
}
|
|
159
175
|
return null;
|
|
160
176
|
}
|
|
177
|
+
/**
|
|
178
|
+
* Model prefixes known to support reasoning/thinking.
|
|
179
|
+
* Mirrors pi-ai's supportsXhigh() + additional models.
|
|
180
|
+
*/
|
|
181
|
+
const REASONING_SUPPORT_PREFIXES = [
|
|
182
|
+
"gpt-5.2", "gpt-5.3", "gpt-5.4", "gpt-5.5",
|
|
183
|
+
"claude-opus-4",
|
|
184
|
+
"o3", "o4",
|
|
185
|
+
"deepseek-r1",
|
|
186
|
+
"gemini-2.5",
|
|
187
|
+
];
|
|
188
|
+
/** Check if a modelId prefix indicates reasoning/thinking support. */
|
|
189
|
+
function supportsReasoning(modelId) {
|
|
190
|
+
const bare = bareModelId(modelId);
|
|
191
|
+
return REASONING_SUPPORT_PREFIXES.some((p) => modelId.startsWith(p) || bare.startsWith(p));
|
|
192
|
+
}
|
|
161
193
|
/**
|
|
162
194
|
* Parse the newline-delimited JSON of wire events persisted alongside an
|
|
163
195
|
* assistant message and extract all tool_call / tool_result events.
|
|
@@ -497,7 +529,7 @@ export class PiBridge {
|
|
|
497
529
|
// at our synthetic proxy provider so auth resolves to the machine JWT.
|
|
498
530
|
provider: SPECTRAL_PROXY_ANTHROPIC,
|
|
499
531
|
baseUrl,
|
|
500
|
-
reasoning:
|
|
532
|
+
reasoning: supportsReasoning(m.modelId),
|
|
501
533
|
input: ["text", "image"],
|
|
502
534
|
// Real pricing so pi can compute accurate token costs.
|
|
503
535
|
cost: pricing
|
|
@@ -527,7 +559,7 @@ export class PiBridge {
|
|
|
527
559
|
// breaking auth lookup against our synthetic proxy provider.
|
|
528
560
|
provider: SPECTRAL_PROXY_OPENAI,
|
|
529
561
|
baseUrl,
|
|
530
|
-
reasoning:
|
|
562
|
+
reasoning: supportsReasoning(m.modelId),
|
|
531
563
|
input: ["text", "image"],
|
|
532
564
|
// Real pricing so pi can compute accurate token costs.
|
|
533
565
|
cost: pricing
|
|
@@ -558,7 +590,7 @@ export class PiBridge {
|
|
|
558
590
|
api: "openai-completions",
|
|
559
591
|
provider: SPECTRAL_PROXY_USER_MODEL,
|
|
560
592
|
baseUrl,
|
|
561
|
-
reasoning:
|
|
593
|
+
reasoning: supportsReasoning(m.modelId),
|
|
562
594
|
input: ["text", "image"],
|
|
563
595
|
cost: pricing
|
|
564
596
|
? { input: pricing.input, output: pricing.output, cacheRead: pricing.cacheRead, cacheWrite: pricing.cacheWrite }
|