@aexol/spectral 0.3.1 → 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.
@@ -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,
@@ -150,10 +150,20 @@ const MODEL_PRICING = [
150
150
  { prefix: "meta-llama/llama-4", input: 0.20, output: 0.80, cacheWrite: 0, cacheRead: 0 },
151
151
  { prefix: "meta-llama/llama-3.3", input: 0.20, output: 0.50, cacheWrite: 0, cacheRead: 0 },
152
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
+ }
153
162
  /** Look up pricing for a modelId. Returns null when unknown. */
154
163
  function lookupPricing(modelId) {
164
+ const bare = bareModelId(modelId);
155
165
  for (const entry of MODEL_PRICING) {
156
- if (modelId.startsWith(entry.prefix)) {
166
+ if (modelId.startsWith(entry.prefix) || bare.startsWith(entry.prefix)) {
157
167
  return {
158
168
  input: entry.input,
159
169
  output: entry.output,
@@ -177,7 +187,8 @@ const REASONING_SUPPORT_PREFIXES = [
177
187
  ];
178
188
  /** Check if a modelId prefix indicates reasoning/thinking support. */
179
189
  function supportsReasoning(modelId) {
180
- return REASONING_SUPPORT_PREFIXES.some((p) => modelId.startsWith(p));
190
+ const bare = bareModelId(modelId);
191
+ return REASONING_SUPPORT_PREFIXES.some((p) => modelId.startsWith(p) || bare.startsWith(p));
181
192
  }
182
193
  /**
183
194
  * Parse the newline-delimited JSON of wire events persisted alongside an
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aexol/spectral",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Always-on coding agent for Aexol — branded pi wrapper with relay-based browser access.",
5
5
  "type": "module",
6
6
  "private": false,