explorbot 0.1.6 → 0.1.7

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.
@@ -131,7 +131,15 @@ export const fileUploadRule = dedent `
131
131
  export const protectionRule = dedent `
132
132
  <important>
133
133
  Do not sign out current user of the application.
134
- Do not change current user account settings
134
+ Do not change current user account settings.
135
+
136
+ Pre-existing data on the page belongs to the application, not the test.
137
+ Items that were not created inside the current test scenario must not be deleted, removed, emptied, reset, archived, or otherwise destroyed.
138
+ If a scenario needs to verify destructive behaviour, the same scenario must first create a disposable target and then destroy that specific target — never operate on data that was already there when the test started.
139
+
140
+ The resource that the current page URL represents is "under test".
141
+ The test must not destroy the resource it is running against — doing so invalidates every subsequent scenario that starts on the same URL.
142
+ Do not propose or perform delete/remove/archive actions on the entity that owns the current URL; propose such actions only on disposable children created within the scenario itself.
135
143
  </important>
136
144
  `;
137
145
  export const focusedElementRule = dedent `
@@ -12,7 +12,7 @@ import { detectFocusArea, extractFocusedElement } from "../utils/aria.js";
12
12
  import { HooksRunner } from "../utils/hooks-runner.js";
13
13
  import { createDebug, tag } from "../utils/logger.js";
14
14
  import { loop } from "../utils/loop.js";
15
- import { actionRule, focusedElementRule, locatorRule, multipleTabsRule, sectionContextRule } from "./rules.js";
15
+ import { actionRule, focusedElementRule, locatorRule, multipleTabsRule, protectionRule, sectionContextRule } from "./rules.js";
16
16
  import { TaskAgent } from "./task-agent.js";
17
17
  import { createCodeceptJSTools, createSpecialContextTools } from "./tools.js";
18
18
  const debugLog = createDebug('explorbot:tester');
@@ -97,6 +97,22 @@ export class Tester extends TaskAgent {
97
97
  this.explorer.getStateManager().clearHistory();
98
98
  this.resetFailureCount();
99
99
  this.pilot?.reset();
100
+ const requestStore = this.explorer.getRequestStore();
101
+ requestStore?.clear();
102
+ const offFailedRequest = requestStore?.onFailedRequest((r) => {
103
+ task.addNote(`Network error: ${r.method} ${r.path} → ${r.status}`, TestResult.FAILED);
104
+ });
105
+ const page = this.explorer.playwrightHelper?.page;
106
+ const onPageError = (err) => {
107
+ task.addNote(`Console error: ${err.message}`, TestResult.FAILED);
108
+ };
109
+ const onConsoleMessage = (msg) => {
110
+ if (msg.type() !== 'error')
111
+ return;
112
+ task.addNote(`Console error: ${msg.text()}`, TestResult.FAILED);
113
+ };
114
+ page?.on('pageerror', onPageError);
115
+ page?.on('console', onConsoleMessage);
100
116
  const initialState = ActionResult.fromState(state);
101
117
  const conversation = this.provider.startConversation(this.getSystemMessage(), 'tester');
102
118
  this.currentConversation = conversation;
@@ -295,6 +311,9 @@ export class Tester extends TaskAgent {
295
311
  }
296
312
  await this.getQuartermaster().analyzeSession(task, initialState, conversation);
297
313
  offStateChange();
314
+ offFailedRequest?.();
315
+ page?.off('pageerror', onPageError);
316
+ page?.off('console', onConsoleMessage);
298
317
  await this.finishTest(task);
299
318
  await this.explorer.stopTest(task, {
300
319
  startUrl: task.startUrl,
@@ -606,6 +625,8 @@ export class Tester extends TaskAgent {
606
625
  When creating or editing items via form() or type() you should include ${task.sessionName} in the value (if it is not restricted by the application logic)
607
626
  Initial page URL: ${actionResult.url}
608
627
 
628
+ ${protectionRule}
629
+
609
630
  ${this.buildDeletionScope(task)}
610
631
 
611
632
  ${this.buildAvailableFiles()}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "explorbot",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "CLI app built with React Ink, CodeceptJS, and Playwright",
5
5
  "license": "Elastic-2.0",
6
6
  "type": "module",
package/src/ai/rules.ts CHANGED
@@ -135,7 +135,15 @@ export const fileUploadRule = dedent`
135
135
  export const protectionRule = dedent`
136
136
  <important>
137
137
  Do not sign out current user of the application.
138
- Do not change current user account settings
138
+ Do not change current user account settings.
139
+
140
+ Pre-existing data on the page belongs to the application, not the test.
141
+ Items that were not created inside the current test scenario must not be deleted, removed, emptied, reset, archived, or otherwise destroyed.
142
+ If a scenario needs to verify destructive behaviour, the same scenario must first create a disposable target and then destroy that specific target — never operate on data that was already there when the test started.
143
+
144
+ The resource that the current page URL represents is "under test".
145
+ The test must not destroy the resource it is running against — doing so invalidates every subsequent scenario that starts on the same URL.
146
+ Do not propose or perform delete/remove/archive actions on the entity that owns the current URL; propose such actions only on disposable children created within the scenario itself.
139
147
  </important>
140
148
  `;
141
149
 
package/src/ai/tester.ts CHANGED
@@ -17,13 +17,13 @@ import { codeToMarkdown } from '../utils/html.ts';
17
17
  import { createDebug, tag } from '../utils/logger.ts';
18
18
  import { loop } from '../utils/loop.ts';
19
19
  import type { Agent } from './agent.ts';
20
+ import type { Captain } from './captain.ts';
20
21
  import type { Conversation } from './conversation.ts';
21
22
  import { Navigator } from './navigator.ts';
22
- import type { Captain } from './captain.ts';
23
23
  import type { Pilot } from './pilot.ts';
24
24
  import { Provider } from './provider.ts';
25
25
  import { Researcher } from './researcher.ts';
26
- import { actionRule, focusedElementRule, locatorRule, multipleTabsRule, sectionContextRule } from './rules.ts';
26
+ import { actionRule, focusedElementRule, locatorRule, multipleTabsRule, protectionRule, sectionContextRule } from './rules.ts';
27
27
  import { TaskAgent } from './task-agent.ts';
28
28
  import { createCodeceptJSTools, createSpecialContextTools } from './tools.ts';
29
29
 
@@ -125,6 +125,23 @@ export class Tester extends TaskAgent implements Agent {
125
125
  this.resetFailureCount();
126
126
  this.pilot?.reset();
127
127
 
128
+ const requestStore = this.explorer.getRequestStore();
129
+ requestStore?.clear();
130
+ const offFailedRequest = requestStore?.onFailedRequest((r) => {
131
+ task.addNote(`Network error: ${r.method} ${r.path} → ${r.status}`, TestResult.FAILED);
132
+ });
133
+
134
+ const page = this.explorer.playwrightHelper?.page;
135
+ const onPageError = (err: Error) => {
136
+ task.addNote(`Console error: ${err.message}`, TestResult.FAILED);
137
+ };
138
+ const onConsoleMessage = (msg: any) => {
139
+ if (msg.type() !== 'error') return;
140
+ task.addNote(`Console error: ${msg.text()}`, TestResult.FAILED);
141
+ };
142
+ page?.on('pageerror', onPageError);
143
+ page?.on('console', onConsoleMessage);
144
+
128
145
  const initialState = ActionResult.fromState(state);
129
146
 
130
147
  const conversation = this.provider.startConversation(this.getSystemMessage(), 'tester');
@@ -355,6 +372,9 @@ export class Tester extends TaskAgent implements Agent {
355
372
  await this.getQuartermaster().analyzeSession(task, initialState, conversation);
356
373
 
357
374
  offStateChange();
375
+ offFailedRequest?.();
376
+ page?.off('pageerror', onPageError);
377
+ page?.off('console', onConsoleMessage);
358
378
  await this.finishTest(task);
359
379
  await this.explorer.stopTest(task, {
360
380
  startUrl: task.startUrl,
@@ -691,6 +711,8 @@ export class Tester extends TaskAgent implements Agent {
691
711
  When creating or editing items via form() or type() you should include ${task.sessionName} in the value (if it is not restricted by the application logic)
692
712
  Initial page URL: ${actionResult.url}
693
713
 
714
+ ${protectionRule}
715
+
694
716
  ${this.buildDeletionScope(task)}
695
717
 
696
718
  ${this.buildAvailableFiles()}