@aexol/spectral 0.9.47 → 0.9.49
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/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +15 -1
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +66 -3
- package/dist/extensions/browser/browser-service.d.ts.map +1 -1
- package/dist/extensions/browser/browser-service.js +13 -3
- package/dist/relay/auto-optimizer.d.ts.map +1 -1
- package/dist/relay/auto-optimizer.js +168 -41
- package/dist/relay/client.d.ts.map +1 -1
- package/dist/relay/client.js +10 -0
- package/dist/relay/dispatcher.d.ts +1 -1
- package/dist/relay/dispatcher.d.ts.map +1 -1
- package/dist/relay/dispatcher.js +12 -0
- package/dist/sdk/coding-agent/core/agent-session.d.ts +6 -0
- package/dist/sdk/coding-agent/core/agent-session.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/agent-session.js +37 -0
- package/dist/sdk/coding-agent/core/settings-manager.d.ts +12 -0
- package/dist/sdk/coding-agent/core/settings-manager.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/settings-manager.js +33 -0
- package/dist/sdk/coding-agent/core/system-prompt-mutator.d.ts +17 -0
- package/dist/sdk/coding-agent/core/system-prompt-mutator.d.ts.map +1 -0
- package/dist/sdk/coding-agent/core/system-prompt-mutator.js +138 -0
- package/dist/server/agent-bridge.d.ts +1 -0
- package/dist/server/agent-bridge.d.ts.map +1 -1
- package/dist/server/agent-bridge.js +32 -10
- package/dist/server/handlers/prompt-mutation-settings.d.ts +34 -0
- package/dist/server/handlers/prompt-mutation-settings.d.ts.map +1 -0
- package/dist/server/handlers/prompt-mutation-settings.js +58 -0
- package/dist/server/shutdown.d.ts +2 -0
- package/dist/server/shutdown.d.ts.map +1 -1
- package/dist/server/shutdown.js +13 -0
- package/dist/server/wire.d.ts +1 -1
- package/dist/server/wire.d.ts.map +1 -1
- 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;
|
|
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"}
|
package/dist/agent/index.js
CHANGED
|
@@ -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:
|
|
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;
|
|
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"}
|
package/dist/commands/serve.js
CHANGED
|
@@ -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
|
|
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
|
|
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;
|
|
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
|
|
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
|
-
|
|
288
|
-
|
|
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
|
-
|
|
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
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
353
|
-
|
|
354
|
-
clearTimeout(timeout);
|
|
355
|
-
finalize({
|
|
480
|
+
watcherFired = true;
|
|
481
|
+
doCleanupAndSend({
|
|
356
482
|
type: "auto_optimize_error",
|
|
357
483
|
projectId,
|
|
358
|
-
message:
|
|
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;
|
|
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"}
|
package/dist/relay/client.js
CHANGED
|
@@ -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":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAIH,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,SAAS,EACT,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACf,MAAM,uBAAuB,CAAC;AAK/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/relay/dispatcher.ts"],"names":[],"mappings":"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"}
|
package/dist/relay/dispatcher.js
CHANGED
|
@@ -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.
|