@aexol/spectral 0.9.47 → 0.9.48

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.
Files changed (34) hide show
  1. package/dist/agent/index.d.ts.map +1 -1
  2. package/dist/agent/index.js +15 -1
  3. package/dist/commands/serve.d.ts.map +1 -1
  4. package/dist/commands/serve.js +66 -3
  5. package/dist/extensions/browser/browser-service.d.ts.map +1 -1
  6. package/dist/extensions/browser/browser-service.js +13 -3
  7. package/dist/relay/auto-optimizer.d.ts.map +1 -1
  8. package/dist/relay/auto-optimizer.js +168 -41
  9. package/dist/relay/client.d.ts.map +1 -1
  10. package/dist/relay/client.js +10 -0
  11. package/dist/relay/dispatcher.d.ts +1 -1
  12. package/dist/relay/dispatcher.d.ts.map +1 -1
  13. package/dist/relay/dispatcher.js +12 -0
  14. package/dist/sdk/coding-agent/core/agent-session.d.ts +6 -0
  15. package/dist/sdk/coding-agent/core/agent-session.d.ts.map +1 -1
  16. package/dist/sdk/coding-agent/core/agent-session.js +37 -0
  17. package/dist/sdk/coding-agent/core/settings-manager.d.ts +12 -0
  18. package/dist/sdk/coding-agent/core/settings-manager.d.ts.map +1 -1
  19. package/dist/sdk/coding-agent/core/settings-manager.js +33 -0
  20. package/dist/sdk/coding-agent/core/system-prompt-mutator.d.ts +17 -0
  21. package/dist/sdk/coding-agent/core/system-prompt-mutator.d.ts.map +1 -0
  22. package/dist/sdk/coding-agent/core/system-prompt-mutator.js +138 -0
  23. package/dist/server/agent-bridge.d.ts +1 -0
  24. package/dist/server/agent-bridge.d.ts.map +1 -1
  25. package/dist/server/agent-bridge.js +32 -10
  26. package/dist/server/handlers/prompt-mutation-settings.d.ts +34 -0
  27. package/dist/server/handlers/prompt-mutation-settings.d.ts.map +1 -0
  28. package/dist/server/handlers/prompt-mutation-settings.js +58 -0
  29. package/dist/server/shutdown.d.ts +2 -0
  30. package/dist/server/shutdown.d.ts.map +1 -1
  31. package/dist/server/shutdown.js +13 -0
  32. package/dist/server/wire.d.ts +1 -1
  33. package/dist/server/wire.d.ts.map +1 -1
  34. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAWH,OAAO,EACN,KAAK,YAAY,EAEjB,MAAM,8BAA8B,CAAC;AAuetC,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,GAAG,EAAE,YAAY,EAAE,IAAI,CAAC,EAAE;IAAE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CA+UvG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAWH,OAAO,EACN,KAAK,YAAY,EAEjB,MAAM,8BAA8B,CAAC;AAsftC,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,GAAG,EAAE,YAAY,EAAE,IAAI,CAAC,EAAE;IAAE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CA+UvG"}
@@ -26,6 +26,7 @@
26
26
  */
27
27
  import { agentLoop } from "../sdk/agent-core/index.js";
28
28
  import { StringEnum } from "../sdk/ai/index.js";
29
+ import { mutateSystemPrompt } from "../sdk/coding-agent/core/system-prompt-mutator.js";
29
30
  import { Type } from "typebox";
30
31
  import { discoverAgents } from "./agents.js";
31
32
  import { loadAgentSettings } from "../server/handlers/agent-settings.js";
@@ -196,6 +197,19 @@ async function runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, si
196
197
  const combinedPrompt = mainSystemPrompt
197
198
  ? `${mainSystemPrompt}\n\n---\n\nSubagent: ${agent.name}\n${agent.systemPrompt}`
198
199
  : agent.systemPrompt;
200
+ // Apply system prompt mutation if enabled in settings (opt-in)
201
+ let effectivePrompt = combinedPrompt;
202
+ if (ctx.settingsManager) {
203
+ const mutationResult = await mutateSystemPrompt({
204
+ systemPrompt: combinedPrompt,
205
+ modelRegistry: ctx.modelRegistry,
206
+ settingsManager: ctx.settingsManager,
207
+ cacheSuffix: `subagent:${agent.name}`,
208
+ });
209
+ if (mutationResult.mutated) {
210
+ effectivePrompt = mutationResult.prompt;
211
+ }
212
+ }
199
213
  // Resolve model — session model preferred, agent-configured as fallback
200
214
  const sessionModel = ctx.model && ctx.modelRegistry.hasConfiguredAuth(ctx.model) ? ctx.model : undefined;
201
215
  const model = sessionModel ?? resolveModelString(agent.model, ctx.modelRegistry);
@@ -262,7 +276,7 @@ async function runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, si
262
276
  toolExecution: "parallel",
263
277
  };
264
278
  const stream = agentLoop([{ role: "user", content: [{ type: "text", text: task }], timestamp: Date.now() }], {
265
- systemPrompt: combinedPrompt,
279
+ systemPrompt: effectivePrompt,
266
280
  messages: [],
267
281
  tools,
268
282
  }, config, signal);
@@ -1 +1 @@
1
- {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAwBH,OAAO,EAAE,WAAW,EAAmB,MAAM,oBAAoB,CAAC;AAUlE,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGnE,OAAO,EAAmB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAsBrE;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAazD;AAED,MAAM,WAAW,eAAe;IAC9B,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,eAAe,CA6B9D;AAED,MAAM,WAAW,eAAe;IAC9B,iEAAiE;IACjE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,uCAAuC;IACvC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,4CAA4C;IAC5C,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,qBAAqB,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;CAC/E;AAED,MAAM,WAAW,cAAc;IAC7B,qCAAqC;IACrC,KAAK,EAAE,YAAY,CAAC;IACpB,wDAAwD;IACxD,OAAO,EAAE,oBAAoB,CAAC;IAC9B,4CAA4C;IAC5C,KAAK,EAAE,WAAW,CAAC;IACnB,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,wBAAsB,QAAQ,CAAC,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,CAoZlF;AAwDD;;;GAGG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAa5E"}
1
+ {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAyBH,OAAO,EAAE,WAAW,EAAmB,MAAM,oBAAoB,CAAC;AAWlE,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGnE,OAAO,EAAmB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAsBrE;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAazD;AAED,MAAM,WAAW,eAAe;IAC9B,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,eAAe,CA6B9D;AAED,MAAM,WAAW,eAAe;IAC9B,iEAAiE;IACjE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,uCAAuC;IACvC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,4CAA4C;IAC5C,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,qBAAqB,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;CAC/E;AAED,MAAM,WAAW,cAAc;IAC7B,qCAAqC;IACrC,KAAK,EAAE,YAAY,CAAC;IACpB,wDAAwD;IACxD,OAAO,EAAE,oBAAoB,CAAC;IAC9B,4CAA4C;IAC5C,KAAK,EAAE,WAAW,CAAC;IACnB,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,wBAAsB,QAAQ,CAAC,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,CAqdlF;AAwDD;;;GAGG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAa5E"}
@@ -40,6 +40,7 @@ import { requireLogin } from "../preflight.js";
40
40
  import { RelayClient } from "../relay/client.js";
41
41
  import { detachAllSubscribers, handleAutoOptimizeFrame, handleAutoResearchFrame, handleCancelTurn, handleClientMessage, handleRestRequest, handleSubscribe, } from "../relay/dispatcher.js";
42
42
  import { ensureMachineRegistered } from "../relay/registration.js";
43
+ import { saveMachine } from "../relay/machine-store.js";
43
44
  import { SessionStreamManager } from "../server/session-stream.js";
44
45
  import { gracefulShutdown } from "../server/shutdown.js";
45
46
  import { getLiveMcpState } from "../mcp/state-getter.js";
@@ -294,6 +295,51 @@ export async function runServe(opts = {}) {
294
295
  });
295
296
  return;
296
297
  }
298
+ if (frame.kind === "machine_team_changed") {
299
+ const mtc = frame;
300
+ const existing = registration.record;
301
+ saveMachine({
302
+ machineId: existing.machineId,
303
+ machineName: existing.machineName,
304
+ machineJwt: mtc.machineJwt,
305
+ teamId: mtc.teamId,
306
+ ownerId: existing.ownerId,
307
+ visibility: existing.visibility,
308
+ registeredAt: Date.now(),
309
+ hostname: existing.hostname,
310
+ version: existing.version,
311
+ }).catch((err) => {
312
+ const msg = err instanceof Error ? err.message : String(err);
313
+ process.stderr.write(`[serve] Failed to save team change: ${msg}\n`);
314
+ });
315
+ // Update registration record so future re-registrations pick up the new team
316
+ registration = {
317
+ reused: false,
318
+ record: {
319
+ ...existing,
320
+ machineJwt: mtc.machineJwt,
321
+ teamId: mtc.teamId,
322
+ },
323
+ };
324
+ // Re-create relay with new JWT
325
+ r.dispose();
326
+ relay = new RelayClient({
327
+ relayUrl,
328
+ machineJwt: mtc.machineJwt,
329
+ backendUrl,
330
+ webSocketImpl: opts.webSocketImpl,
331
+ fetchImpl: opts.fetchImpl,
332
+ logger: silent
333
+ ? { log: () => { }, warn: () => { }, error: () => { } }
334
+ : console,
335
+ });
336
+ wireRelay(relay);
337
+ relay.connect();
338
+ if (!silent) {
339
+ process.stdout.write(`✓ Machine moved to team ${mtc.teamId}. Reconnecting with new credentials…\n`);
340
+ }
341
+ return;
342
+ }
297
343
  // Other frames (error, machine_disconnected addressed to us, etc.)
298
344
  // are ignored at this layer. Future batches may surface them in
299
345
  // structured logs.
@@ -313,6 +359,8 @@ export async function runServe(opts = {}) {
313
359
  });
314
360
  if (!silent) {
315
361
  r.on("close", ({ code, reason }) => {
362
+ if (reason === "team-changed")
363
+ return; // handled in frame handler
316
364
  process.stdout.write(`Relay closed (${code}${reason ? `: ${reason}` : ""}); will reconnect…\n`);
317
365
  });
318
366
  r.on("reconnect-scheduled", ({ delayMs, attempt }) => {
@@ -428,6 +476,15 @@ export async function runServe(opts = {}) {
428
476
  catch {
429
477
  // ignore — best-effort
430
478
  }
479
+ // Close browser instances (Playwright) so Chrome for Testing
480
+ // processes don't stay alive after the relay shuts down.
481
+ try {
482
+ const { BrowserService } = await import("../extensions/browser/browser-service.js");
483
+ await BrowserService.getInstance().close();
484
+ }
485
+ catch {
486
+ // browser extension may not be loaded or already closed
487
+ }
431
488
  if (!silent)
432
489
  process.stdout.write("Spectral relay stopped\n");
433
490
  };
@@ -469,9 +526,6 @@ export async function runServe(opts = {}) {
469
526
  void gracefulShutdown({
470
527
  inFlightCount: () => manager.activeTurnCount(),
471
528
  closeRelay: () => {
472
- // Mirror our own `close()`: dispose the relay (sends close 1000).
473
- // We don't await here because RelayClient.dispose is sync and
474
- // the shutdown helper expects a void|Promise return.
475
529
  relay.dispose();
476
530
  },
477
531
  disposeManager: () => {
@@ -480,6 +534,15 @@ export async function runServe(opts = {}) {
480
534
  closeStore: () => {
481
535
  store.close();
482
536
  },
537
+ closeBrowser: async () => {
538
+ try {
539
+ const { BrowserService } = await import("../extensions/browser/browser-service.js");
540
+ await BrowserService.getInstance().close();
541
+ }
542
+ catch {
543
+ // browser extension may not be loaded
544
+ }
545
+ },
483
546
  logger: silent
484
547
  ? { log: () => { }, warn: () => { }, error: () => { } }
485
548
  : console,
@@ -1 +1 @@
1
- {"version":3,"file":"browser-service.d.ts","sourceRoot":"","sources":["../../../src/extensions/browser/browser-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"browser-service.d.ts","sourceRoot":"","sources":["../../../src/extensions/browser/browser-service.ts"],"names":[],"mappings":"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"}
@@ -275,6 +275,7 @@ export class BrowserService {
275
275
  this.nextNetworkIndex = 0;
276
276
  }
277
277
  async close() {
278
+ // Close each page (ignore errors if already closed).
278
279
  for (const page of this.pages) {
279
280
  try {
280
281
  await page.close();
@@ -283,18 +284,27 @@ export class BrowserService {
283
284
  }
284
285
  this.pages = [];
285
286
  this.activePageIndex = 0;
287
+ // Close the browser context.
286
288
  if (this.context) {
287
289
  try {
288
- await this.context.close();
290
+ await Promise.race([
291
+ this.context.close(),
292
+ new Promise((_, reject) => setTimeout(() => reject(new Error("context.close timed out")), 5_000)),
293
+ ]);
289
294
  }
290
295
  catch { /* ignore */ }
291
296
  this.context = null;
292
297
  }
298
+ // Close the browser process (Playwright-managed Chromium).
299
+ // Use a timeout so a hung close doesn't block server shutdown.
293
300
  if (this.browser) {
294
301
  try {
295
- await this.browser.close();
302
+ await Promise.race([
303
+ this.browser.close(),
304
+ new Promise((_, reject) => setTimeout(() => reject(new Error("browser.close timed out")), 5_000)),
305
+ ]);
296
306
  }
297
- catch { /* ignore */ }
307
+ catch { /* ignore — process.exit will clean up orphans */ }
298
308
  this.browser = null;
299
309
  }
300
310
  this._recording = null;
@@ -1 +1 @@
1
- {"version":3,"file":"auto-optimizer.d.ts","sourceRoot":"","sources":["../../src/relay/auto-optimizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EACV,oBAAoB,EACpB,UAAU,EACX,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,YAAY,CAAC;IACpB,OAAO,EAAE,oBAAoB,CAAC;IAC9B,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACjC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;KAAE,CAAC;CAClD;AA6ND,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,iBAAiB,EACxB,IAAI,EAAE,gBAAgB,GACrB,IAAI,CAmLN"}
1
+ {"version":3,"file":"auto-optimizer.d.ts","sourceRoot":"","sources":["../../src/relay/auto-optimizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EACV,oBAAoB,EACpB,UAAU,EACX,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,YAAY,CAAC;IACpB,OAAO,EAAE,oBAAoB,CAAC;IAC9B,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACjC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;KAAE,CAAC;CAClD;AA+UD,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,iBAAiB,EACxB,IAAI,EAAE,gBAAgB,GACrB,IAAI,CAoON"}
@@ -20,6 +20,7 @@
20
20
  */
21
21
  import * as fs from "node:fs";
22
22
  import * as path from "node:path";
23
+ import { execSync } from "node:child_process";
23
24
  const activeAutoOptimizeSessions = new Set();
24
25
  const OPTIMIZER_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes
25
26
  // ---------------------------------------------------------------------------
@@ -189,6 +190,91 @@ function parseRecommendations(text) {
189
190
  return [];
190
191
  }
191
192
  }
193
+ function parseExecuteResults(text) {
194
+ const fenceMatch = text.match(/```(?:json)?\s*([\s\S]*?)```/);
195
+ const jsonText = fenceMatch ? fenceMatch[1].trim() : text.trim();
196
+ try {
197
+ const parsed = JSON.parse(jsonText);
198
+ if (parsed.results && Array.isArray(parsed.results)) {
199
+ return { results: parsed.results };
200
+ }
201
+ if (Array.isArray(parsed)) {
202
+ return { results: parsed };
203
+ }
204
+ return { results: [] };
205
+ }
206
+ catch {
207
+ return { results: [] };
208
+ }
209
+ }
210
+ async function runQualityGates(projectPath) {
211
+ const gates = [];
212
+ // Gate 1: TypeScript type-check
213
+ const hasTsConfig = fs.existsSync(path.join(projectPath, "tsconfig.json"));
214
+ if (hasTsConfig) {
215
+ try {
216
+ execSync("npx tsc --noEmit", {
217
+ cwd: projectPath,
218
+ timeout: 60_000,
219
+ stdio: "pipe",
220
+ });
221
+ gates.push({ gate: "tsc", passed: true, message: "TypeScript type-check passed." });
222
+ }
223
+ catch (err) {
224
+ const e = err;
225
+ const raw = e.stderr?.toString() || e.message || "Unknown error";
226
+ const short = raw.length > 500 ? raw.slice(0, 500) + "..." : raw;
227
+ gates.push({ gate: "tsc", passed: false, message: `TypeScript errors:\n${short}` });
228
+ }
229
+ }
230
+ // Gate 2: Next.js lint (if Next.js project)
231
+ const hasNextConfig = fs.existsSync(path.join(projectPath, "next.config.ts")) ||
232
+ fs.existsSync(path.join(projectPath, "next.config.js")) ||
233
+ fs.existsSync(path.join(projectPath, "next.config.mjs"));
234
+ if (hasNextConfig) {
235
+ try {
236
+ execSync("npx next lint --no-cache", {
237
+ cwd: projectPath,
238
+ timeout: 120_000,
239
+ stdio: "pipe",
240
+ });
241
+ gates.push({ gate: "next lint", passed: true, message: "Next.js lint passed." });
242
+ }
243
+ catch (err) {
244
+ const e = err;
245
+ const raw = e.stderr?.toString() || e.message || "Unknown error";
246
+ const short = raw.length > 500 ? raw.slice(0, 500) + "..." : raw;
247
+ gates.push({ gate: "next lint", passed: false, message: `Lint errors:\n${short}` });
248
+ }
249
+ }
250
+ // Gate 3: Deno lint (if Deno project and not already Next.js)
251
+ const hasDenoJson = fs.existsSync(path.join(projectPath, "deno.json"));
252
+ if (hasDenoJson && !hasNextConfig) {
253
+ try {
254
+ execSync("deno lint", {
255
+ cwd: projectPath,
256
+ timeout: 60_000,
257
+ stdio: "pipe",
258
+ });
259
+ gates.push({ gate: "deno lint", passed: true, message: "Deno lint passed." });
260
+ }
261
+ catch (err) {
262
+ const e = err;
263
+ const raw = e.stderr?.toString() || e.message || "Unknown error";
264
+ const short = raw.length > 500 ? raw.slice(0, 500) + "..." : raw;
265
+ gates.push({ gate: "deno lint", passed: false, message: `Lint errors:\n${short}` });
266
+ }
267
+ }
268
+ // If no gates ran, return informational note
269
+ if (gates.length === 0) {
270
+ gates.push({
271
+ gate: "info",
272
+ passed: true,
273
+ message: "No quality gates configured for this project type.",
274
+ });
275
+ }
276
+ return gates;
277
+ }
192
278
  // ---------------------------------------------------------------------------
193
279
  // Main handler
194
280
  // ---------------------------------------------------------------------------
@@ -265,11 +351,10 @@ export function handleAutoOptimize(input, deps) {
265
351
  }
266
352
  const storedModelId = store.getSessionModel(sessionId) ?? undefined;
267
353
  activeAutoOptimizeSessions.add(sessionId);
354
+ // Phase 3: buffer text_delta events to parse the agent's structured output
355
+ let textBuffer = "";
268
356
  let watcherFired = false;
269
- const finalize = (event) => {
270
- if (watcherFired)
271
- return;
272
- watcherFired = true;
357
+ const doCleanupAndSend = (event) => {
273
358
  activeAutoOptimizeSessions.delete(sessionId);
274
359
  try {
275
360
  manager.detach(sessionId, watcher);
@@ -279,40 +364,93 @@ export function handleAutoOptimize(input, deps) {
279
364
  }
280
365
  sendEvent(relay, sessionId, event);
281
366
  };
367
+ let retryCount = 0;
368
+ const MAX_PROMPT_RETRIES = 3;
369
+ const isCompactingError = (msg) => /compacting|compacted|wait.*moment|try again/i.test(msg);
370
+ const sendPrompt = () => {
371
+ manager
372
+ .prompt(sessionId, taskContent, storedModelId, undefined, undefined, {
373
+ skipPersistence: true,
374
+ })
375
+ .catch((err) => {
376
+ if (watcherFired)
377
+ return;
378
+ const msg = err instanceof Error ? err.message : String(err);
379
+ logger.error?.(`[auto-optimizer] manager.prompt failed for ${sessionId}:`, msg);
380
+ clearTimeout(timeout);
381
+ watcherFired = true;
382
+ doCleanupAndSend({
383
+ type: "auto_optimize_error",
384
+ projectId,
385
+ message: `Auto-optimizer prompt failed: ${msg}`,
386
+ });
387
+ });
388
+ };
282
389
  const watcher = {
283
390
  send(event) {
284
391
  if (watcherFired)
285
392
  return;
393
+ if (event.type === "text_delta") {
394
+ textBuffer += event.delta;
395
+ return;
396
+ }
286
397
  if (event.type === "agent_end") {
287
- // The agent finished — results are in the last assistant message.
288
- // For analyze phase: parse recommendations from the response.
289
- // For execute phase: we'd need to read the agent's output.
290
- // Since we use skipPersistence, messages aren't stored — we rely on
291
- // the agent sending structured output. In practice, the agent will
292
- // produce tool_call/tool_result events; the final result is in the
293
- // last text_delta before message_end + agent_end.
294
- //
295
- // For now: emit a completion event. Phase 3 will wire up proper
296
- // response parsing from the agent output stream.
398
+ watcherFired = true;
399
+ clearTimeout(timeout);
297
400
  if (action === "analyze") {
298
- finalize({
401
+ const recommendations = parseRecommendations(textBuffer);
402
+ logger.error?.(`[auto-optimizer] analyze complete: ${recommendations.length} recommendations from ${textBuffer.length} chars`);
403
+ doCleanupAndSend({
299
404
  type: "auto_optimize_analysis_complete",
300
405
  projectId,
301
- recommendations: [],
406
+ recommendations,
302
407
  });
303
408
  }
304
409
  else {
305
- finalize({
306
- type: "auto_optimize_execution_complete",
307
- projectId,
308
- results: [],
309
- gatesPassed: false,
310
- gateResults: [],
410
+ // execute — parse results then run quality gates (Phase 5)
411
+ const { results } = parseExecuteResults(textBuffer);
412
+ logger.error?.(`[auto-optimizer] execute complete: ${results.length} results, running quality gates...`);
413
+ runQualityGates(project.path)
414
+ .then((gateResults) => {
415
+ const gatesPassed = gateResults.every((g) => g.passed);
416
+ doCleanupAndSend({
417
+ type: "auto_optimize_execution_complete",
418
+ projectId,
419
+ results,
420
+ gatesPassed,
421
+ gateResults,
422
+ });
423
+ })
424
+ .catch((err) => {
425
+ const msg = err instanceof Error ? err.message : String(err);
426
+ logger.error?.("[auto-optimizer] quality gates crashed:", msg);
427
+ doCleanupAndSend({
428
+ type: "auto_optimize_error",
429
+ projectId,
430
+ message: `Quality gates failed: ${msg}`,
431
+ });
311
432
  });
312
433
  }
313
434
  }
314
435
  else if (event.type === "error") {
315
- finalize({
436
+ const errorMsg = typeof event.message === "string" ? event.message : "";
437
+ // If the session is compacting, retry prompt with backoff
438
+ // instead of immediately failing
439
+ if (isCompactingError(errorMsg) &&
440
+ retryCount < MAX_PROMPT_RETRIES) {
441
+ retryCount++;
442
+ const delay = 2000 * Math.pow(2, retryCount - 1); // 2s, 4s, 8s
443
+ logger.error?.(`[auto-optimizer] session compacting, retrying prompt ${retryCount}/${MAX_PROMPT_RETRIES} in ${delay}ms`);
444
+ setTimeout(() => {
445
+ if (watcherFired)
446
+ return;
447
+ sendPrompt();
448
+ }, delay);
449
+ return;
450
+ }
451
+ watcherFired = true;
452
+ clearTimeout(timeout);
453
+ doCleanupAndSend({
316
454
  type: "auto_optimize_error",
317
455
  projectId,
318
456
  message: event.message,
@@ -328,7 +466,8 @@ export function handleAutoOptimize(input, deps) {
328
466
  }
329
467
  catch (err) {
330
468
  const msg = err instanceof Error ? err.message : String(err);
331
- finalize({
469
+ watcherFired = true;
470
+ doCleanupAndSend({
332
471
  type: "auto_optimize_error",
333
472
  projectId,
334
473
  message: `Failed to attach auto-optimizer watcher: ${msg}`,
@@ -336,26 +475,14 @@ export function handleAutoOptimize(input, deps) {
336
475
  return;
337
476
  }
338
477
  const timeout = setTimeout(() => {
339
- finalize({
340
- type: "auto_optimize_error",
341
- projectId,
342
- message: "Auto-optimizer timed out after 10 minutes.",
343
- });
344
- }, OPTIMIZER_TIMEOUT_MS);
345
- manager
346
- .prompt(sessionId, taskContent, storedModelId, undefined, undefined, {
347
- skipPersistence: true,
348
- })
349
- .catch((err) => {
350
478
  if (watcherFired)
351
479
  return;
352
- const msg = err instanceof Error ? err.message : String(err);
353
- logger.error?.(`[auto-optimizer] manager.prompt failed for ${sessionId}:`, msg);
354
- clearTimeout(timeout);
355
- finalize({
480
+ watcherFired = true;
481
+ doCleanupAndSend({
356
482
  type: "auto_optimize_error",
357
483
  projectId,
358
- message: `Auto-optimizer prompt failed: ${msg}`,
484
+ message: "Auto-optimizer timed out after 10 minutes.",
359
485
  });
360
- });
486
+ }, OPTIMIZER_TIMEOUT_MS);
487
+ sendPrompt();
361
488
  }
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/relay/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,SAAS,MAAM,IAAI,CAAC;AAqB3B,MAAM,WAAW,kBAAkB;IACjC,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,SAAS,CAAC;IACjC;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB;;OAEG;IACH,MAAM,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IACjD;;;;OAIG;IACH,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC;CAChC;AAED,6EAA6E;AAC7E,MAAM,WAAW,UAAU;IACzB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,qBAAa,WAAY,SAAQ,YAAY;IAC3C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqB;IAChD,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAmB;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IACjE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0B;IAE/C,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,SAAS,CAAgB;IACjC,iFAAiF;IACjF,OAAO,CAAC,UAAU,CAAS;IAE3B,qEAAqE;IACrE,OAAO,CAAC,cAAc,CAAa;IACnC,OAAO,CAAC,aAAa,CAA+B;gBAExC,IAAI,EAAE,kBAAkB;IAWpC,kEAAkE;IAClE,OAAO,IAAI,IAAI;IAMf;;;;;;;OAOG;IACH,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO;IAqBzC;;;OAGG;IACH,OAAO,IAAI,IAAI;IA2Bf,OAAO,CAAC,UAAU;IAsIlB,OAAO,CAAC,aAAa;IAsBrB,OAAO,CAAC,YAAY;IAOpB;;;;;OAKG;YACW,WAAW;YA8BX,iBAAiB;CAmDhC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/relay/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,SAAS,MAAM,IAAI,CAAC;AAqB3B,MAAM,WAAW,kBAAkB;IACjC,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,SAAS,CAAC;IACjC;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB;;OAEG;IACH,MAAM,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IACjD;;;;OAIG;IACH,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC;CAChC;AAED,6EAA6E;AAC7E,MAAM,WAAW,UAAU;IACzB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,qBAAa,WAAY,SAAQ,YAAY;IAC3C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqB;IAChD,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAmB;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IACjE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0B;IAE/C,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,SAAS,CAAgB;IACjC,iFAAiF;IACjF,OAAO,CAAC,UAAU,CAAS;IAE3B,qEAAqE;IACrE,OAAO,CAAC,cAAc,CAAa;IACnC,OAAO,CAAC,aAAa,CAA+B;gBAExC,IAAI,EAAE,kBAAkB;IAWpC,kEAAkE;IAClE,OAAO,IAAI,IAAI;IAMf;;;;;;;OAOG;IACH,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO;IAqBzC;;;OAGG;IACH,OAAO,IAAI,IAAI;IA2Bf,OAAO,CAAC,UAAU;IAgJlB,OAAO,CAAC,aAAa;IAsBrB,OAAO,CAAC,YAAY;IAOpB;;;;;OAKG;YACW,WAAW;YA8BX,iBAAiB;CAmDhC"}
@@ -258,6 +258,16 @@ export class RelayClient extends EventEmitter {
258
258
  this.exit(1);
259
259
  return;
260
260
  }
261
+ if (reasonStr === "team-changed") {
262
+ // Team was changed via Studio — the machine_team_changed frame handler
263
+ // in serve.ts already saved the new JWT. Just reconnect normally.
264
+ if (this.authFailed) {
265
+ this.emit("auth-failed");
266
+ return;
267
+ }
268
+ this.scheduleReconnect();
269
+ return;
270
+ }
261
271
  // Auth failure at the transport layer (HTTP 401/403 on WS upgrade).
262
272
  // The machine JWT is invalid (expired, malformed, or revoked by key
263
273
  // rotation) but the backend didn't send a structured close reason.
@@ -48,7 +48,7 @@ import type { RelayClient } from "./client.js";
48
48
  * `id` is populated when the route had an `:id` placeholder.
49
49
  */
50
50
  interface RouteMatch {
51
- route: "list_projects" | "create_project" | "update_project" | "delete_project" | "bind_studio" | "unbind_studio" | "get_project_observations" | "list_project_sessions" | "cleanup_project_sessions" | "create_session" | "get_session" | "get_session_messages" | "update_session" | "delete_session" | "get_session_memory" | "get_session_memory_details" | "compact_session" | "remember_and_delete_session" | "fork_session" | "list_path_autocomplete" | "pick_directory" | "search_project_files" | "enqueue_prompt" | "get_prompt_queue" | "remove_prompt" | "clear_prompt_queue" | "list_mcp_status" | "reload_mcp_config" | "refresh_native_extensions" | "get_settings" | "put_settings" | "get_agent_settings" | "put_agent_settings" | "list_agents";
51
+ route: "list_projects" | "create_project" | "update_project" | "delete_project" | "bind_studio" | "unbind_studio" | "get_project_observations" | "list_project_sessions" | "cleanup_project_sessions" | "create_session" | "get_session" | "get_session_messages" | "update_session" | "delete_session" | "get_session_memory" | "get_session_memory_details" | "compact_session" | "remember_and_delete_session" | "fork_session" | "list_path_autocomplete" | "pick_directory" | "search_project_files" | "enqueue_prompt" | "get_prompt_queue" | "remove_prompt" | "clear_prompt_queue" | "list_mcp_status" | "reload_mcp_config" | "refresh_native_extensions" | "get_settings" | "put_settings" | "get_agent_settings" | "put_agent_settings" | "get_prompt_mutation_settings" | "put_prompt_mutation_settings" | "list_agents";
52
52
  id?: string;
53
53
  /** Parsed query params, if the path carried a `?...` suffix. */
54
54
  query?: URLSearchParams;
@@ -1 +1 @@
1
- {"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/relay/dispatcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/relay/dispatcher.ts"],"names":[],"mappings":"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"}
@@ -50,6 +50,7 @@ import { handleCompactSession, handleCreateSession, handleDeleteSession, handleF
50
50
  import { handleClearPromptQueue, handleEnqueuePrompt, handleGetPromptQueue, handleRemovePrompt, } from "../server/handlers/queue.js";
51
51
  import { handleGetAgentSettings, handleListAgents, handlePutAgentSettings, } from "../server/handlers/agent-settings.js";
52
52
  import { handleGetSettings, handlePutSettings, } from "../server/handlers/settings.js";
53
+ import { handleGetPromptMutationSettings, handlePutPromptMutationSettings, } from "../server/handlers/prompt-mutation-settings.js";
53
54
  import { shutdownState } from "../server/shutdown.js";
54
55
  import { handleAutoResearch } from "./auto-research.js";
55
56
  import { handleAutoOptimize } from "./auto-optimizer.js";
@@ -97,6 +98,13 @@ export function matchRoute(method, path) {
97
98
  return { route: "put_agent_settings" };
98
99
  return null;
99
100
  }
101
+ if (cleanPath === "/api/prompt-mutation-settings") {
102
+ if (method === "GET")
103
+ return { route: "get_prompt_mutation_settings" };
104
+ if (method === "PUT")
105
+ return { route: "put_prompt_mutation_settings" };
106
+ return null;
107
+ }
100
108
  // /api/agents
101
109
  if (cleanPath === "/api/agents") {
102
110
  if (method === "GET")
@@ -555,6 +563,10 @@ async function dispatchRoute(match, body, deps) {
555
563
  return handleGetAgentSettings(deps.cwd ?? homedir(), deps.agentDir);
556
564
  case "put_agent_settings":
557
565
  return handlePutAgentSettings(deps.cwd ?? homedir(), asObject(body), deps.agentDir);
566
+ case "get_prompt_mutation_settings":
567
+ return handleGetPromptMutationSettings(deps.cwd ?? homedir(), deps.agentDir);
568
+ case "put_prompt_mutation_settings":
569
+ return handlePutPromptMutationSettings(deps.cwd ?? homedir(), asObject(body), deps.agentDir);
558
570
  case "list_agents": {
559
571
  const agentCwd = match.query?.get("cwd") || deps.cwd || homedir();
560
572
  return handleListAgents(agentCwd, deps.agentDir);
@@ -78,6 +78,10 @@ export type AgentSessionEvent = Exclude<AgentEvent, {
78
78
  type: "compaction_delta";
79
79
  delta: string;
80
80
  content: string;
81
+ } | {
82
+ type: "prompt_mutation_status";
83
+ phase: "mutating" | "done";
84
+ message?: string;
81
85
  };
82
86
  /** Listener function for agent session events */
83
87
  export type AgentSessionEventListener = (event: AgentSessionEvent) => void;
@@ -198,6 +202,7 @@ export declare class AgentSession {
198
202
  private _extensionCommandContextActions?;
199
203
  private _extensionAbortHandler?;
200
204
  private _extensionShutdownHandler?;
205
+ private _promptMutationApplied;
201
206
  private _extensionErrorListener?;
202
207
  private _extensionErrorUnsubscriber?;
203
208
  private _modelRegistry;
@@ -316,6 +321,7 @@ export declare class AgentSession {
316
321
  private _normalizePromptGuidelines;
317
322
  private _rebuildSystemPrompt;
318
323
  private _runAgentPrompt;
324
+ private _applyPromptMutationIfNeeded;
319
325
  private _handlePostAgentRun;
320
326
  /**
321
327
  * Send a prompt to the agent.