@openqa/cli 2.1.0 → 2.1.1

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.
@@ -26,7 +26,7 @@ init_esm_shims();
26
26
  import { ReActAgent as ReActAgent2 } from "@orka-js/agent";
27
27
  import { OpenAIAdapter as OpenAIAdapter2 } from "@orka-js/openai";
28
28
  import { AnthropicAdapter as AnthropicAdapter2 } from "@orka-js/anthropic";
29
- import { SessionMemory } from "@orka-js/memory-store";
29
+ import { Memory } from "@orka-js/memory-store";
30
30
  import { Tracer } from "@orka-js/observability";
31
31
  import { EventEmitter as EventEmitter3 } from "events";
32
32
 
@@ -621,13 +621,9 @@ var BrowserTools = class {
621
621
  {
622
622
  name: "navigate_to_page",
623
623
  description: "Navigate to a specific URL in the application",
624
- parameters: {
625
- type: "object",
626
- properties: {
627
- url: { type: "string", description: "The URL to navigate to" }
628
- },
629
- required: ["url"]
630
- },
624
+ parameters: [
625
+ { name: "url", type: "string", description: "The URL to navigate to", required: true }
626
+ ],
631
627
  execute: async ({ url }) => {
632
628
  if (!this.page) await this.initialize();
633
629
  try {
@@ -640,24 +636,20 @@ var BrowserTools = class {
640
636
  input: url,
641
637
  output: `Page title: ${title}`
642
638
  });
643
- return `Successfully navigated to ${url}. Page title: "${title}"`;
639
+ return { output: `Successfully navigated to ${url}. Page title: "${title}"` };
644
640
  } catch (error) {
645
- return `Failed to navigate: ${error instanceof Error ? error.message : String(error)}`;
641
+ return { output: `Failed to navigate: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };
646
642
  }
647
643
  }
648
644
  },
649
645
  {
650
646
  name: "click_element",
651
647
  description: "Click on an element using a CSS selector",
652
- parameters: {
653
- type: "object",
654
- properties: {
655
- selector: { type: "string", description: "CSS selector of the element to click" }
656
- },
657
- required: ["selector"]
658
- },
648
+ parameters: [
649
+ { name: "selector", type: "string", description: "CSS selector of the element to click", required: true }
650
+ ],
659
651
  execute: async ({ selector }) => {
660
- if (!this.page) return "Browser not initialized. Navigate to a page first.";
652
+ if (!this.page) return { output: "Browser not initialized. Navigate to a page first.", error: "Browser not initialized" };
661
653
  try {
662
654
  await this.page.click(selector, { timeout: 5e3 });
663
655
  this.db.createAction({
@@ -666,25 +658,21 @@ var BrowserTools = class {
666
658
  description: `Clicked element: ${selector}`,
667
659
  input: selector
668
660
  });
669
- return `Successfully clicked element: ${selector}`;
661
+ return { output: `Successfully clicked element: ${selector}` };
670
662
  } catch (error) {
671
- return `Failed to click element: ${error instanceof Error ? error.message : String(error)}`;
663
+ return { output: `Failed to click element: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };
672
664
  }
673
665
  }
674
666
  },
675
667
  {
676
668
  name: "fill_input",
677
669
  description: "Fill an input field with text",
678
- parameters: {
679
- type: "object",
680
- properties: {
681
- selector: { type: "string", description: "CSS selector of the input field" },
682
- text: { type: "string", description: "Text to fill in the input" }
683
- },
684
- required: ["selector", "text"]
685
- },
670
+ parameters: [
671
+ { name: "selector", type: "string", description: "CSS selector of the input field", required: true },
672
+ { name: "text", type: "string", description: "Text to fill in the input", required: true }
673
+ ],
686
674
  execute: async ({ selector, text }) => {
687
- if (!this.page) return "Browser not initialized. Navigate to a page first.";
675
+ if (!this.page) return { output: "Browser not initialized. Navigate to a page first.", error: "Browser not initialized" };
688
676
  try {
689
677
  await this.page.fill(selector, text);
690
678
  this.db.createAction({
@@ -693,24 +681,20 @@ var BrowserTools = class {
693
681
  description: `Filled input ${selector}`,
694
682
  input: `${selector} = ${text}`
695
683
  });
696
- return `Successfully filled input ${selector} with text`;
684
+ return { output: `Successfully filled input ${selector} with text` };
697
685
  } catch (error) {
698
- return `Failed to fill input: ${error instanceof Error ? error.message : String(error)}`;
686
+ return { output: `Failed to fill input: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };
699
687
  }
700
688
  }
701
689
  },
702
690
  {
703
691
  name: "take_screenshot",
704
692
  description: "Take a screenshot of the current page for evidence",
705
- parameters: {
706
- type: "object",
707
- properties: {
708
- name: { type: "string", description: "Name for the screenshot file" }
709
- },
710
- required: ["name"]
711
- },
693
+ parameters: [
694
+ { name: "name", type: "string", description: "Name for the screenshot file", required: true }
695
+ ],
712
696
  execute: async ({ name }) => {
713
- if (!this.page) return "Browser not initialized. Navigate to a page first.";
697
+ if (!this.page) return { output: "Browser not initialized. Navigate to a page first.", error: "Browser not initialized" };
714
698
  try {
715
699
  const filename = `${Date.now()}_${name}.png`;
716
700
  const path2 = join2(this.screenshotDir, filename);
@@ -721,38 +705,32 @@ var BrowserTools = class {
721
705
  description: `Screenshot: ${name}`,
722
706
  screenshot_path: path2
723
707
  });
724
- return `Screenshot saved: ${path2}`;
708
+ return { output: `Screenshot saved: ${path2}` };
725
709
  } catch (error) {
726
- return `Failed to take screenshot: ${error instanceof Error ? error.message : String(error)}`;
710
+ return { output: `Failed to take screenshot: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };
727
711
  }
728
712
  }
729
713
  },
730
714
  {
731
715
  name: "get_page_content",
732
716
  description: "Get the text content of the current page",
733
- parameters: {
734
- type: "object",
735
- properties: {}
736
- },
717
+ parameters: [],
737
718
  execute: async () => {
738
- if (!this.page) return "Browser not initialized. Navigate to a page first.";
719
+ if (!this.page) return { output: "Browser not initialized. Navigate to a page first.", error: "Browser not initialized" };
739
720
  try {
740
721
  const content = await this.page.textContent("body");
741
- return content?.slice(0, 1e3) || "No content found";
722
+ return { output: content?.slice(0, 1e3) || "No content found" };
742
723
  } catch (error) {
743
- return `Failed to get content: ${error instanceof Error ? error.message : String(error)}`;
724
+ return { output: `Failed to get content: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };
744
725
  }
745
726
  }
746
727
  },
747
728
  {
748
729
  name: "check_console_errors",
749
730
  description: "Check for JavaScript console errors on the page",
750
- parameters: {
751
- type: "object",
752
- properties: {}
753
- },
731
+ parameters: [],
754
732
  execute: async () => {
755
- if (!this.page) return "Browser not initialized. Navigate to a page first.";
733
+ if (!this.page) return { output: "Browser not initialized. Navigate to a page first.", error: "Browser not initialized" };
756
734
  const errors = [];
757
735
  this.page.on("console", (msg) => {
758
736
  if (msg.type() === "error") {
@@ -761,10 +739,10 @@ var BrowserTools = class {
761
739
  });
762
740
  await this.page.waitForTimeout(2e3);
763
741
  if (errors.length > 0) {
764
- return `Found ${errors.length} console errors:
765
- ${errors.join("\n")}`;
742
+ return { output: `Found ${errors.length} console errors:
743
+ ${errors.join("\n")}` };
766
744
  }
767
- return "No console errors detected";
745
+ return { output: "No console errors detected" };
768
746
  }
769
747
  }
770
748
  ];
@@ -799,20 +777,16 @@ var GitHubTools = class {
799
777
  {
800
778
  name: "create_github_issue",
801
779
  description: "Create a GitHub issue when a critical bug is found. Use this for bugs that require developer attention.",
802
- parameters: {
803
- type: "object",
804
- properties: {
805
- title: { type: "string", description: "Issue title (concise and descriptive)" },
806
- body: { type: "string", description: "Detailed description with steps to reproduce" },
807
- severity: { type: "string", enum: ["low", "medium", "high", "critical"], description: "Bug severity" },
808
- labels: { type: "array", items: { type: "string" }, description: "Labels for the issue" },
809
- screenshot_path: { type: "string", description: "Path to screenshot evidence" }
810
- },
811
- required: ["title", "body", "severity"]
812
- },
780
+ parameters: [
781
+ { name: "title", type: "string", description: "Issue title (concise and descriptive)", required: true },
782
+ { name: "body", type: "string", description: "Detailed description with steps to reproduce", required: true },
783
+ { name: "severity", type: "string", description: "Bug severity (low, medium, high, critical)", required: true },
784
+ { name: "labels", type: "string", description: "Comma-separated labels for the issue", required: false },
785
+ { name: "screenshot_path", type: "string", description: "Path to screenshot evidence", required: false }
786
+ ],
813
787
  execute: async ({ title, body, severity, labels = [], screenshot_path }) => {
814
788
  if (!this.octokit || !this.config.owner || !this.config.repo) {
815
- return "GitHub not configured. Please set GITHUB_TOKEN, GITHUB_OWNER, and GITHUB_REPO.";
789
+ return { output: "GitHub not configured. Please set GITHUB_TOKEN, GITHUB_OWNER, and GITHUB_REPO.", error: "GitHub not configured" };
816
790
  }
817
791
  try {
818
792
  const severityLabel = `severity: ${severity}`;
@@ -852,11 +826,11 @@ ${screenshot_path ? `**Screenshot:** ${screenshot_path}` : ""}
852
826
  github_issue_url: issue.data.html_url,
853
827
  screenshot_path
854
828
  });
855
- return `\u2705 GitHub issue created successfully!
829
+ return { output: `\u2705 GitHub issue created successfully!
856
830
  URL: ${issue.data.html_url}
857
- Issue #${issue.data.number}`;
831
+ Issue #${issue.data.number}` };
858
832
  } catch (error) {
859
- return `\u274C Failed to create GitHub issue: ${error instanceof Error ? error.message : String(error)}`;
833
+ return { output: `\u274C Failed to create GitHub issue: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };
860
834
  }
861
835
  }
862
836
  }
@@ -878,18 +852,14 @@ var KanbanTools = class {
878
852
  {
879
853
  name: "create_kanban_ticket",
880
854
  description: "Create a ticket on the internal Kanban board for QA tracking. Use this for bugs, improvements, or test findings.",
881
- parameters: {
882
- type: "object",
883
- properties: {
884
- title: { type: "string", description: "Ticket title" },
885
- description: { type: "string", description: "Detailed description" },
886
- priority: { type: "string", enum: ["low", "medium", "high", "critical"], description: "Ticket priority" },
887
- column: { type: "string", enum: ["backlog", "to-do", "in-progress", "done"], description: "Kanban column" },
888
- tags: { type: "array", items: { type: "string" }, description: "Tags for categorization" },
889
- screenshot_path: { type: "string", description: "Path to screenshot evidence" }
890
- },
891
- required: ["title", "description", "priority"]
892
- },
855
+ parameters: [
856
+ { name: "title", type: "string", description: "Ticket title", required: true },
857
+ { name: "description", type: "string", description: "Detailed description", required: true },
858
+ { name: "priority", type: "string", description: "Ticket priority (low, medium, high, critical)", required: true },
859
+ { name: "column", type: "string", description: "Kanban column (backlog, to-do, in-progress, done)", required: false },
860
+ { name: "tags", type: "string", description: "Comma-separated tags for categorization", required: false },
861
+ { name: "screenshot_path", type: "string", description: "Path to screenshot evidence", required: false }
862
+ ],
893
863
  execute: async ({ title, description, priority, column = "to-do", tags = [], screenshot_path }) => {
894
864
  try {
895
865
  const allTags = ["automated-qa", ...tags];
@@ -908,46 +878,39 @@ var KanbanTools = class {
908
878
  input: JSON.stringify({ title, priority, column }),
909
879
  output: ticket.id
910
880
  });
911
- return `\u2705 Kanban ticket created successfully!
881
+ return { output: `\u2705 Kanban ticket created successfully!
912
882
  ID: ${ticket.id}
913
883
  Column: ${column}
914
- Priority: ${priority}`;
884
+ Priority: ${priority}` };
915
885
  } catch (error) {
916
- return `\u274C Failed to create Kanban ticket: ${error instanceof Error ? error.message : String(error)}`;
886
+ return { output: `\u274C Failed to create Kanban ticket: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };
917
887
  }
918
888
  }
919
889
  },
920
890
  {
921
891
  name: "update_kanban_ticket",
922
892
  description: "Update an existing Kanban ticket (move columns, change priority, etc.)",
923
- parameters: {
924
- type: "object",
925
- properties: {
926
- ticket_id: { type: "string", description: "ID of the ticket to update" },
927
- column: { type: "string", enum: ["backlog", "to-do", "in-progress", "done"], description: "New column" },
928
- priority: { type: "string", enum: ["low", "medium", "high", "critical"], description: "New priority" }
929
- },
930
- required: ["ticket_id"]
931
- },
893
+ parameters: [
894
+ { name: "ticket_id", type: "string", description: "ID of the ticket to update", required: true },
895
+ { name: "column", type: "string", description: "New column (backlog, to-do, in-progress, done)", required: false },
896
+ { name: "priority", type: "string", description: "New priority (low, medium, high, critical)", required: false }
897
+ ],
932
898
  execute: async ({ ticket_id, column, priority }) => {
933
899
  try {
934
900
  const updates = {};
935
901
  if (column) updates.column = column;
936
902
  if (priority) updates.priority = priority;
937
903
  await this.db.updateKanbanTicket(ticket_id, updates);
938
- return `\u2705 Kanban ticket ${ticket_id} updated successfully!`;
904
+ return { output: `\u2705 Kanban ticket ${ticket_id} updated successfully!` };
939
905
  } catch (error) {
940
- return `\u274C Failed to update Kanban ticket: ${error instanceof Error ? error.message : String(error)}`;
906
+ return { output: `\u274C Failed to update Kanban ticket: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };
941
907
  }
942
908
  }
943
909
  },
944
910
  {
945
911
  name: "get_kanban_board",
946
912
  description: "Get all tickets from the Kanban board to see current status",
947
- parameters: {
948
- type: "object",
949
- properties: {}
950
- },
913
+ parameters: [],
951
914
  execute: async () => {
952
915
  try {
953
916
  const tickets = await this.db.getKanbanTickets();
@@ -966,9 +929,9 @@ Priority: ${priority}`;
966
929
 
967
930
  Total: ${tickets.length} tickets
968
931
  `.trim();
969
- return summary;
932
+ return { output: summary };
970
933
  } catch (error) {
971
- return `\u274C Failed to get Kanban board: ${error instanceof Error ? error.message : String(error)}`;
934
+ return { output: `\u274C Failed to get Kanban board: ${error instanceof Error ? error.message : String(error)}`, error: error instanceof Error ? error.message : String(error) };
972
935
  }
973
936
  }
974
937
  }
@@ -1739,7 +1702,7 @@ var OpenQAAgent = class extends EventEmitter3 {
1739
1702
  ...kanbanTools.getTools()
1740
1703
  ];
1741
1704
  const llm = this.createLLMAdapter();
1742
- const memory = new SessionMemory({ maxMessages: 50 });
1705
+ const memory = new Memory({ maxMessages: 50 });
1743
1706
  const tracer = new Tracer({ logLevel: "info" });
1744
1707
  const enabledSkills = this.skillManager.getEnabledSkills();
1745
1708
  const skillPrompt = this.skillManager.generateSkillPrompt(enabledSkills);
@@ -1780,8 +1743,9 @@ ${skillPrompt}
1780
1743
  Always provide clear, actionable information with steps to reproduce. Think step by step like a human QA expert.`
1781
1744
  };
1782
1745
  this.agent = new ReActAgent2({
1746
+ goal: agentConfig.goal,
1783
1747
  tools: allTools,
1784
- maxIterations: cfg.agent.maxIterations,
1748
+ maxSteps: cfg.agent.maxIterations,
1785
1749
  systemPrompt: agentConfig.systemPrompt
1786
1750
  }, llm, memory);
1787
1751
  this.specialistManager = new SpecialistAgentManager(
@@ -1882,17 +1846,22 @@ Always provide clear, actionable information with steps to reproduce. Think step
1882
1846
  branch: "main",
1883
1847
  pollIntervalMs: 6e4
1884
1848
  });
1885
- } else if (this.config.get("gitlab.token") && this.config.get("gitlab.project")) {
1886
- const [owner, repo] = (this.config.get("gitlab.project") || "").split("/");
1887
- this.gitListener = new GitListener({
1888
- provider: "gitlab",
1889
- token: this.config.get("gitlab.token") || "",
1890
- owner,
1891
- repo,
1892
- branch: "main",
1893
- pollIntervalMs: 6e4,
1894
- gitlabUrl: this.config.get("gitlab.url") || "https://gitlab.com"
1895
- });
1849
+ } else {
1850
+ const gitlabToken = await this.config.get("gitlab.token");
1851
+ const gitlabProject = await this.config.get("gitlab.project");
1852
+ if (gitlabToken && gitlabProject) {
1853
+ const [owner, repo] = gitlabProject.split("/");
1854
+ const gitlabUrl = await this.config.get("gitlab.url");
1855
+ this.gitListener = new GitListener({
1856
+ provider: "gitlab",
1857
+ token: gitlabToken,
1858
+ owner,
1859
+ repo,
1860
+ branch: "main",
1861
+ pollIntervalMs: 6e4,
1862
+ gitlabUrl: gitlabUrl || "https://gitlab.com"
1863
+ });
1864
+ }
1896
1865
  }
1897
1866
  if (this.gitListener) {
1898
1867
  this.gitListener.on("merge", async (event) => {