@wrongstack/core 0.141.0 → 0.155.0
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-bridge-r9y6gdn4.d.ts → agent-bridge-BbZU5TPN.d.ts} +1 -1
- package/dist/{agent-subagent-runner-1GeQE_L0.d.ts → agent-subagent-runner-Bsueu0J2.d.ts} +2 -2
- package/dist/{brain-Cp_3GIS2.d.ts → brain-CS_B0vIE.d.ts} +2 -0
- package/dist/coordination/index.d.ts +7 -7
- package/dist/coordination/index.js +147 -10
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +13 -13
- package/dist/defaults/index.js +360 -78
- package/dist/defaults/index.js.map +1 -1
- package/dist/execution/index.d.ts +6 -6
- package/dist/execution/index.js +277 -16
- package/dist/execution/index.js.map +1 -1
- package/dist/extension/index.d.ts +2 -2
- package/dist/{goal-preamble-iuIUTQwk.d.ts → goal-preamble-CbV8pXLD.d.ts} +11 -3
- package/dist/{index-CPweVoFM.d.ts → index-B5wz-GXm.d.ts} +1 -1
- package/dist/{index-BZdezm3g.d.ts → index-CI1hRfPt.d.ts} +2 -2
- package/dist/index.d.ts +23 -23
- package/dist/index.js +396 -86
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +3 -3
- package/dist/infrastructure/index.js +11 -2
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +3 -3
- package/dist/kernel/index.js.map +1 -1
- package/dist/{mcp-servers-Bl5LTvQg.d.ts → mcp-servers-CPERR2De.d.ts} +8 -1
- package/dist/{multi-agent-coordinator-QWEzJDlm.d.ts → multi-agent-coordinator-BSKSFNhv.d.ts} +1 -1
- package/dist/{null-fleet-bus-BUyfqh23.d.ts → null-fleet-bus-CGOez8Le.d.ts} +4 -4
- package/dist/observability/index.d.ts +1 -1
- package/dist/{parallel-eternal-engine-Dj2SYzha.d.ts → parallel-eternal-engine-CYoTKjsz.d.ts} +13 -4
- package/dist/{path-resolver-DRjQBkoO.d.ts → path-resolver-DuhlmPil.d.ts} +1 -1
- package/dist/{plan-templates-CkKNPU3I.d.ts → plan-templates-DbH7lg-t.d.ts} +2 -2
- package/dist/{provider-runner-BNpuIyOL.d.ts → provider-runner-Cocq0O9E.d.ts} +1 -1
- package/dist/sdd/index.d.ts +3 -3
- package/dist/sdd/index.js +143 -6
- package/dist/sdd/index.js.map +1 -1
- package/dist/{secret-vault-DoISxaKO.d.ts → secret-vault-BJDY28ev.d.ts} +7 -1
- package/dist/{secret-vault-BTcC_T5v.d.ts → secret-vault-w8MbUe2Q.d.ts} +1 -1
- package/dist/security/index.d.ts +2 -2
- package/dist/security/index.js +60 -23
- package/dist/security/index.js.map +1 -1
- package/dist/storage/index.d.ts +5 -5
- package/dist/storage/index.js +78 -44
- package/dist/storage/index.js.map +1 -1
- package/dist/types/index.d.ts +11 -11
- package/dist/types/index.js +186 -26
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +65 -1
- package/dist/utils/index.js +64 -5
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/tech-stack/SKILL.md +253 -97
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
export { C as CompactorOptions, D as DefaultErrorHandler, a as DefaultRetryPolicy, E as EternalAutonomyEngine, b as EternalAutonomyOptions, c as EternalEngineState, H as HybridCompactor, I as IterationStage, P as ParallelEngineState, d as ParallelEternalEngine, e as ParallelEternalOptions, f as ParallelIterationStage, T as ToolExecutor } from '../parallel-eternal-engine-
|
|
2
|
-
export { A as AutoCompactionMiddleware, a as AutonomousRunner, b as AutonomousRunnerOptions, c as AutonomyPromptContributorOptions, C as CompactorStrategy, D as DefaultSkillLoader, d as DoneCheckResult, e as DoneConditionChecker, I as IntelligentCompactor, f as IntelligentCompactorOptions, S as SelectiveCompactor, g as SelectiveCompactorOptions, h as SkillLoaderOptions, i as StrategyCompactorOptions, j as buildGoalPreamble, k as createStrategyCompactor, m as makeAutonomyPromptContributor } from '../goal-preamble-
|
|
1
|
+
export { C as CompactorOptions, D as DefaultErrorHandler, a as DefaultRetryPolicy, E as EternalAutonomyEngine, b as EternalAutonomyOptions, c as EternalEngineState, H as HybridCompactor, I as IterationStage, P as ParallelEngineState, d as ParallelEternalEngine, e as ParallelEternalOptions, f as ParallelIterationStage, T as ToolExecutor } from '../parallel-eternal-engine-CYoTKjsz.js';
|
|
2
|
+
export { A as AutoCompactionMiddleware, a as AutonomousRunner, b as AutonomousRunnerOptions, c as AutonomyPromptContributorOptions, C as CompactorStrategy, D as DefaultSkillLoader, d as DoneCheckResult, e as DoneConditionChecker, I as IntelligentCompactor, f as IntelligentCompactorOptions, S as SelectiveCompactor, g as SelectiveCompactorOptions, h as SkillLoaderOptions, i as StrategyCompactorOptions, j as buildGoalPreamble, k as createStrategyCompactor, m as makeAutonomyPromptContributor } from '../goal-preamble-CbV8pXLD.js';
|
|
3
3
|
import { P as Provider } from '../context-C7G_MtLV.js';
|
|
4
|
-
import { B as BrainDecision, a as BrainDecisionRequest, b as BrainArbiter } from '../brain-
|
|
4
|
+
import { B as BrainDecision, a as BrainDecisionRequest, b as BrainArbiter } from '../brain-CS_B0vIE.js';
|
|
5
5
|
import '../retry-policy-rutAfVeR.js';
|
|
6
6
|
import '../compactor-BueGt7LG.js';
|
|
7
7
|
import '../config-BaVThgnT.js';
|
|
8
|
-
import '../index-
|
|
8
|
+
import '../index-B5wz-GXm.js';
|
|
9
9
|
import '../logger-B63L5bTg.js';
|
|
10
10
|
import '../pipeline-BG7UgbDc.js';
|
|
11
11
|
import '../observability-D-HZN_mF.js';
|
|
12
12
|
import '../permission-B7nKnEvQ.js';
|
|
13
|
-
import '../agent-subagent-runner-
|
|
13
|
+
import '../agent-subagent-runner-Bsueu0J2.js';
|
|
14
14
|
import '../goal-store-CV9Yz2X_.js';
|
|
15
|
-
import '../multi-agent-coordinator-
|
|
15
|
+
import '../multi-agent-coordinator-BSKSFNhv.js';
|
|
16
16
|
import 'node:events';
|
|
17
17
|
import '../skill-Bj6Ezqb8.js';
|
|
18
18
|
import '../wstack-paths-DD50Omgn.js';
|
package/dist/execution/index.js
CHANGED
|
@@ -255,8 +255,8 @@ function findPreserveStart(messages, preserveK) {
|
|
|
255
255
|
for (let i = preserveStart; i < messages.length; i++) {
|
|
256
256
|
const m = messages[i];
|
|
257
257
|
if (!m || typeof m.content === "string" || !Array.isArray(m.content)) continue;
|
|
258
|
-
const
|
|
259
|
-
if (
|
|
258
|
+
const hasToolUse3 = m.content.some((b) => b.type === "tool_use");
|
|
259
|
+
if (hasToolUse3 && i + 1 < messages.length) {
|
|
260
260
|
const next = messages[i + 1];
|
|
261
261
|
if (next && next.role === "user" && typeof next.content !== "string" && Array.isArray(next.content) && next.content.some((b) => b.type === "tool_result")) {
|
|
262
262
|
preserveStart = i + 1;
|
|
@@ -320,6 +320,127 @@ function buildLosslessDigest(messages) {
|
|
|
320
320
|
}
|
|
321
321
|
return lines.join("\n");
|
|
322
322
|
}
|
|
323
|
+
function extractText(m) {
|
|
324
|
+
if (typeof m.content === "string") return m.content;
|
|
325
|
+
return m.content.filter(isTextBlock).map((b) => b.text).join(" ");
|
|
326
|
+
}
|
|
327
|
+
function hasToolUse2(m) {
|
|
328
|
+
if (typeof m.content === "string") return false;
|
|
329
|
+
return m.content.some((b) => b.type === "tool_use");
|
|
330
|
+
}
|
|
331
|
+
function hasLargeToolResult(m, threshold = 3e3) {
|
|
332
|
+
if (typeof m.content === "string") return false;
|
|
333
|
+
return m.content.some(
|
|
334
|
+
(b) => b.type === "tool_result" && b.content && (typeof b.content === "string" ? b.content.length : JSON.stringify(b.content).length) > threshold
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
function scoreMessage(m, context) {
|
|
338
|
+
const text = extractText(m).toLowerCase();
|
|
339
|
+
if (text.trim().length === 0 && (hasToolUse2(m) || typeof m.content !== "string")) {
|
|
340
|
+
const hasResult = typeof m.content !== "string" && m.content.some((b) => b.type === "tool_result");
|
|
341
|
+
if (hasToolUse2(m) || hasResult) return 0;
|
|
342
|
+
}
|
|
343
|
+
if (context?.failureCounts && m.role === "user" && hasToolUse2(m) === false) {
|
|
344
|
+
const isFailure = /error|fail|exception|timeout|enonet|eacces|eperm|enoent|abort/i.test(text);
|
|
345
|
+
if (isFailure) {
|
|
346
|
+
const errKey = /(error|fail|exception|timeout|enonet|eacces|eperm|enoent|abort)/i.exec(text)?.[0]?.toLowerCase() ?? "error";
|
|
347
|
+
const count = (context.failureCounts.get(errKey) ?? 0) + 1;
|
|
348
|
+
context.failureCounts.set(errKey, count);
|
|
349
|
+
if (count >= 5) return 0;
|
|
350
|
+
if (count >= 3) return 1;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
if (m.role === "user") {
|
|
354
|
+
if (/\b(wrong|no\b|stop\b|don'?t\b|actually|fix that|undo|revert|forget|ignore|skip)\b/i.test(
|
|
355
|
+
text
|
|
356
|
+
)) {
|
|
357
|
+
return 5;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (/\b(error|exception|fatal|critical|crash|panic|abort|segfault|core dump|undefined is not|null pointer|typeerror|referenceerror|syntaxerror)\b/i.test(
|
|
361
|
+
text
|
|
362
|
+
)) {
|
|
363
|
+
return 5;
|
|
364
|
+
}
|
|
365
|
+
if (/\b(security|vulnerability|injection|xss|csrf|secret|apikey|api.key|hardcoded|leak|exploit|cve)\b/i.test(
|
|
366
|
+
text
|
|
367
|
+
)) {
|
|
368
|
+
return 5;
|
|
369
|
+
}
|
|
370
|
+
if (m.role === "assistant" && /\b(architecture|design|approach|strategy|pattern|refactor|migrate|restructure|decision|trade.?off)\b/i.test(
|
|
371
|
+
text
|
|
372
|
+
)) {
|
|
373
|
+
return 5;
|
|
374
|
+
}
|
|
375
|
+
if (hasLargeToolResult(m)) return 1;
|
|
376
|
+
if (m.role === "user" && !hasToolUse2(m) && /\b(files_with_matches|count|found \d+ match|directory tree|\.\.\. and \d+ more)\b/i.test(text)) {
|
|
377
|
+
return 1;
|
|
378
|
+
}
|
|
379
|
+
return 3;
|
|
380
|
+
}
|
|
381
|
+
function buildSmartDigest(messages) {
|
|
382
|
+
const lines = [];
|
|
383
|
+
const failureCounts = /* @__PURE__ */ new Map();
|
|
384
|
+
let noiseCount = 0;
|
|
385
|
+
for (const m of messages) {
|
|
386
|
+
const score = scoreMessage(m, { failureCounts });
|
|
387
|
+
const text = extractText(m);
|
|
388
|
+
const toolCount = countToolBlocks(m);
|
|
389
|
+
if (score === 0) {
|
|
390
|
+
noiseCount++;
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
const marker = toolCount > 0 ? ` [${toolCount} tool call(s)]` : "";
|
|
394
|
+
let display;
|
|
395
|
+
switch (score) {
|
|
396
|
+
case 5:
|
|
397
|
+
display = text.trim();
|
|
398
|
+
break;
|
|
399
|
+
case 3:
|
|
400
|
+
display = firstSentence(text);
|
|
401
|
+
break;
|
|
402
|
+
case 1:
|
|
403
|
+
display = oneLineSummary(m, text);
|
|
404
|
+
break;
|
|
405
|
+
default:
|
|
406
|
+
display = firstSentence(text);
|
|
407
|
+
}
|
|
408
|
+
if (display.length === 0 && toolCount === 0) continue;
|
|
409
|
+
lines.push(`[${m.role}]: ${display}${marker}`);
|
|
410
|
+
}
|
|
411
|
+
if (noiseCount > 0) {
|
|
412
|
+
lines.push(`[system]: ${noiseCount} low-importance turn(s) collapsed (repeated failures / pure tool I/O)`);
|
|
413
|
+
}
|
|
414
|
+
return lines.join("\n");
|
|
415
|
+
}
|
|
416
|
+
function countToolBlocks(m) {
|
|
417
|
+
if (typeof m.content === "string") return 0;
|
|
418
|
+
return m.content.filter(
|
|
419
|
+
(b) => b.type === "tool_use" || b.type === "tool_result"
|
|
420
|
+
).length;
|
|
421
|
+
}
|
|
422
|
+
function firstSentence(text) {
|
|
423
|
+
const trimmed = text.trim();
|
|
424
|
+
if (trimmed.length === 0) return "";
|
|
425
|
+
const dot = trimmed.indexOf(". ");
|
|
426
|
+
if (dot === -1) return trimmed.length > 150 ? `${trimmed.slice(0, 147)}\u2026` : trimmed;
|
|
427
|
+
const sentence = trimmed.slice(0, dot + 1);
|
|
428
|
+
return sentence.length > 150 ? `${sentence.slice(0, 147)}\u2026` : sentence;
|
|
429
|
+
}
|
|
430
|
+
function oneLineSummary(m, text) {
|
|
431
|
+
const trimmed = text.trim();
|
|
432
|
+
if (trimmed.length === 0) {
|
|
433
|
+
if (typeof m.content !== "string") {
|
|
434
|
+
const results = m.content.filter((b) => b.type === "tool_result");
|
|
435
|
+
if (results.length > 0) {
|
|
436
|
+
return `[${results.length} tool result(s) \u2014 see session log]`;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
return "[no text content]";
|
|
440
|
+
}
|
|
441
|
+
const firstLine = trimmed.split("\n")[0] ?? "";
|
|
442
|
+
return firstLine.length > 100 ? `${firstLine.slice(0, 97)}\u2026` : firstLine;
|
|
443
|
+
}
|
|
323
444
|
function findSafeBoundary(messages, from, to) {
|
|
324
445
|
for (let i = to; i >= from; i--) {
|
|
325
446
|
const m = messages[i];
|
|
@@ -335,8 +456,8 @@ function findExchangeStart(messages, userIndex) {
|
|
|
335
456
|
const m = messages[i];
|
|
336
457
|
if (!m) continue;
|
|
337
458
|
if (m.role === "assistant") {
|
|
338
|
-
const
|
|
339
|
-
if (!
|
|
459
|
+
const hasToolUse3 = Array.isArray(m.content) ? m.content.some((b) => b.type === "tool_use") : false;
|
|
460
|
+
if (!hasToolUse3) return i + 1;
|
|
340
461
|
} else if (m.role === "user") {
|
|
341
462
|
return i;
|
|
342
463
|
}
|
|
@@ -348,9 +469,11 @@ function findExchangeStart(messages, userIndex) {
|
|
|
348
469
|
var HybridCompactor = class {
|
|
349
470
|
preserveK;
|
|
350
471
|
eliseThreshold;
|
|
472
|
+
smart;
|
|
351
473
|
constructor(opts = {}) {
|
|
352
474
|
this.preserveK = opts.preserveK ?? 5;
|
|
353
475
|
this.eliseThreshold = opts.eliseThreshold ?? 2e3;
|
|
476
|
+
this.smart = opts.smart ?? false;
|
|
354
477
|
}
|
|
355
478
|
async compact(ctx, opts = {}) {
|
|
356
479
|
const beforeTokens = estimateMessages(ctx.messages);
|
|
@@ -422,7 +545,7 @@ var HybridCompactor = class {
|
|
|
422
545
|
if (boundary <= 0) return { saved: 0 };
|
|
423
546
|
const removed = messages.slice(0, boundary);
|
|
424
547
|
const removedTokens = estimateMessages(removed);
|
|
425
|
-
const digest = buildLosslessDigest(removed) || `${removed.length} earlier turns (no textual content; tool I/O omitted \u2014 see session log)`;
|
|
548
|
+
const digest = this.smart ? buildSmartDigest(removed) || `${removed.length} earlier turns (no textual content; tool I/O omitted \u2014 see session log)` : buildLosslessDigest(removed) || `${removed.length} earlier turns (no textual content; tool I/O omitted \u2014 see session log)`;
|
|
426
549
|
const summaryMsg = {
|
|
427
550
|
role: "system",
|
|
428
551
|
content: `[prior_turns_digest: ${digest}]`
|
|
@@ -946,7 +1069,8 @@ function createStrategyCompactor(opts = {}) {
|
|
|
946
1069
|
}
|
|
947
1070
|
return new HybridCompactor({
|
|
948
1071
|
preserveK: opts.preserveK,
|
|
949
|
-
eliseThreshold: opts.eliseThreshold
|
|
1072
|
+
eliseThreshold: opts.eliseThreshold,
|
|
1073
|
+
smart: opts.smart
|
|
950
1074
|
});
|
|
951
1075
|
}
|
|
952
1076
|
var ProviderBackedCompactor = class {
|
|
@@ -1807,7 +1931,7 @@ ${excerpt}`;
|
|
|
1807
1931
|
subjectFor(toolName, input, subjectKey) {
|
|
1808
1932
|
if (!input || typeof input !== "object") return void 0;
|
|
1809
1933
|
const obj = input;
|
|
1810
|
-
const globChars = /[
|
|
1934
|
+
const globChars = /[*?[\]]/g;
|
|
1811
1935
|
const escapeGlob = (s) => s.replace(globChars, (c) => `\\${c}`);
|
|
1812
1936
|
const normalizePath = (s) => escapeGlob(s.replace(/\\/g, "/"));
|
|
1813
1937
|
if (subjectKey) {
|
|
@@ -2237,7 +2361,7 @@ function appendJournal(goal, entry) {
|
|
|
2237
2361
|
};
|
|
2238
2362
|
}
|
|
2239
2363
|
function parseProgressFromText(text) {
|
|
2240
|
-
const re = /\[progress:\s*(\d{1,3})%\]\s*(?:[
|
|
2364
|
+
const re = /\[progress:\s*(\d{1,3})%\]\s*(?:[—-]\s*(.+))?/i;
|
|
2241
2365
|
const m = text.match(re);
|
|
2242
2366
|
if (!m) return null;
|
|
2243
2367
|
const progress = Math.min(100, Math.max(0, Number.parseInt(m[1] ?? "0", 10)));
|
|
@@ -2415,7 +2539,7 @@ ${request.context}` : "",
|
|
|
2415
2539
|
},
|
|
2416
2540
|
{ signal }
|
|
2417
2541
|
);
|
|
2418
|
-
const text =
|
|
2542
|
+
const text = extractText2(response).trim();
|
|
2419
2543
|
if (request.options?.length) {
|
|
2420
2544
|
for (const opt of request.options) {
|
|
2421
2545
|
if (text.toLowerCase().includes(opt.id.toLowerCase())) {
|
|
@@ -2443,7 +2567,7 @@ ${request.context}` : "",
|
|
|
2443
2567
|
return { type: "deny", reason: "Autonomy Brain LLM unavailable for decision." };
|
|
2444
2568
|
}
|
|
2445
2569
|
}
|
|
2446
|
-
function
|
|
2570
|
+
function extractText2(result) {
|
|
2447
2571
|
if (!result || typeof result !== "object") return "";
|
|
2448
2572
|
const r = result;
|
|
2449
2573
|
if (Array.isArray(r.content)) {
|
|
@@ -3455,6 +3579,7 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
3455
3579
|
function makeAgentSubagentRunner(opts) {
|
|
3456
3580
|
const format = opts.formatTaskInput ?? defaultFormatTaskInput;
|
|
3457
3581
|
return async (task, ctx) => {
|
|
3582
|
+
const taskStartedAt = Date.now();
|
|
3458
3583
|
const factoryResult = await opts.factory(ctx.config);
|
|
3459
3584
|
const { agent, events } = factoryResult;
|
|
3460
3585
|
const detachFleet = opts.fleetBus?.attach(ctx.subagentId, events, task.id);
|
|
@@ -3551,7 +3676,7 @@ function makeAgentSubagentRunner(opts) {
|
|
|
3551
3676
|
}),
|
|
3552
3677
|
events.on("provider.text_delta", (e) => {
|
|
3553
3678
|
ctx.budget.markActivity();
|
|
3554
|
-
streamingTextAcc = (streamingTextAcc + e.text).slice(-
|
|
3679
|
+
streamingTextAcc = (streamingTextAcc + e.text).slice(-2e3);
|
|
3555
3680
|
})
|
|
3556
3681
|
);
|
|
3557
3682
|
const onParentAbort = () => aborter.abort();
|
|
@@ -3559,6 +3684,15 @@ function makeAgentSubagentRunner(opts) {
|
|
|
3559
3684
|
let result;
|
|
3560
3685
|
try {
|
|
3561
3686
|
result = await agent.run(format(task, ctx.config), { signal: aborter.signal });
|
|
3687
|
+
events.emit("subagent.task_completed", {
|
|
3688
|
+
subagentId: ctx.subagentId,
|
|
3689
|
+
taskId: task.id,
|
|
3690
|
+
status: result.status === "done" ? "success" : "failed",
|
|
3691
|
+
iterations: result.iterations,
|
|
3692
|
+
toolCalls: ctx.budget.usage().toolCalls,
|
|
3693
|
+
durationMs: Date.now() - taskStartedAt,
|
|
3694
|
+
finalText: result.finalText?.trim() || void 0
|
|
3695
|
+
});
|
|
3562
3696
|
} finally {
|
|
3563
3697
|
detachFleet?.();
|
|
3564
3698
|
ctx.signal.removeEventListener("abort", onParentAbort);
|
|
@@ -4468,15 +4602,44 @@ Working rules:
|
|
|
4468
4602
|
id: "e2e",
|
|
4469
4603
|
name: "E2E",
|
|
4470
4604
|
role: "e2e",
|
|
4471
|
-
tools: [
|
|
4605
|
+
tools: [
|
|
4606
|
+
...TOOLS.build,
|
|
4607
|
+
"fetch",
|
|
4608
|
+
"playwright_navigate",
|
|
4609
|
+
"playwright_screenshot",
|
|
4610
|
+
"playwright_click",
|
|
4611
|
+
"playwright_type",
|
|
4612
|
+
"playwright_evaluate",
|
|
4613
|
+
"playwright_select_option",
|
|
4614
|
+
"playwright_hover",
|
|
4615
|
+
"playwright_fill_form",
|
|
4616
|
+
"playwright_wait_for",
|
|
4617
|
+
"playwright_press_key",
|
|
4618
|
+
"playwright_drag"
|
|
4619
|
+
],
|
|
4472
4620
|
prompt: `You are the E2E agent. Your job is end-to-end testing: drive the whole
|
|
4473
4621
|
system the way a user would and verify the full flow works across boundaries.
|
|
4474
4622
|
|
|
4475
4623
|
Scope:
|
|
4476
4624
|
- Author end-to-end scenarios that exercise real user journeys
|
|
4477
4625
|
- Drive UI/CLI/API across process and network boundaries
|
|
4626
|
+
- Use Playwright browser tools (navigate, click, type, screenshot, evaluate)
|
|
4627
|
+
to automate web UI flows \u2014 open pages, interact with forms, capture evidence
|
|
4478
4628
|
- Set up and tear down realistic test state
|
|
4479
|
-
- Capture failures with enough detail to reproduce (screenshots, logs)
|
|
4629
|
+
- Capture failures with enough detail to reproduce (screenshots, logs, page HTML)
|
|
4630
|
+
|
|
4631
|
+
Playwright tools available (require the "playwright" MCP server to be enabled):
|
|
4632
|
+
playwright_navigate(url) \u2014 open a page at the given URL
|
|
4633
|
+
playwright_screenshot() \u2014 capture a full-page or viewport screenshot
|
|
4634
|
+
playwright_click(selector) \u2014 click on an element matching a CSS selector
|
|
4635
|
+
playwright_type(selector, text) \u2014 type text into a focused input element
|
|
4636
|
+
playwright_evaluate(script) \u2014 run arbitrary JavaScript in the page context
|
|
4637
|
+
playwright_select_option(selector, value) \u2014 pick a <select> dropdown option
|
|
4638
|
+
playwright_hover(selector) \u2014 hover the mouse over an element
|
|
4639
|
+
playwright_fill_form(fields) \u2014 fill multiple form fields in one call
|
|
4640
|
+
playwright_wait_for(selector) \u2014 block until an element appears on the page
|
|
4641
|
+
playwright_press_key(key) \u2014 press a keyboard key (Enter, Tab, Escape, \u2026)
|
|
4642
|
+
playwright_drag(from, to) \u2014 drag an element from one selector to another
|
|
4480
4643
|
|
|
4481
4644
|
Input format you accept:
|
|
4482
4645
|
{ "task": "scenario | smoke | journey", "flow": "<user journey>", "surface": "ui | cli | api" }
|
|
@@ -4490,8 +4653,10 @@ Output: Markdown e2e report:
|
|
|
4490
4653
|
Working rules:
|
|
4491
4654
|
- Test the real flow end to end; don't stub the thing under test
|
|
4492
4655
|
- Make scenarios deterministic \u2014 control time, randomness, and external state
|
|
4493
|
-
- On failure, capture artifacts (logs
|
|
4494
|
-
- Keep scenarios independent so one failure doesn't cascade
|
|
4656
|
+
- On failure, capture artifacts (screenshots, page HTML, logs) for reproduction
|
|
4657
|
+
- Keep scenarios independent so one failure doesn't cascade
|
|
4658
|
+
- For browser tests: playwright_navigate first, then interact, then playwright_screenshot as evidence
|
|
4659
|
+
- If playwright tools are unavailable, report it and fall back to API/CLI testing`
|
|
4495
4660
|
},
|
|
4496
4661
|
budget: HEAVY_BUDGET,
|
|
4497
4662
|
capability: {
|
|
@@ -4504,10 +4669,106 @@ Working rules:
|
|
|
4504
4669
|
"user journey",
|
|
4505
4670
|
"smoke test",
|
|
4506
4671
|
"playwright",
|
|
4672
|
+
"browser",
|
|
4673
|
+
"screenshot",
|
|
4674
|
+
"web ui",
|
|
4675
|
+
"headless",
|
|
4507
4676
|
"cypress",
|
|
4508
4677
|
"full flow",
|
|
4509
4678
|
"browser test",
|
|
4510
|
-
"acceptance test"
|
|
4679
|
+
"acceptance test",
|
|
4680
|
+
"navigate",
|
|
4681
|
+
"click",
|
|
4682
|
+
"form fill",
|
|
4683
|
+
"dom",
|
|
4684
|
+
"page load"
|
|
4685
|
+
]
|
|
4686
|
+
}
|
|
4687
|
+
},
|
|
4688
|
+
{
|
|
4689
|
+
config: {
|
|
4690
|
+
id: "browser",
|
|
4691
|
+
name: "Browser",
|
|
4692
|
+
role: "browser",
|
|
4693
|
+
tools: [
|
|
4694
|
+
...TOOLS.read,
|
|
4695
|
+
"fetch",
|
|
4696
|
+
"playwright_navigate",
|
|
4697
|
+
"playwright_screenshot",
|
|
4698
|
+
"playwright_click",
|
|
4699
|
+
"playwright_type",
|
|
4700
|
+
"playwright_evaluate",
|
|
4701
|
+
"playwright_select_option",
|
|
4702
|
+
"playwright_hover",
|
|
4703
|
+
"playwright_fill_form",
|
|
4704
|
+
"playwright_wait_for",
|
|
4705
|
+
"playwright_press_key",
|
|
4706
|
+
"playwright_drag"
|
|
4707
|
+
],
|
|
4708
|
+
prompt: `You are the Browser agent. Your job is browser automation: open web pages,
|
|
4709
|
+
interact with them, extract data, capture screenshots, and return structured
|
|
4710
|
+
results. You are a read-focused agent \u2014 you drive the browser, not the filesystem.
|
|
4711
|
+
|
|
4712
|
+
Scope:
|
|
4713
|
+
- Navigate to URLs and wait for pages to load
|
|
4714
|
+
- Take full-page or element screenshots as evidence
|
|
4715
|
+
- Click buttons, fill forms, select options, type text \u2014 full user simulation
|
|
4716
|
+
- Extract page content: text, HTML, element attributes, data tables
|
|
4717
|
+
- Evaluate JavaScript in the page context to extract structured data
|
|
4718
|
+
- Verify visual state (element visibility, text content, attribute values)
|
|
4719
|
+
|
|
4720
|
+
Playwright tools available (require the "playwright" MCP server to be enabled):
|
|
4721
|
+
playwright_navigate(url) \u2014 open a page at the given URL
|
|
4722
|
+
playwright_screenshot() \u2014 capture a full-page or viewport screenshot
|
|
4723
|
+
playwright_click(selector) \u2014 click on an element matching a CSS selector
|
|
4724
|
+
playwright_type(selector, text) \u2014 type text into a focused input element
|
|
4725
|
+
playwright_evaluate(script) \u2014 run arbitrary JavaScript in the page context
|
|
4726
|
+
playwright_select_option(selector, value) \u2014 pick a <select> dropdown option
|
|
4727
|
+
playwright_hover(selector) \u2014 hover the mouse over an element
|
|
4728
|
+
playwright_fill_form(fields) \u2014 fill multiple form fields in one call
|
|
4729
|
+
playwright_wait_for(selector) \u2014 block until an element appears on the page
|
|
4730
|
+
playwright_press_key(key) \u2014 press a keyboard key (Enter, Tab, Escape, \u2026)
|
|
4731
|
+
playwright_drag(from, to) \u2014 drag an element from one selector to another
|
|
4732
|
+
|
|
4733
|
+
Input format you accept:
|
|
4734
|
+
{ "task": "navigate | screenshot | extract | interact | verify", "url": "<url>", "steps": ["step1", "step2"] }
|
|
4735
|
+
|
|
4736
|
+
Output: Structured markdown report:
|
|
4737
|
+
- ## Page (URL, title, load status)
|
|
4738
|
+
- ## Actions Taken (step-by-step with timestamps)
|
|
4739
|
+
- ## Results (extracted data, element states, verification results)
|
|
4740
|
+
- ## Screenshots (list attached screenshot references)
|
|
4741
|
+
- ## Errors (any failures with stack traces)
|
|
4742
|
+
|
|
4743
|
+
Working rules:
|
|
4744
|
+
- Always playwright_navigate first before any interaction
|
|
4745
|
+
- Always playwright_wait_for after navigation to ensure the page is ready
|
|
4746
|
+
- playwright_screenshot is your primary evidence \u2014 use it before and after interactions
|
|
4747
|
+
- Use playwright_evaluate for structured data extraction (JSON, text content)
|
|
4748
|
+
- If a selector fails, try alternative selectors before giving up
|
|
4749
|
+
- Report exact CSS selectors used \u2014 they're part of the evidence
|
|
4750
|
+
- If playwright tools are unavailable, report the error immediately \u2014 do not guess`
|
|
4751
|
+
},
|
|
4752
|
+
budget: MEDIUM_BUDGET,
|
|
4753
|
+
capability: {
|
|
4754
|
+
phase: "verify",
|
|
4755
|
+
summary: "Browser automation: opens pages, clicks, types, screenshots, extracts data via Playwright headless Chromium.",
|
|
4756
|
+
keywords: [
|
|
4757
|
+
"browser",
|
|
4758
|
+
"screenshot",
|
|
4759
|
+
"navigate",
|
|
4760
|
+
"web page",
|
|
4761
|
+
"scrape",
|
|
4762
|
+
"crawl",
|
|
4763
|
+
"headless",
|
|
4764
|
+
"chrome",
|
|
4765
|
+
"open url",
|
|
4766
|
+
"capture",
|
|
4767
|
+
"page title",
|
|
4768
|
+
"extract data",
|
|
4769
|
+
"fill form",
|
|
4770
|
+
"click button",
|
|
4771
|
+
"take screenshot"
|
|
4511
4772
|
]
|
|
4512
4773
|
}
|
|
4513
4774
|
},
|