@aexol/spectral 0.9.247 → 0.9.249

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/CHANGELOG.md CHANGED
@@ -5,6 +5,15 @@ All notable changes to `@aexol/spectral` are documented here. Format follows
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.9.249] - 2026-10-06
9
+
10
+ ### Changed
11
+
12
+ - Release housekeeping for v0.9.249: cli-node version bump to 0.9.249, npm
13
+ lockfile version sync in `package-lock.json` (the root and package entries
14
+ were left at 0.9.247 by the v0.9.248 release), and Nix package version sync
15
+ in `nix/packages/spectral-cli.nix`.
16
+
8
17
  ## [0.9.247] - 2026-10-04
9
18
 
10
19
  ### Added
@@ -1,4 +1,3 @@
1
- export type AgentScope = "user" | "project" | "both";
2
1
  export type AgentMode = "primary" | "subagent";
3
2
  export interface AgentConfig {
4
3
  name: string;
@@ -6,13 +5,9 @@ export interface AgentConfig {
6
5
  mode: AgentMode;
7
6
  model?: string;
8
7
  systemPrompt: string;
9
- source: "user" | "project" | "cloud" | "system";
8
+ source: "cloud" | "system";
10
9
  filePath: string;
11
10
  }
12
- export interface AgentDiscoveryResult {
13
- agents: AgentConfig[];
14
- projectAgentsDir: string | null;
15
- }
16
11
  export declare const SYSTEM_AGENTS: AgentConfig[];
17
12
  export declare function setCloudAgents(agents: AgentConfig[], teamId?: string): void;
18
13
  /**
@@ -35,8 +30,15 @@ export declare function refreshCloudAgents(opts: {
35
30
  machineJwt: string;
36
31
  teamId?: string;
37
32
  }): Promise<CloudAgentRefreshResult>;
38
- export declare function discoverAgents(cwd: string, scope: AgentScope, agentDir?: string, teamId?: string): AgentDiscoveryResult;
39
- export declare function discoverPrimaryAgent(cwd: string, scope?: AgentScope, agentDir?: string, teamId?: string): AgentConfig | null;
33
+ /**
34
+ * Discover all agents available to a session: built-in system agents
35
+ * (SYSTEM_AGENTS, read-only) plus cloud agents from the backend cache
36
+ * (refreshCloudAgents, managed in Aexol Studio). Cloud agents override
37
+ * system agents on name collision. Never throws and never touches the
38
+ * network — offline / logged-out sessions simply get the system agents.
39
+ */
40
+ export declare function discoverAgents(teamId?: string): AgentConfig[];
41
+ export declare function discoverPrimaryAgent(teamId?: string): AgentConfig | null;
40
42
  /**
41
43
  * Resolve the primary agent for a session.
42
44
  *
@@ -46,7 +48,7 @@ export declare function discoverPrimaryAgent(cwd: string, scope?: AgentScope, ag
46
48
  * resolves to `null` (no fallback to auto-detect), so a stale selection never
47
49
  * silently injects an arbitrary primary agent.
48
50
  */
49
- export declare function resolveSelectedPrimaryAgent(selectedName: string | null | undefined, cwd: string, agentDir?: string, teamId?: string): AgentConfig | null;
51
+ export declare function resolveSelectedPrimaryAgent(selectedName: string | null | undefined, teamId?: string): AgentConfig | null;
50
52
  /**
51
53
  * Prepend the primary agent's system prompt above the base system prompt.
52
54
  *
@@ -1 +1 @@
1
- {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/agent/agents.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;AACrD,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;AAC/C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;IAChD,QAAQ,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AA6ED,eAAO,MAAM,aAAa,EAAE,WAAW,EAkDtC,CAAC;AA0DF,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAO3E;AACD;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,yEAAyE;IACzE,YAAY,EAAE,IAAI,CAAC;IACnB,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG;IACF,YAAY,EAAE,KAAK,CAAC;IACpB,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CA6EnC;AAkBD,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,UAAU,EACjB,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,oBAAoB,CAmBtB;AACD,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,EACX,KAAK,GAAE,UAAmB,EAC1B,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,WAAW,GAAG,IAAI,CAepB;AACD;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CACzC,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACvC,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,WAAW,GAAG,IAAI,CAgBpB;AACD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,YAAY,EAAE,IAAI,CAChB,WAAW,EACX,MAAM,GAAG,aAAa,GAAG,cAAc,GAAG,OAAO,GAAG,QAAQ,CAC7D,GAAG,IAAI,GACP,MAAM,GAAG,SAAS,CAQpB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,IAAI,CACT,WAAW,EACX,MAAM,GAAG,aAAa,GAAG,cAAc,GAAG,OAAO,GAAG,QAAQ,CAC7D,GAAG,IAAI,GACP,MAAM,CAgBR"}
1
+ {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/agent/agents.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;AAC/C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;CAClB;AA6ED,eAAO,MAAM,aAAa,EAAE,WAAW,EAkDtC,CAAC;AAkBF,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAO3E;AACD;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,yEAAyE;IACzE,YAAY,EAAE,IAAI,CAAC;IACnB,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG;IACF,YAAY,EAAE,KAAK,CAAC;IACpB,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CA6EnC;AACD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,MAAM,CAAC,EAAE,MAAM,GACd,WAAW,EAAE,CAMf;AACD,wBAAgB,oBAAoB,CAClC,MAAM,CAAC,EAAE,MAAM,GACd,WAAW,GAAG,IAAI,CAiBpB;AACD;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CACzC,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACvC,MAAM,CAAC,EAAE,MAAM,GACd,WAAW,GAAG,IAAI,CAgBpB;AACD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,YAAY,EAAE,IAAI,CAChB,WAAW,EACX,MAAM,GAAG,aAAa,GAAG,cAAc,GAAG,OAAO,GAAG,QAAQ,CAC7D,GAAG,IAAI,GACP,MAAM,GAAG,SAAS,CAQpB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,IAAI,CACT,WAAW,EACX,MAAM,GAAG,aAAa,GAAG,cAAc,GAAG,OAAO,GAAG,QAAQ,CAC7D,GAAG,IAAI,GACP,MAAM,CAYR"}
@@ -1,7 +1,4 @@
1
- import * as fs from "node:fs";
2
- import * as path from "node:path";
3
1
  import chalk from "chalk";
4
- import { getAgentDir, parseFrontmatter } from "../sdk/coding-agent/index.js";
5
2
  import { classifyGraphqlError, createBackendClient, graphqlErrorMessage, scalars, } from "../generated/graphql-client.js";
6
3
  const GHOST_SYSTEM_PROMPT = [
7
4
  "You are ghost, the built-in system orchestrator. Your job is to plan, coordinate, and integrate — not to do the work yourself. Delegate through the `subagent` tool to these subagents:",
@@ -119,44 +116,6 @@ export const SYSTEM_AGENTS = [
119
116
  filePath: "system:fork",
120
117
  },
121
118
  ];
122
- function loadAgentsFromDir(dir, source) {
123
- const agents = [];
124
- if (!fs.existsSync(dir))
125
- return agents;
126
- let entries;
127
- try {
128
- entries = fs.readdirSync(dir, { withFileTypes: true });
129
- }
130
- catch {
131
- return agents;
132
- }
133
- for (const entry of entries) {
134
- if (!entry.name.endsWith(".md") ||
135
- (!entry.isFile() && !entry.isSymbolicLink()))
136
- continue;
137
- const filePath = path.join(dir, entry.name);
138
- let content;
139
- try {
140
- content = fs.readFileSync(filePath, "utf-8");
141
- }
142
- catch {
143
- continue;
144
- }
145
- const { frontmatter, body } = parseFrontmatter(content);
146
- if (!frontmatter.name || !frontmatter.description)
147
- continue;
148
- agents.push({
149
- name: frontmatter.name,
150
- description: frontmatter.description,
151
- mode: frontmatter.mode === "primary" ? "primary" : "subagent",
152
- model: frontmatter.model,
153
- systemPrompt: body,
154
- source,
155
- filePath,
156
- });
157
- }
158
- return agents;
159
- }
160
119
  const LEGACY_CLOUD_TEAM = "__legacy__";
161
120
  const cloudAgentsByTeam = new Map();
162
121
  function getCloudAgentCache(teamId) {
@@ -251,55 +210,32 @@ export async function refreshCloudAgents(opts) {
251
210
  cache.inFlight = refresh;
252
211
  return refresh;
253
212
  }
254
- function isDirectory(p) {
255
- try {
256
- return fs.statSync(p).isDirectory();
257
- }
258
- catch {
259
- return false;
260
- }
261
- }
262
- function findNearestProjectAgentsDir(cwd) {
263
- let currentDir = cwd;
264
- while (true) {
265
- const candidate = path.join(currentDir, ".spectral", "agents");
266
- if (isDirectory(candidate))
267
- return candidate;
268
- const parentDir = path.dirname(currentDir);
269
- if (parentDir === currentDir)
270
- return null;
271
- currentDir = parentDir;
272
- }
273
- }
274
- export function discoverAgents(cwd, scope, agentDir, teamId) {
275
- const userDir = path.join(agentDir ?? getAgentDir(), "agents");
276
- const projectAgentsDir = findNearestProjectAgentsDir(cwd);
277
- const userAgents = scope === "project" ? [] : loadAgentsFromDir(userDir, "user");
278
- const projectAgents = scope === "user" || !projectAgentsDir
279
- ? []
280
- : loadAgentsFromDir(projectAgentsDir, "project");
281
- const cloudAgents = scope === "both"
282
- ? getCloudAgentCache(teamId ?? LEGACY_CLOUD_TEAM).agents
283
- : [];
213
+ /**
214
+ * Discover all agents available to a session: built-in system agents
215
+ * (SYSTEM_AGENTS, read-only) plus cloud agents from the backend cache
216
+ * (refreshCloudAgents, managed in Aexol Studio). Cloud agents override
217
+ * system agents on name collision. Never throws and never touches the
218
+ * network — offline / logged-out sessions simply get the system agents.
219
+ */
220
+ export function discoverAgents(teamId) {
221
+ const cloudAgents = getCloudAgentCache(teamId ?? LEGACY_CLOUD_TEAM).agents;
284
222
  const agentMap = new Map();
285
223
  for (const agent of SYSTEM_AGENTS)
286
224
  agentMap.set(agent.name, agent);
287
225
  for (const agent of cloudAgents)
288
226
  agentMap.set(agent.name, agent);
289
- for (const agent of projectAgents)
290
- agentMap.set(agent.name, agent);
291
- for (const agent of userAgents)
292
- agentMap.set(agent.name, agent);
293
- return { agents: Array.from(agentMap.values()), projectAgentsDir };
227
+ return Array.from(agentMap.values());
294
228
  }
295
- export function discoverPrimaryAgent(cwd, scope = "both", agentDir, teamId) {
296
- const { agents } = discoverAgents(cwd, scope, agentDir, teamId);
229
+ export function discoverPrimaryAgent(teamId) {
230
+ const agents = discoverAgents(teamId);
297
231
  const primaries = agents.filter((a) => a.mode === "primary");
298
232
  if (primaries.length === 0)
299
233
  return null;
300
234
  if (primaries.length > 1) {
301
- const userPrimary = primaries.find((a) => a.source === "user");
302
- const chosen = userPrimary ?? primaries[0];
235
+ // Cloud agents override built-in system agents (same precedence as
236
+ // discovery): a cloud primary always wins over the built-in ghost.
237
+ const cloudPrimary = primaries.find((a) => a.source === "cloud");
238
+ const chosen = cloudPrimary ?? primaries[0];
303
239
  console.warn(chalk.yellow(`Multiple primary agents found (${primaries.map((a) => a.name).join(", ")}). Using "${chosen.name}".`));
304
240
  return chosen;
305
241
  }
@@ -314,7 +250,7 @@ export function discoverPrimaryAgent(cwd, scope = "both", agentDir, teamId) {
314
250
  * resolves to `null` (no fallback to auto-detect), so a stale selection never
315
251
  * silently injects an arbitrary primary agent.
316
252
  */
317
- export function resolveSelectedPrimaryAgent(selectedName, cwd, agentDir, teamId) {
253
+ export function resolveSelectedPrimaryAgent(selectedName, teamId) {
318
254
  if (selectedName === undefined ||
319
255
  selectedName === null ||
320
256
  selectedName === "__auto__" ||
@@ -322,7 +258,7 @@ export function resolveSelectedPrimaryAgent(selectedName, cwd, agentDir, teamId)
322
258
  selectedName === "__none__") {
323
259
  return null;
324
260
  }
325
- const { agents } = discoverAgents(cwd, "both", agentDir, teamId);
261
+ const agents = discoverAgents(teamId);
326
262
  return (agents.find((agent) => agent.mode === "primary" && agent.name === selectedName) ?? null);
327
263
  }
328
264
  /**
@@ -360,11 +296,7 @@ export function agentMetadataBlock(agent) {
360
296
  }
361
297
  const sourceLabel = agent.source === "cloud"
362
298
  ? "cloud backend (managed in Aexol Studio; not a local file)"
363
- : agent.source === "project"
364
- ? "project file (.spectral/agents)"
365
- : agent.source === "system"
366
- ? "built-in system agent (read-only)"
367
- : "user file (~/.spectral/agents)";
299
+ : "built-in system agent (read-only)";
368
300
  lines.push(`Source: ${sourceLabel}`);
369
301
  return `\n\n## Agent metadata\n${lines.map((l) => `- ${l}`).join("\n")}`;
370
302
  }
@@ -12,9 +12,9 @@
12
12
  * - Parallel: { tasks: [{ agent, task }, ...] } (max 8, 4 concurrent)
13
13
  * - Chain: { chain: [{ agent, task: "... {previous} ..." }, ...] }
14
14
  *
15
- * Agent definitions live as markdown files with YAML frontmatter:
16
- * - ~/.spectral/agent/agents/*.md (user-level, always loaded)
17
- * - .spectral/agents/*.md (project-level, opt-in via agentScope)
15
+ * Agents come from two sources only:
16
+ * - Built-in system agents (SYSTEM_AGENTS, read-only)
17
+ * - Cloud agents from the backend cache (managed in Aexol Studio /agents)
18
18
  *
19
19
  * Subagents use an in-process `agentLoop()` for:
20
20
  * - Clean context isolation (fresh messages array)
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAEX,UAAU,EAEV,SAAS,EAET,MAAM,4BAA4B,CAAC;AAqBpC,OAAO,EACN,KAAK,YAAY,EACjB,KAAK,gBAAgB,EAKrB,MAAM,8BAA8B,CAAC;AAItC,OAAO,EACN,KAAK,WAAW,EAKhB,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAGN,KAAK,cAAc,EACnB,MAAM,uCAAuC,CAAC;AAS/C,OAAO,KAAK,EAAE,sBAAsB,EAAgB,MAAM,6CAA6C,CAAC;AAyGxG;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACxC,gBAAgB,EAAE,MAAM,GAAG,SAAS,EACpC,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,GAAG,cAAc,GAAG,OAAO,GAAG,QAAQ,CAAC,GACpF,MAAM,CAYR;AA2ND;;;GAGG;AACH,wBAAgB,oCAAoC,CACnD,cAAc,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,GAChD,IAAI,CAAC,sBAAsB,EAAE,WAAW,GAAG,cAAc,CAAC,CAe5D;AAgCD,wBAAgB,oBAAoB,CACnC,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,YAAY,EACjB,GAAG,EAAE,gBAAgB,EACrB,SAAS,CAAC,EAAE,MAAM,GAChB,SAAS,EAAE,CAkDb;AAyBD;;;;;;;;;;GAUG;AACH;;;;;;GAMG;AACH,MAAM,WAAW,wBAAwB;IACxC,IAAI,EAAE,uBAAuB,CAAC;IAC9B,6EAA6E;IAC7E,GAAG,EAAE,cAAc,CAAC;CACpB;AAED,8EAA8E;AAC9E,MAAM,MAAM,qBAAqB,GAAG,UAAU,GAAG,wBAAwB,CAAC;AAmF1E,2FAA2F;AAC3F,wBAAgB,+BAA+B,CAC9C,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,GACtD,IAAI,CAEN;AAmBD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACzC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,QAAQ,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,GAC9D,MAAM,CAiBR;AAmmBD,MAAM,CAAC,OAAO,UAAU,iBAAiB,CACxC,GAAG,EAAE,YAAY,EACjB,IAAI,CAAC,EAAE;IACN,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB,GACC,IAAI,CA+cN"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAEX,UAAU,EAEV,SAAS,EAET,MAAM,4BAA4B,CAAC;AAoBpC,OAAO,EACN,KAAK,YAAY,EACjB,KAAK,gBAAgB,EAKrB,MAAM,8BAA8B,CAAC;AAItC,OAAO,EACN,KAAK,WAAW,EAIhB,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAGN,KAAK,cAAc,EACnB,MAAM,uCAAuC,CAAC;AAS/C,OAAO,KAAK,EAAE,sBAAsB,EAAgB,MAAM,6CAA6C,CAAC;AAyGxG;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACxC,gBAAgB,EAAE,MAAM,GAAG,SAAS,EACpC,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,GAAG,cAAc,GAAG,OAAO,GAAG,QAAQ,CAAC,GACpF,MAAM,CAYR;AAyND;;;GAGG;AACH,wBAAgB,oCAAoC,CACnD,cAAc,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,GAChD,IAAI,CAAC,sBAAsB,EAAE,WAAW,GAAG,cAAc,CAAC,CAe5D;AAgCD,wBAAgB,oBAAoB,CACnC,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,YAAY,EACjB,GAAG,EAAE,gBAAgB,EACrB,SAAS,CAAC,EAAE,MAAM,GAChB,SAAS,EAAE,CAkDb;AAyBD;;;;;;;;;;GAUG;AACH;;;;;;GAMG;AACH,MAAM,WAAW,wBAAwB;IACxC,IAAI,EAAE,uBAAuB,CAAC;IAC9B,6EAA6E;IAC7E,GAAG,EAAE,cAAc,CAAC;CACpB;AAED,8EAA8E;AAC9E,MAAM,MAAM,qBAAqB,GAAG,UAAU,GAAG,wBAAwB,CAAC;AAmF1E,2FAA2F;AAC3F,wBAAgB,+BAA+B,CAC9C,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,GACtD,IAAI,CAEN;AAmBD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACzC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,QAAQ,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,GAC9D,MAAM,CAiBR;AAqlBD,MAAM,CAAC,OAAO,UAAU,iBAAiB,CACxC,GAAG,EAAE,YAAY,EACjB,IAAI,CAAC,EAAE;IACN,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB,GACC,IAAI,CAmaN"}
@@ -12,9 +12,9 @@
12
12
  * - Parallel: { tasks: [{ agent, task }, ...] } (max 8, 4 concurrent)
13
13
  * - Chain: { chain: [{ agent, task: "... {previous} ..." }, ...] }
14
14
  *
15
- * Agent definitions live as markdown files with YAML frontmatter:
16
- * - ~/.spectral/agent/agents/*.md (user-level, always loaded)
17
- * - .spectral/agents/*.md (project-level, opt-in via agentScope)
15
+ * Agents come from two sources only:
16
+ * - Built-in system agents (SYSTEM_AGENTS, read-only)
17
+ * - Cloud agents from the backend cache (managed in Aexol Studio /agents)
18
18
  *
19
19
  * Subagents use an in-process `agentLoop()` for:
20
20
  * - Clean context isolation (fresh messages array)
@@ -31,7 +31,7 @@
31
31
  */
32
32
  import { agentLoop, agentLoopContinue, } from "../sdk/agent-core/index.js";
33
33
  import { buildIsolatedRequestTimePrunedMessagesResult, COMPACT_CONTEXT_TOOL_NAME, } from "../memory/tools/compact-context.js";
34
- import { isRateLimitError, isTransientApiError, isContextOverflow, isPaymentRequiredError, StringEnum, streamSimple, } from "../sdk/ai/index.js";
34
+ import { isRateLimitError, isTransientApiError, isContextOverflow, isPaymentRequiredError, streamSimple, } from "../sdk/ai/index.js";
35
35
  import { RETRY_DEFAULT_BASE_DELAY_MS, RETRY_DEFAULT_MAX_RETRIES, RETRY_MAX_BACKOFF_DELAY_MS, } from "../sdk/coding-agent/index.js";
36
36
  import { mutateSystemPrompt } from "../sdk/coding-agent/core/system-prompt-mutator.js";
37
37
  import { sleep } from "../sdk/coding-agent/utils/sleep.js";
@@ -929,10 +929,6 @@ const ChainItem = Type.Object({
929
929
  }),
930
930
  cwd: Type.Optional(Type.String({ description: "Working directory for the agent process" })),
931
931
  });
932
- const AgentScopeSchema = StringEnum(["user", "project", "both"], {
933
- description: 'Which agent directories to use. Default: "both" (user + project agents).',
934
- default: "both",
935
- });
936
932
  const SubagentParams = Type.Object({
937
933
  agent: Type.Optional(Type.String({
938
934
  description: "Known agent name to invoke (single mode; use names from the available agents list)",
@@ -948,11 +944,6 @@ const SubagentParams = Type.Object({
948
944
  description: "Sequential steps of {agent, task}; {previous} substitutes the previous step's output (max 8 steps)",
949
945
  minItems: 1,
950
946
  })),
951
- agentScope: Type.Optional(AgentScopeSchema),
952
- confirmProjectAgents: Type.Optional(Type.Boolean({
953
- description: "Prompt before running project-local agents. Default: true.",
954
- default: true,
955
- })),
956
947
  cwd: Type.Optional(Type.String({
957
948
  description: "Working directory for the agent process (single mode)",
958
949
  })),
@@ -972,8 +963,8 @@ export default function subagentExtension(ext, opts) {
972
963
  description: [
973
964
  "Delegate tasks to specialized subagents with isolated context.",
974
965
  "Modes: single (agent + task), parallel (tasks array), chain (sequential with {previous} placeholder).",
975
- 'Default agent scope is "both" (user agents from ~/.spectral/agent/agents + project agents from .spectral/agents).',
976
- 'Set agentScope: "user" or "project" to limit scope.',
966
+ "Agents come from two sources only: built-in system agents (read-only) and cloud agents from the backend cache (managed in Aexol Studio /agents).",
967
+ "Local agent files are not read; manage cloud agents in the Studio /agents page.",
977
968
  "Exactly one mode per call.",
978
969
  'Single (one task): {"agent":"researcher","task":"<full self-contained task text>"}',
979
970
  'Parallel (independent tasks; max 8, 4 run concurrently): {"tasks":[{"agent":"researcher","task":"..."},{"agent":"executor","task":"..."}]}',
@@ -1003,30 +994,23 @@ export default function subagentExtension(ext, opts) {
1003
994
  ],
1004
995
  details: {
1005
996
  mode: "single",
1006
- agentScope: (params.agentScope ?? "both"),
1007
- projectAgentsDir: null,
1008
997
  results: [],
1009
998
  },
1010
999
  };
1011
1000
  }
1012
- const agentScope = params.agentScope ?? "both";
1013
- const discovery = discoverAgents(ctx.cwd, agentScope, undefined, opts?.teamId);
1014
1001
  // Merge registration-time disabled list (from session start) with the
1015
1002
  // live disabled list (just read from disk) so both are honored.
1016
1003
  const disabledSet = new Set([
1017
1004
  ...(opts?.disabledAgents ?? []),
1018
1005
  ...(liveSettings.disabledSubagents ?? []),
1019
1006
  ]);
1020
- const agents = discovery.agents.filter((a) => !disabledSet.has(a.name));
1021
- const confirmProjectAgents = params.confirmProjectAgents ?? false;
1007
+ const agents = discoverAgents(opts?.teamId).filter((a) => !disabledSet.has(a.name));
1022
1008
  const hasChain = (params.chain?.length ?? 0) > 0;
1023
1009
  const hasTasks = (params.tasks?.length ?? 0) > 0;
1024
1010
  const hasSingle = Boolean(params.agent && params.task);
1025
1011
  const modeCount = Number(hasChain) + Number(hasTasks) + Number(hasSingle);
1026
1012
  const makeDetails = (mode) => (results) => ({
1027
1013
  mode,
1028
- agentScope,
1029
- projectAgentsDir: discovery.projectAgentsDir,
1030
1014
  results,
1031
1015
  });
1032
1016
  // Forward internal subagent tool lifecycle events to the bridge so the
@@ -1112,37 +1096,6 @@ export default function subagentExtension(ext, opts) {
1112
1096
  details: makeDetails("single")([]),
1113
1097
  };
1114
1098
  }
1115
- // Security: if project-local agents are enabled, confirm with user.
1116
- // In headless mode (no TUI), project-local agents are silently allowed —
1117
- // the caller is already trusted (it's the coding agent itself).
1118
- if ((agentScope === "project" || agentScope === "both") &&
1119
- confirmProjectAgents &&
1120
- ctx.hasUI) {
1121
- const requestedAgentNames = new Set();
1122
- if (params.chain)
1123
- for (const step of params.chain)
1124
- requestedAgentNames.add(step.agent.replace(/^@/, ""));
1125
- if (params.tasks)
1126
- for (const t of params.tasks)
1127
- requestedAgentNames.add(t.agent.replace(/^@/, ""));
1128
- if (params.agent)
1129
- requestedAgentNames.add(params.agent.replace(/^@/, ""));
1130
- const projectAgentsRequested = Array.from(requestedAgentNames)
1131
- .map((name) => agents.find((a) => a.name === name))
1132
- .filter((a) => a?.source === "project");
1133
- if (projectAgentsRequested.length > 0) {
1134
- const names = projectAgentsRequested.map((a) => a.name).join(", ");
1135
- const dir = discovery.projectAgentsDir ?? "(unknown)";
1136
- const ok = await ctx.ui.confirm("Run project-local agents?", `Agents: ${names}\nSource: ${dir}\n\nProject agents are repo-controlled. Only continue for trusted repositories.`);
1137
- if (!ok)
1138
- return {
1139
- content: [
1140
- { type: "text", text: "Canceled: project-local agents not approved." },
1141
- ],
1142
- details: makeDetails(hasChain ? "chain" : hasTasks ? "parallel" : "single")([]),
1143
- };
1144
- }
1145
- }
1146
1099
  // ── Chain mode ──────────────────────────────────────────────
1147
1100
  if (params.chain && params.chain.length > 0) {
1148
1101
  if (params.chain.length > MAX_CHAIN_STEPS)
@@ -1 +1 @@
1
- {"version":3,"file":"const.d.ts","sourceRoot":"","sources":["../../../src/generated/zeus/const.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAC,GAAG,CAy0B5C,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAC,GAAG,CAqpC1C,CAAA;AAED,eAAO,MAAM,GAAG;;;;CAIf,CAAA"}
1
+ {"version":3,"file":"const.d.ts","sourceRoot":"","sources":["../../../src/generated/zeus/const.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAC,GAAG,CAw4B5C,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAC,GAAG,CAg1C1C,CAAA;AAED,eAAO,MAAM,GAAG;;;;CAIf,CAAA"}
@@ -217,7 +217,12 @@ export const AllTypesProps = {
217
217
  seoIndexationStatus: {},
218
218
  seoIndexationReport: {},
219
219
  seoAuditTasks: {},
220
- seoAuditTask: {}
220
+ seoAuditTask: {},
221
+ adminLyceumModelStatus: {},
222
+ adminVastAiOffers: {
223
+ query: "AdminVastAiOfferQueryInput"
224
+ },
225
+ adminRunPodPods: {}
221
226
  },
222
227
  Mutation: {
223
228
  register: {
@@ -394,6 +399,26 @@ export const AllTypesProps = {
394
399
  adminSetUserGlobalRole: {
395
400
  globalRole: "GlobalRole"
396
401
  },
402
+ adminStartLyceumVm: {
403
+ input: "AdminStartLyceumVmInput"
404
+ },
405
+ adminStopLyceumVm: {},
406
+ adminInstallLyceumModel: {
407
+ custom: "AdminCustomLyceumModelInput"
408
+ },
409
+ adminStopLyceumModel: {},
410
+ adminCreateVastAiInstance: {
411
+ input: "AdminCreateVastAiInstanceInput"
412
+ },
413
+ adminStartVastAiInstance: {},
414
+ adminStopVastAiInstance: {},
415
+ adminDestroyVastAiInstance: {},
416
+ adminCreateRunPod: {
417
+ input: "AdminCreateRunPodInput"
418
+ },
419
+ adminStartRunPod: {},
420
+ adminStopRunPod: {},
421
+ adminTerminateRunPod: {},
397
422
  maintainerCreateDedicatedClientTeam: {
398
423
  members: "CreateTeamMemberInput"
399
424
  },
@@ -503,6 +528,16 @@ export const AllTypesProps = {
503
528
  AdminCreateCreditPackInput: {},
504
529
  AdminUpdateCreditPackInput: {},
505
530
  ModelScope: "enum",
531
+ AdminStartLyceumVmInput: {},
532
+ AdminLyceumEnvOverrideInput: {},
533
+ AdminCustomLyceumModelInput: {
534
+ env: "AdminLyceumEnvOverrideInput"
535
+ },
536
+ AdminVastAiOfferQueryInput: {},
537
+ AdminCreateVastAiInstanceInput: {},
538
+ AdminCreateRunPodInput: {
539
+ env: "JSON"
540
+ },
506
541
  BaseModelUpdateInput: {},
507
542
  BaseModelCreateInput: {
508
543
  capabilities: "JSON"
@@ -1067,7 +1102,20 @@ export const ReturnTypes = {
1067
1102
  seoConnectionStatus: "SeoConnectionStatus",
1068
1103
  seoListProperties: "GscProperty",
1069
1104
  seoAuditTasks: "SeoAuditTask",
1070
- seoAuditTask: "SeoAuditTask"
1105
+ seoAuditTask: "SeoAuditTask",
1106
+ adminLyceumVms: "AdminLyceumVm",
1107
+ adminLyceumAvailability: "AdminLyceumAvailabilityItem",
1108
+ adminLyceumSettings: "AdminLyceumSettings",
1109
+ adminLyceumModelProfiles: "AdminLyceumModelProfile",
1110
+ adminLyceumModelStatus: "AdminLyceumModelStatus",
1111
+ adminVastAiAccount: "AdminVastAiAccount",
1112
+ adminVastAiSettings: "AdminVastAiSettings",
1113
+ adminVastAiOffers: "AdminVastAiOffer",
1114
+ adminVastAiInstances: "AdminVastAiInstance",
1115
+ adminRunPodAccount: "AdminRunPodAccount",
1116
+ adminRunPodSettings: "AdminRunPodSettings",
1117
+ adminRunPodPods: "AdminRunPodPod",
1118
+ adminRunPodGpuTypes: "AdminRunPodGpuType"
1071
1119
  },
1072
1120
  Mutation: {
1073
1121
  register: "AuthPayload",
@@ -1163,6 +1211,18 @@ export const ReturnTypes = {
1163
1211
  adminResendTeamInvite: "AdminTeamInvite",
1164
1212
  adminRevokeTeamInvite: "AdminTeamInvite",
1165
1213
  adminSetUserGlobalRole: "AdminUserInfo",
1214
+ adminStartLyceumVm: "AdminLyceumVm",
1215
+ adminStopLyceumVm: "AdminLyceumVmOperation",
1216
+ adminInstallLyceumModel: "AdminLyceumVmOperation",
1217
+ adminStopLyceumModel: "AdminLyceumVmOperation",
1218
+ adminCreateVastAiInstance: "AdminVastAiInstance",
1219
+ adminStartVastAiInstance: "AdminVastAiOperation",
1220
+ adminStopVastAiInstance: "AdminVastAiOperation",
1221
+ adminDestroyVastAiInstance: "AdminVastAiOperation",
1222
+ adminCreateRunPod: "AdminRunPodPod",
1223
+ adminStartRunPod: "AdminRunPodOperation",
1224
+ adminStopRunPod: "AdminRunPodOperation",
1225
+ adminTerminateRunPod: "AdminRunPodOperation",
1166
1226
  maintainerCreateDedicatedClientTeam: "TeamInvite",
1167
1227
  adminSetBuiltInModelSortOrder: "UserModel",
1168
1228
  adminSyncModelsDev: "AdminSyncResult",
@@ -1593,6 +1653,168 @@ export const ReturnTypes = {
1593
1653
  total: "Int",
1594
1654
  syncedAt: "String"
1595
1655
  },
1656
+ AdminLyceumVm: {
1657
+ vmId: "String",
1658
+ status: "String",
1659
+ name: "String",
1660
+ displayName: "String",
1661
+ hardwareProfile: "String",
1662
+ gpuCount: "Int",
1663
+ instanceType: "String",
1664
+ ipAddress: "String",
1665
+ sshCommand: "String",
1666
+ uptimeSeconds: "Int",
1667
+ billed: "Float",
1668
+ croesusBilled: "Float",
1669
+ createdAt: "String",
1670
+ statusCheckUrl: "String"
1671
+ },
1672
+ AdminLyceumVmOperation: {
1673
+ vmId: "String",
1674
+ status: "String",
1675
+ message: "String"
1676
+ },
1677
+ AdminLyceumAvailabilityItem: {
1678
+ hardwareProfile: "String",
1679
+ label: "String",
1680
+ pricePerHour: "Float",
1681
+ gpuCounts: "Int",
1682
+ availableGpuCounts: "Int",
1683
+ available: "Boolean"
1684
+ },
1685
+ AdminLyceumSettings: {
1686
+ sshPrivateKeyConfigured: "Boolean"
1687
+ },
1688
+ AdminLyceumModelProfile: {
1689
+ id: "String",
1690
+ label: "String",
1691
+ model: "String",
1692
+ image: "String",
1693
+ supportedHardware: "String",
1694
+ mtpTokens: "Int",
1695
+ description: "String"
1696
+ },
1697
+ AdminLyceumModelStatus: {
1698
+ vmId: "String",
1699
+ ipAddress: "String",
1700
+ containerRunning: "Boolean",
1701
+ containerStatus: "String",
1702
+ model: "String",
1703
+ endpoint: "String",
1704
+ apiReady: "Boolean",
1705
+ logTail: "String",
1706
+ error: "String"
1707
+ },
1708
+ AdminVastAiAccount: {
1709
+ balance: "Float",
1710
+ credit: "Float",
1711
+ email: "String",
1712
+ sshKeyConfigured: "Boolean",
1713
+ sshKey: "String"
1714
+ },
1715
+ AdminVastAiSettings: {
1716
+ apiKeyConfigured: "Boolean",
1717
+ sshKeyDerived: "Boolean"
1718
+ },
1719
+ AdminVastAiOffer: {
1720
+ offerId: "String",
1721
+ gpuName: "String",
1722
+ numGpus: "Int",
1723
+ gpuRamMb: "Int",
1724
+ cpuCores: "Int",
1725
+ cpuRamMb: "Int",
1726
+ diskSpaceGb: "Float",
1727
+ dphTotal: "Float",
1728
+ dphBase: "Float",
1729
+ inetDown: "Float",
1730
+ inetUp: "Float",
1731
+ geolocation: "String",
1732
+ rentable: "Boolean",
1733
+ rented: "Boolean",
1734
+ verified: "Boolean",
1735
+ reliability: "Float",
1736
+ cudaMaxGood: "Float",
1737
+ driverVersion: "String",
1738
+ machineId: "Int",
1739
+ publicIpaddr: "String",
1740
+ directPortCount: "Int",
1741
+ isBid: "Boolean"
1742
+ },
1743
+ AdminVastAiInstance: {
1744
+ instanceId: "String",
1745
+ actualStatus: "String",
1746
+ intendedStatus: "String",
1747
+ curState: "String",
1748
+ label: "String",
1749
+ gpuName: "String",
1750
+ numGpus: "Int",
1751
+ dphTotal: "Float",
1752
+ sshHost: "String",
1753
+ sshPort: "Int",
1754
+ sshCommand: "String",
1755
+ publicIpaddr: "String",
1756
+ uptimeMins: "Int",
1757
+ diskSpaceGb: "Float",
1758
+ imageUuid: "String",
1759
+ startedAt: "String"
1760
+ },
1761
+ AdminVastAiOperation: {
1762
+ instanceId: "String",
1763
+ status: "String",
1764
+ message: "String"
1765
+ },
1766
+ AdminRunPodAccount: {
1767
+ balance: "Float",
1768
+ spendPerHr: "Float",
1769
+ email: "String",
1770
+ sshKeyCount: "Int"
1771
+ },
1772
+ AdminRunPodSettings: {
1773
+ apiKeyConfigured: "Boolean",
1774
+ sshKeyDerived: "Boolean"
1775
+ },
1776
+ AdminRunPodPod: {
1777
+ podId: "String",
1778
+ name: "String",
1779
+ image: "String",
1780
+ containerDiskInGb: "Int",
1781
+ ports: "String",
1782
+ env: "JSON",
1783
+ status: "String",
1784
+ locked: "Boolean",
1785
+ costPerHr: "Float",
1786
+ createdAt: "String",
1787
+ startedAt: "String",
1788
+ gpuTypeId: "String",
1789
+ gpuCount: "Int",
1790
+ cloudType: "String",
1791
+ dataCenterId: "String",
1792
+ cudaVersion: "String",
1793
+ sshHost: "String",
1794
+ sshPort: "Int",
1795
+ sshUsername: "String",
1796
+ sshCommand: "String",
1797
+ hasRuntime: "Boolean"
1798
+ },
1799
+ AdminRunPodGpuType: {
1800
+ id: "String",
1801
+ displayName: "String",
1802
+ manufacturer: "String",
1803
+ memoryGb: "Int",
1804
+ secure: "Boolean",
1805
+ community: "Boolean",
1806
+ priceSecure: "Float",
1807
+ priceCommunity: "Float",
1808
+ priceServerless: "Float",
1809
+ maxCountSecure: "Int",
1810
+ maxCountCommunity: "Int",
1811
+ availability: "String"
1812
+ },
1813
+ AdminRunPodOperation: {
1814
+ podId: "String",
1815
+ status: "String",
1816
+ message: "String"
1817
+ },
1596
1818
  OpenRouterModelProvider: {
1597
1819
  name: "String",
1598
1820
  label: "String"