testeiya 0.2.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.
Files changed (369) hide show
  1. package/README.md +212 -0
  2. package/models.catalog.json +6963 -0
  3. package/package.json +71 -0
  4. package/skills/codeceptjs/ci-fix-tests/SKILL.md +120 -0
  5. package/skills/codeceptjs/codeceptjs-auth/SKILL.md +158 -0
  6. package/skills/codeceptjs/codeceptjs-exploration/SKILL.md +91 -0
  7. package/skills/codeceptjs/codeceptjs-fundamentals/SKILL.md +158 -0
  8. package/skills/codeceptjs/codeceptjs-run-analysis/SKILL.md +90 -0
  9. package/skills/codeceptjs/debugging-codeceptjs-tests/SKILL.md +234 -0
  10. package/skills/codeceptjs/migrate-codeceptjs-4/SKILL.md +110 -0
  11. package/skills/codeceptjs/migrate-cypress-to-codeceptjs/SKILL.md +306 -0
  12. package/skills/codeceptjs/migrate-protractor-to-codeceptjs/SKILL.md +352 -0
  13. package/skills/codeceptjs/migrate-selenium-java-to-codeceptjs/SKILL.md +472 -0
  14. package/skills/codeceptjs/migrate-testcafe-to-codeceptjs/SKILL.md +350 -0
  15. package/skills/codeceptjs/refactoring-codeceptjs-tests/SKILL.md +81 -0
  16. package/skills/codeceptjs/writing-codeceptjs-tests/SKILL.md +206 -0
  17. package/skills/playwright-best-practices-skill/LICENSE.md +7 -0
  18. package/skills/playwright-best-practices-skill/README.md +147 -0
  19. package/skills/playwright-best-practices-skill/SKILL.md +303 -0
  20. package/skills/playwright-best-practices-skill/advanced/authentication-flows.md +360 -0
  21. package/skills/playwright-best-practices-skill/advanced/authentication.md +871 -0
  22. package/skills/playwright-best-practices-skill/advanced/clock-mocking.md +364 -0
  23. package/skills/playwright-best-practices-skill/advanced/mobile-testing.md +409 -0
  24. package/skills/playwright-best-practices-skill/advanced/multi-context.md +288 -0
  25. package/skills/playwright-best-practices-skill/advanced/multi-user.md +393 -0
  26. package/skills/playwright-best-practices-skill/advanced/network-advanced.md +452 -0
  27. package/skills/playwright-best-practices-skill/advanced/third-party.md +464 -0
  28. package/skills/playwright-best-practices-skill/architecture/pom-vs-fixtures.md +363 -0
  29. package/skills/playwright-best-practices-skill/architecture/test-architecture.md +369 -0
  30. package/skills/playwright-best-practices-skill/architecture/when-to-mock.md +383 -0
  31. package/skills/playwright-best-practices-skill/browser-apis/browser-apis.md +391 -0
  32. package/skills/playwright-best-practices-skill/browser-apis/iframes.md +403 -0
  33. package/skills/playwright-best-practices-skill/browser-apis/service-workers.md +504 -0
  34. package/skills/playwright-best-practices-skill/browser-apis/websockets.md +403 -0
  35. package/skills/playwright-best-practices-skill/core/annotations.md +424 -0
  36. package/skills/playwright-best-practices-skill/core/assertions-waiting.md +361 -0
  37. package/skills/playwright-best-practices-skill/core/configuration.md +452 -0
  38. package/skills/playwright-best-practices-skill/core/fixtures-hooks.md +417 -0
  39. package/skills/playwright-best-practices-skill/core/global-setup.md +434 -0
  40. package/skills/playwright-best-practices-skill/core/locators.md +242 -0
  41. package/skills/playwright-best-practices-skill/core/page-object-model.md +315 -0
  42. package/skills/playwright-best-practices-skill/core/projects-dependencies.md +453 -0
  43. package/skills/playwright-best-practices-skill/core/test-data.md +492 -0
  44. package/skills/playwright-best-practices-skill/core/test-suite-structure.md +361 -0
  45. package/skills/playwright-best-practices-skill/core/test-tags.md +298 -0
  46. package/skills/playwright-best-practices-skill/debugging/console-errors.md +420 -0
  47. package/skills/playwright-best-practices-skill/debugging/debugging.md +504 -0
  48. package/skills/playwright-best-practices-skill/debugging/error-testing.md +360 -0
  49. package/skills/playwright-best-practices-skill/debugging/flaky-tests.md +496 -0
  50. package/skills/playwright-best-practices-skill/frameworks/angular.md +530 -0
  51. package/skills/playwright-best-practices-skill/frameworks/nextjs.md +469 -0
  52. package/skills/playwright-best-practices-skill/frameworks/react.md +531 -0
  53. package/skills/playwright-best-practices-skill/frameworks/vue.md +574 -0
  54. package/skills/playwright-best-practices-skill/infrastructure-ci-cd/ci-cd.md +468 -0
  55. package/skills/playwright-best-practices-skill/infrastructure-ci-cd/docker.md +283 -0
  56. package/skills/playwright-best-practices-skill/infrastructure-ci-cd/github-actions.md +546 -0
  57. package/skills/playwright-best-practices-skill/infrastructure-ci-cd/gitlab.md +397 -0
  58. package/skills/playwright-best-practices-skill/infrastructure-ci-cd/other-providers.md +521 -0
  59. package/skills/playwright-best-practices-skill/infrastructure-ci-cd/parallel-sharding.md +371 -0
  60. package/skills/playwright-best-practices-skill/infrastructure-ci-cd/performance.md +453 -0
  61. package/skills/playwright-best-practices-skill/infrastructure-ci-cd/reporting.md +424 -0
  62. package/skills/playwright-best-practices-skill/infrastructure-ci-cd/test-coverage.md +497 -0
  63. package/skills/playwright-best-practices-skill/testing-patterns/accessibility.md +359 -0
  64. package/skills/playwright-best-practices-skill/testing-patterns/api-testing.md +719 -0
  65. package/skills/playwright-best-practices-skill/testing-patterns/browser-extensions.md +506 -0
  66. package/skills/playwright-best-practices-skill/testing-patterns/canvas-webgl.md +493 -0
  67. package/skills/playwright-best-practices-skill/testing-patterns/component-testing.md +500 -0
  68. package/skills/playwright-best-practices-skill/testing-patterns/drag-drop.md +576 -0
  69. package/skills/playwright-best-practices-skill/testing-patterns/electron.md +509 -0
  70. package/skills/playwright-best-practices-skill/testing-patterns/file-operations.md +377 -0
  71. package/skills/playwright-best-practices-skill/testing-patterns/file-upload-download.md +562 -0
  72. package/skills/playwright-best-practices-skill/testing-patterns/forms-validation.md +561 -0
  73. package/skills/playwright-best-practices-skill/testing-patterns/graphql-testing.md +331 -0
  74. package/skills/playwright-best-practices-skill/testing-patterns/i18n.md +508 -0
  75. package/skills/playwright-best-practices-skill/testing-patterns/performance-testing.md +476 -0
  76. package/skills/playwright-best-practices-skill/testing-patterns/security-testing.md +430 -0
  77. package/skills/playwright-best-practices-skill/testing-patterns/visual-regression.md +634 -0
  78. package/skills/playwright-cli/SKILL.md +420 -0
  79. package/skills/playwright-cli/references/element-attributes.md +23 -0
  80. package/skills/playwright-cli/references/playwright-tests.md +39 -0
  81. package/skills/playwright-cli/references/request-mocking.md +87 -0
  82. package/skills/playwright-cli/references/running-code.md +241 -0
  83. package/skills/playwright-cli/references/session-management.md +225 -0
  84. package/skills/playwright-cli/references/storage-state.md +275 -0
  85. package/skills/playwright-cli/references/test-generation.md +433 -0
  86. package/skills/playwright-cli/references/tracing.md +139 -0
  87. package/skills/playwright-cli/references/video-recording.md +143 -0
  88. package/skills/testeiya/README.md +29 -0
  89. package/skills/testeiya/answer-formatting/SKILL.md +30 -0
  90. package/skills/testeiya/check-cucumber/SKILL.md +200 -0
  91. package/skills/testeiya/check-tests/SKILL.md +260 -0
  92. package/skills/testeiya/manual-run-assistant/SKILL.md +61 -0
  93. package/skills/testeiya/testomatio-docs/INDEX.md +175 -0
  94. package/skills/testeiya/testomatio-docs/SKILL.md +102 -0
  95. package/skills/testeiya/testomatio-docs/docs/advanced/ai-powered-features/ai-agents.md +144 -0
  96. package/skills/testeiya/testomatio-docs/docs/advanced/ai-powered-features/ai-powered-features.md +531 -0
  97. package/skills/testeiya/testomatio-docs/docs/advanced/ai-powered-features/ai-requirements.md +437 -0
  98. package/skills/testeiya/testomatio-docs/docs/advanced/api-access/index.md +191 -0
  99. package/skills/testeiya/testomatio-docs/docs/advanced/branches-folder/index.md +277 -0
  100. package/skills/testeiya/testomatio-docs/docs/advanced/bulk-edit-folder/bulk-edit-demos.mdx +39 -0
  101. package/skills/testeiya/testomatio-docs/docs/advanced/bulk-edit-folder/bulk-edit-on-suite-and-test-level.md +122 -0
  102. package/skills/testeiya/testomatio-docs/docs/advanced/bulk-edit-folder/what-is-bulk-edit.md +170 -0
  103. package/skills/testeiya/testomatio-docs/docs/advanced/jira-plugin/branches.md +53 -0
  104. package/skills/testeiya/testomatio-docs/docs/advanced/jira-plugin/index.mdx +98 -0
  105. package/skills/testeiya/testomatio-docs/docs/advanced/jira-plugin/jira-issue.md +151 -0
  106. package/skills/testeiya/testomatio-docs/docs/advanced/jira-plugin/runs-and-reports.md +377 -0
  107. package/skills/testeiya/testomatio-docs/docs/advanced/jira-plugin/work-in-jira.md +267 -0
  108. package/skills/testeiya/testomatio-docs/docs/advanced/living-doc/index.md +138 -0
  109. package/skills/testeiya/testomatio-docs/docs/advanced/milestones/index.md +220 -0
  110. package/skills/testeiya/testomatio-docs/docs/advanced/shortcuts/index.md +48 -0
  111. package/skills/testeiya/testomatio-docs/docs/advanced/tags-labels/labels-and-custom-fields.md +201 -0
  112. package/skills/testeiya/testomatio-docs/docs/advanced/tags-labels/tags-or-labels.md +94 -0
  113. package/skills/testeiya/testomatio-docs/docs/advanced/tags-labels/tags.md +243 -0
  114. package/skills/testeiya/testomatio-docs/docs/advanced/test-artifacts/index.md +135 -0
  115. package/skills/testeiya/testomatio-docs/docs/advanced/tql/index.md +394 -0
  116. package/skills/testeiya/testomatio-docs/docs/getting-started/index.md +290 -0
  117. package/skills/testeiya/testomatio-docs/docs/integrations/continuous-integration/azure.md +96 -0
  118. package/skills/testeiya/testomatio-docs/docs/integrations/continuous-integration/bamboo.md +94 -0
  119. package/skills/testeiya/testomatio-docs/docs/integrations/continuous-integration/bitbucket.md +106 -0
  120. package/skills/testeiya/testomatio-docs/docs/integrations/continuous-integration/circle.md +115 -0
  121. package/skills/testeiya/testomatio-docs/docs/integrations/continuous-integration/github.md +120 -0
  122. package/skills/testeiya/testomatio-docs/docs/integrations/continuous-integration/gitlab.md +88 -0
  123. package/skills/testeiya/testomatio-docs/docs/integrations/continuous-integration/index.mdx +151 -0
  124. package/skills/testeiya/testomatio-docs/docs/integrations/continuous-integration/jenkins.md +121 -0
  125. package/skills/testeiya/testomatio-docs/docs/integrations/continuous-integration/teamcity.md +96 -0
  126. package/skills/testeiya/testomatio-docs/docs/integrations/issues-management/azure.md +31 -0
  127. package/skills/testeiya/testomatio-docs/docs/integrations/issues-management/clickup.md +54 -0
  128. package/skills/testeiya/testomatio-docs/docs/integrations/issues-management/confluence.md +34 -0
  129. package/skills/testeiya/testomatio-docs/docs/integrations/issues-management/github.md +31 -0
  130. package/skills/testeiya/testomatio-docs/docs/integrations/issues-management/gitlab.md +93 -0
  131. package/skills/testeiya/testomatio-docs/docs/integrations/issues-management/index.md +131 -0
  132. package/skills/testeiya/testomatio-docs/docs/integrations/issues-management/jira.md +164 -0
  133. package/skills/testeiya/testomatio-docs/docs/integrations/issues-management/linear.md +29 -0
  134. package/skills/testeiya/testomatio-docs/docs/integrations/issues-management/shortcut.md +67 -0
  135. package/skills/testeiya/testomatio-docs/docs/integrations/issues-management/youtrack.md +94 -0
  136. package/skills/testeiya/testomatio-docs/docs/integrations/report-notifications/azure-devops.md +53 -0
  137. package/skills/testeiya/testomatio-docs/docs/integrations/report-notifications/email.md +71 -0
  138. package/skills/testeiya/testomatio-docs/docs/integrations/report-notifications/jira.md +52 -0
  139. package/skills/testeiya/testomatio-docs/docs/integrations/report-notifications/ms-teams.md +60 -0
  140. package/skills/testeiya/testomatio-docs/docs/integrations/report-notifications/rules.md +267 -0
  141. package/skills/testeiya/testomatio-docs/docs/integrations/report-notifications/slack.md +82 -0
  142. package/skills/testeiya/testomatio-docs/docs/integrations/report-notifications/telegram.md +73 -0
  143. package/skills/testeiya/testomatio-docs/docs/integrations/scim-provisioning/index.mdx +207 -0
  144. package/skills/testeiya/testomatio-docs/docs/integrations/scim-provisioning/okta.md +204 -0
  145. package/skills/testeiya/testomatio-docs/docs/integrations/single-sign-on/azure.md +95 -0
  146. package/skills/testeiya/testomatio-docs/docs/integrations/single-sign-on/google.md +75 -0
  147. package/skills/testeiya/testomatio-docs/docs/integrations/single-sign-on/index.mdx +33 -0
  148. package/skills/testeiya/testomatio-docs/docs/integrations/single-sign-on/okta.md +108 -0
  149. package/skills/testeiya/testomatio-docs/docs/integrations/single-sign-on/saml.md +66 -0
  150. package/skills/testeiya/testomatio-docs/docs/legal/compliance/gdpr.md +95 -0
  151. package/skills/testeiya/testomatio-docs/docs/legal/compliance/index.mdx +94 -0
  152. package/skills/testeiya/testomatio-docs/docs/legal/compliance/privacy.md +26 -0
  153. package/skills/testeiya/testomatio-docs/docs/legal/compliance/terms.md +32 -0
  154. package/skills/testeiya/testomatio-docs/docs/legal/security/index.mdx +242 -0
  155. package/skills/testeiya/testomatio-docs/docs/legal/security/jira.md +140 -0
  156. package/skills/testeiya/testomatio-docs/docs/legal/security/subprocessors.md +76 -0
  157. package/skills/testeiya/testomatio-docs/docs/management/company/administration.md +363 -0
  158. package/skills/testeiya/testomatio-docs/docs/management/company/audit-log.md +41 -0
  159. package/skills/testeiya/testomatio-docs/docs/management/company/plan-features-comparison.md +240 -0
  160. package/skills/testeiya/testomatio-docs/docs/management/company/subscriptions.md +326 -0
  161. package/skills/testeiya/testomatio-docs/docs/management/company/trials.md +75 -0
  162. package/skills/testeiya/testomatio-docs/docs/management/company/users-and-permissions/accountant.md +49 -0
  163. package/skills/testeiya/testomatio-docs/docs/management/company/users-and-permissions/index.mdx +285 -0
  164. package/skills/testeiya/testomatio-docs/docs/management/company/users-and-permissions/read-only-user.md +67 -0
  165. package/skills/testeiya/testomatio-docs/docs/management/company/users-and-permissions/teams.md +138 -0
  166. package/skills/testeiya/testomatio-docs/docs/management/project/settings.md +87 -0
  167. package/skills/testeiya/testomatio-docs/docs/management/project/templates.md +546 -0
  168. package/skills/testeiya/testomatio-docs/docs/project/analytics/index.md +326 -0
  169. package/skills/testeiya/testomatio-docs/docs/project/import-export/export-tests/classical-tests-markdown-format.md +386 -0
  170. package/skills/testeiya/testomatio-docs/docs/project/import-export/export-tests/download-manual-tests-as-files.md +378 -0
  171. package/skills/testeiya/testomatio-docs/docs/project/import-export/export-tests/export-to-obsidian.md +112 -0
  172. package/skills/testeiya/testomatio-docs/docs/project/import-export/export-tests/export-to-spreadsheet.md +127 -0
  173. package/skills/testeiya/testomatio-docs/docs/project/import-export/import/auto-import.md +63 -0
  174. package/skills/testeiya/testomatio-docs/docs/project/import-export/import/import-tests-from-Allure-TestOps.md +49 -0
  175. package/skills/testeiya/testomatio-docs/docs/project/import-export/import/import-tests-from-QTest.md +41 -0
  176. package/skills/testeiya/testomatio-docs/docs/project/import-export/import/import-tests-from-Qase.md +39 -0
  177. package/skills/testeiya/testomatio-docs/docs/project/import-export/import/import-tests-from-Zephyr.md +37 -0
  178. package/skills/testeiya/testomatio-docs/docs/project/import-export/import/import-tests-from-csv-xlsx.md +117 -0
  179. package/skills/testeiya/testomatio-docs/docs/project/import-export/import/import-tests-from-cucumber.md +93 -0
  180. package/skills/testeiya/testomatio-docs/docs/project/import-export/import/import-tests-from-qmetry.md +44 -0
  181. package/skills/testeiya/testomatio-docs/docs/project/import-export/import/import-tests-from-source-code.md +117 -0
  182. package/skills/testeiya/testomatio-docs/docs/project/import-export/import/import-tests-from-testcaselabs.md +44 -0
  183. package/skills/testeiya/testomatio-docs/docs/project/import-export/import/import-tests-from-testmo.md +47 -0
  184. package/skills/testeiya/testomatio-docs/docs/project/import-export/import/import-tests-from-testrail.md +82 -0
  185. package/skills/testeiya/testomatio-docs/docs/project/import-export/import/import-tests-from-xray.md +55 -0
  186. package/skills/testeiya/testomatio-docs/docs/project/plans/index.md +334 -0
  187. package/skills/testeiya/testomatio-docs/docs/project/pulse/index.md +104 -0
  188. package/skills/testeiya/testomatio-docs/docs/project/runs/archive-runs-and-groups.md +176 -0
  189. package/skills/testeiya/testomatio-docs/docs/project/runs/custom-statuses.md +195 -0
  190. package/skills/testeiya/testomatio-docs/docs/project/runs/environments.md +203 -0
  191. package/skills/testeiya/testomatio-docs/docs/project/runs/managing-runs.md +455 -0
  192. package/skills/testeiya/testomatio-docs/docs/project/runs/merge-strategies.md +137 -0
  193. package/skills/testeiya/testomatio-docs/docs/project/runs/reports.md +329 -0
  194. package/skills/testeiya/testomatio-docs/docs/project/runs/rungroups.md +342 -0
  195. package/skills/testeiya/testomatio-docs/docs/project/runs/running-automated-tests.md +256 -0
  196. package/skills/testeiya/testomatio-docs/docs/project/runs/running-manual-and-automated-tests.md +331 -0
  197. package/skills/testeiya/testomatio-docs/docs/project/runs/running-tests-manually.md +633 -0
  198. package/skills/testeiya/testomatio-docs/docs/project/runs/temporary-tests-notes.md +223 -0
  199. package/skills/testeiya/testomatio-docs/docs/project/steps-snippets/snippets.md +68 -0
  200. package/skills/testeiya/testomatio-docs/docs/project/steps-snippets/steps.md +181 -0
  201. package/skills/testeiya/testomatio-docs/docs/project/tests/bdd-test-case-editor.md +98 -0
  202. package/skills/testeiya/testomatio-docs/docs/project/tests/classical-test-case-editor.md +354 -0
  203. package/skills/testeiya/testomatio-docs/docs/project/tests/classical-vs-bdd.md +169 -0
  204. package/skills/testeiya/testomatio-docs/docs/project/tests/copy-and-move-your-tests.md +156 -0
  205. package/skills/testeiya/testomatio-docs/docs/project/tests/other-features-for-test-case-design.md +412 -0
  206. package/skills/testeiya/testomatio-docs/docs/project/tests/test-case-creation-and-editing.md +527 -0
  207. package/skills/testeiya/testomatio-docs/docs/support/index.md +75 -0
  208. package/skills/testeiya/testomatio-docs/docs/test-reporting/artifacts.md +388 -0
  209. package/skills/testeiya/testomatio-docs/docs/test-reporting/cli.md +215 -0
  210. package/skills/testeiya/testomatio-docs/docs/test-reporting/configuration.md +247 -0
  211. package/skills/testeiya/testomatio-docs/docs/test-reporting/frameworks.md +490 -0
  212. package/skills/testeiya/testomatio-docs/docs/test-reporting/functions.md +144 -0
  213. package/skills/testeiya/testomatio-docs/docs/test-reporting/index.mdx +48 -0
  214. package/skills/testeiya/testomatio-docs/docs/test-reporting/junit.md +248 -0
  215. package/skills/testeiya/testomatio-docs/docs/test-reporting/logger.md +138 -0
  216. package/skills/testeiya/testomatio-docs/docs/test-reporting/php.md +77 -0
  217. package/skills/testeiya/testomatio-docs/docs/test-reporting/pipes/bitbucket.md +72 -0
  218. package/skills/testeiya/testomatio-docs/docs/test-reporting/pipes/csv.md +23 -0
  219. package/skills/testeiya/testomatio-docs/docs/test-reporting/pipes/debug.md +18 -0
  220. package/skills/testeiya/testomatio-docs/docs/test-reporting/pipes/github.md +63 -0
  221. package/skills/testeiya/testomatio-docs/docs/test-reporting/pipes/gitlab.md +29 -0
  222. package/skills/testeiya/testomatio-docs/docs/test-reporting/pipes/html.md +80 -0
  223. package/skills/testeiya/testomatio-docs/docs/test-reporting/pipes/index.mdx +57 -0
  224. package/skills/testeiya/testomatio-docs/docs/test-reporting/pipes/testomatio.md +331 -0
  225. package/skills/testeiya/testomatio-docs/docs/test-reporting/python.md +229 -0
  226. package/skills/testeiya/testomatio-docs/docs/test-reporting/workflows.md +325 -0
  227. package/skills/testeiya/testomatio-docs/docs/tutorials/Interacting-via-API.md +159 -0
  228. package/skills/testeiya/testomatio-docs/docs/tutorials/Manual-Testing-Classic.md +164 -0
  229. package/skills/testeiya/testomatio-docs/docs/tutorials/Set-Up-Read-Only-Access.md +85 -0
  230. package/skills/testeiya/testomatio-docs/docs/tutorials/Using-AI-in-Testing.md +163 -0
  231. package/skills/testeiya/testomatio-docs/docs/tutorials/Working-with-Jira.md +125 -0
  232. package/skills/testeiya/testomatio-docs/docs/tutorials/java.md +478 -0
  233. package/skills/testeiya/testomatio-docs/docs/tutorials/playwright.md +207 -0
  234. package/skills/testeiya/testomatio-docs/docs/tutorials/webdriver.md +218 -0
  235. package/skills/testeiya/testomatio-docs/docs.lock.json +6 -0
  236. package/skills/testeiya/testomatio-reporter/SKILL.md +307 -0
  237. package/skills/testomatio/explorbot/explorbot-fundamentals/SKILL.md +88 -0
  238. package/skills/testomatio/explorbot/explorbot-plan/SKILL.md +95 -0
  239. package/skills/testomatio/explorbot/explorbot-setup/SKILL.md +334 -0
  240. package/skills/testomatio/test-automation/automate-manual-test-cases/CLAUDE.md +56 -0
  241. package/skills/testomatio/test-automation/automate-manual-test-cases/SKILL.md +242 -0
  242. package/skills/testomatio/test-automation/automate-manual-test-cases/references/CODECEPTJS_BEST_PRACTICES.md +182 -0
  243. package/skills/testomatio/test-automation/automate-manual-test-cases/references/FINAL_SUMMARY_TEMPLATE.md +22 -0
  244. package/skills/testomatio/test-automation/automate-manual-test-cases/references/PLAYWRIGHT_BEST_PRACTICES.md +90 -0
  245. package/skills/testomatio/test-automation/automate-manual-test-cases/references/POM_BEST_PRACTICES.md +53 -0
  246. package/skills/testomatio/test-automation/automate-manual-test-cases/references/TEST_DATA_MANAGEMENT.md +52 -0
  247. package/skills/testomatio/test-automation/debug-fix-failed-flaky-autotests/SKILL.md +107 -0
  248. package/skills/testomatio/test-automation/debug-fix-failed-flaky-autotests/references/DEBUGGING_QUICK_REFERENCE.md +113 -0
  249. package/skills/testomatio/test-automation/qa-automation-test-consolidation/SKILL.md +29 -0
  250. package/skills/testomatio/test-automation/run-tests-with-testomatio-reporter/SKILL.md +151 -0
  251. package/skills/testomatio/test-automation/setup-pr-testing/SKILL.md +199 -0
  252. package/skills/testomatio/test-automation/testomat-allure-adapter/SKILL.md +289 -0
  253. package/skills/testomatio/test-management/detect-duplicate-test-cases/SKILL.md +86 -0
  254. package/skills/testomatio/test-management/detect-duplicate-test-cases/references/DUPLICATE_INSTRUCTIONS.md +54 -0
  255. package/skills/testomatio/test-management/improve-test-cases/SKILL.md +114 -0
  256. package/skills/testomatio/test-management/improve-test-cases/references/TESTOMAT_MARKDOWN_EXAMPLE.md +66 -0
  257. package/skills/testomatio/test-management/pull-request-diff-analyzer/SKILL.md +141 -0
  258. package/skills/testomatio/test-management/qa-e2e-tests-reporting/SKILL.md +354 -0
  259. package/skills/testomatio/test-management/qa-e2e-tests-reporting/references/TESTOMATIO_ARTIFACTS.md +82 -0
  260. package/skills/testomatio/test-management/qa-e2e-tests-reporting/references/TESTOMATIO_HTML_REPORT.md +37 -0
  261. package/skills/testomatio/test-management/qa-e2e-tests-reporting/references/TESTOMATIO_REPORTERS_CONFIG.md +118 -0
  262. package/skills/testomatio/test-management/qa-pr-requirements-analyzer/SKILL.md +149 -0
  263. package/skills/testomatio/test-management/qa-pr-requirements-analyzer/references/summary-example.md +54 -0
  264. package/skills/testomatio/test-management/qa-requirement-reviewer/SKILL.md +126 -0
  265. package/skills/testomatio/test-management/qa-requirement-reviewer/references/requirements_reviewer_examples.md +128 -0
  266. package/skills/testomatio/test-management/qa-test-code-coverage/SKILL.md +174 -0
  267. package/skills/testomatio/test-management/qa-test-code-coverage/references/COVERAGE_FILE_FORMAT.md +138 -0
  268. package/skills/testomatio/test-management/qa-test-code-coverage/references/E2E_FRAMEWORKS.md +65 -0
  269. package/skills/testomatio/test-management/qa-test-code-coverage/scripts/check-coverage.mjs +40 -0
  270. package/skills/testomatio/test-management/qa-thinking/SKILL.md +36 -0
  271. package/skills/testomatio/test-management/qa-write-test-cases/SKILL.md +267 -0
  272. package/skills/testomatio/test-management/qa-write-test-cases/references/test-case-format.md +387 -0
  273. package/skills/testomatio/test-management/qa-write-test-cases/references/testomat-tms-guide.md +72 -0
  274. package/skills/testomatio/test-management/qa-write-test-cases/references/writing-rule.md +159 -0
  275. package/skills/testomatio/test-management/scan-automation-project/SKILL.md +152 -0
  276. package/skills/testomatio/test-management/sync-test-cases-with-tms/SKILL.md +107 -0
  277. package/skills/testomatio/test-management/sync-test-cases-with-tms/references/TESTOMATIO_CLI.md +140 -0
  278. package/skills/testomatio/test-management/testomatio-mcp/SKILL.md +182 -0
  279. package/skills/testomatio/test-management/testomatio-mcp/references/MCP_SETUP.md +169 -0
  280. package/skills.lock.json +72 -0
  281. package/skills.yaml +21 -0
  282. package/src/ai-debug.ts +188 -0
  283. package/src/api/agent-get.ts +22 -0
  284. package/src/api/agent-start.ts +384 -0
  285. package/src/api/client-log.ts +29 -0
  286. package/src/api/context.ts +332 -0
  287. package/src/api/debug-layout.ts +47 -0
  288. package/src/api/debug-report.ts +29 -0
  289. package/src/api/debug-snapshot.ts +30 -0
  290. package/src/api/debug-stream.ts +52 -0
  291. package/src/api/files-delete.ts +184 -0
  292. package/src/api/files-read.ts +41 -0
  293. package/src/api/files-rename.ts +99 -0
  294. package/src/api/files-tree.ts +292 -0
  295. package/src/api/files-write.ts +41 -0
  296. package/src/api/mcp.ts +603 -0
  297. package/src/api/memory.ts +69 -0
  298. package/src/api/open-external.ts +39 -0
  299. package/src/api/playwright-cli.ts +606 -0
  300. package/src/api/providers.ts +457 -0
  301. package/src/api/read-env-token.ts +33 -0
  302. package/src/api/sessions.ts +79 -0
  303. package/src/api/settings.ts +120 -0
  304. package/src/api/skills.ts +58 -0
  305. package/src/api/testomatio-attachment.ts +89 -0
  306. package/src/api/testomatio-auth.ts +284 -0
  307. package/src/api/testomatio-proxy.ts +197 -0
  308. package/src/api/testomatio-run-stats.ts +81 -0
  309. package/src/api/testomatio-target.ts +225 -0
  310. package/src/api/testomatio-transcription.ts +82 -0
  311. package/src/api/workspace-search.ts +96 -0
  312. package/src/api/workspace-sync.ts +151 -0
  313. package/src/api/workspace.ts +165 -0
  314. package/src/app-server.ts +556 -0
  315. package/src/bridge.ts +251 -0
  316. package/src/check-tests.ts +156 -0
  317. package/src/cli.ts +17 -0
  318. package/src/commands.ts +244 -0
  319. package/src/config.ts +183 -0
  320. package/src/connection.ts +658 -0
  321. package/src/context-store.ts +265 -0
  322. package/src/debug-bus.ts +405 -0
  323. package/src/extensions/tool-gate.ts +220 -0
  324. package/src/extensions/webui/ask-channel.ts +52 -0
  325. package/src/extensions/webui/index.ts +184 -0
  326. package/src/extensions/webui/tools/ask-question.ts +88 -0
  327. package/src/extensions/webui/tools/query-result.ts +79 -0
  328. package/src/extensions/webui/tools/render-chart.ts +53 -0
  329. package/src/extensions/webui/tools/render-item.ts +61 -0
  330. package/src/extensions/webui/tools/render-list.ts +170 -0
  331. package/src/extensions/webui/tools/render-result.ts +85 -0
  332. package/src/extensions/webui/tools/render-tree.ts +71 -0
  333. package/src/extensions/webui/tools/ui-widget.ts +54 -0
  334. package/src/extensions/webui/tools/widget-result.ts +13 -0
  335. package/src/extensions/webui/widget-channel.ts +50 -0
  336. package/src/file-log.ts +196 -0
  337. package/src/git-tracked.ts +68 -0
  338. package/src/gitignore.ts +53 -0
  339. package/src/json-store.ts +43 -0
  340. package/src/load-env.ts +70 -0
  341. package/src/loader-style.ts +96 -0
  342. package/src/main.ts +140 -0
  343. package/src/mcp-catalog.ts +96 -0
  344. package/src/models-catalog.ts +72 -0
  345. package/src/permissions.ts +120 -0
  346. package/src/project-dir.ts +189 -0
  347. package/src/project-info.ts +108 -0
  348. package/src/prompt/app-ui.ts +59 -0
  349. package/src/prompt/browser.ts +27 -0
  350. package/src/prompt/index.ts +62 -0
  351. package/src/prompt/system-prompt.ts +161 -0
  352. package/src/prompt/testomatio.ts +170 -0
  353. package/src/prompt/tools.ts +27 -0
  354. package/src/server-info.ts +62 -0
  355. package/src/session-factory.ts +442 -0
  356. package/src/session-store.ts +115 -0
  357. package/src/shell-env.ts +45 -0
  358. package/src/skills.ts +163 -0
  359. package/src/sync-snapshot.ts +140 -0
  360. package/src/telemetry.ts +239 -0
  361. package/src/testomatio-auth.ts +299 -0
  362. package/src/testomatio.ts +98 -0
  363. package/src/theme.ts +30 -0
  364. package/src/user-env.ts +94 -0
  365. package/src/welcome.ts +127 -0
  366. package/src/workspace/safe-path.ts +85 -0
  367. package/src/workspace/test-md.ts +70 -0
  368. package/src/workspace-model.ts +440 -0
  369. package/testeiya.config.json +14 -0
package/src/skills.ts ADDED
@@ -0,0 +1,163 @@
1
+ import { join } from "node:path";
2
+ import { readdirSync, readFileSync, existsSync, mkdirSync, writeFileSync } from "node:fs";
3
+ import { createRequire } from "node:module";
4
+ import { parse as parseYaml } from "yaml";
5
+ import dedent from "dedent";
6
+ import type { Skill } from "@oh-my-pi/pi-coding-agent";
7
+ import { CUSTOM_SKILLS_DIR, projectSkillsDir, resolveBundledSkillsDir } from "./project-dir.js";
8
+
9
+ const require = createRequire(import.meta.url);
10
+
11
+ /**
12
+ * Whether the Playwright browser CLI (`@playwright/cli`) is installed. This gates
13
+ * the browser-automation guidance in the system prompt so it's only advertised
14
+ * when the tool is actually present. The `playwright-cli` *skill* is vendored
15
+ * from GitHub (`microsoft/playwright-cli`) like every other prebuilt skill — it
16
+ * is not read from the package.
17
+ */
18
+ export function hasPlaywrightCli(): boolean {
19
+ try {
20
+ require.resolve("@playwright/cli/package.json");
21
+ return true;
22
+ } catch {
23
+ return false;
24
+ }
25
+ }
26
+
27
+ /**
28
+ * The skills tree shipped with the CLI package / desktop bundle, organized by
29
+ * vendor folder: external vendors written by `bunosh skills:update` plus
30
+ * first-party folders authored in this repo (e.g. `testeiya/`). Inside a vendor
31
+ * folder — a root SKILL.md makes the folder one flat skill; a child folder with
32
+ * a SKILL.md is a skill whose `category` is the (prettified) vendor folder; a
33
+ * child folder without one is a category folder whose skill children get that
34
+ * folder as `category`. Source `"bundled"`.
35
+ */
36
+ export function loadBundledSkills(): CategorizedSkill[] {
37
+ const dir = resolveBundledSkillsDir();
38
+ if (!existsSync(dir)) return [];
39
+ const skills: CategorizedSkill[] = [];
40
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
41
+ if (!entry.isDirectory()) continue;
42
+ skills.push(...readVendorDir(join(dir, entry.name), entry.name));
43
+ }
44
+ return skills;
45
+ }
46
+
47
+ /**
48
+ * User-added skills from the global `~/.testeiya/skills` folder and, when a
49
+ * workspace is open, its per-project `<cwd>/.testeiya/skills`. Directory entries
50
+ * that are symlinks are followed so a skill can live in another repo and be
51
+ * linked in. Deduped by name so a per-project or custom skill overrides one from
52
+ * a broader scope.
53
+ */
54
+ export function loadCustomSkills(cwd?: string): CategorizedSkill[] {
55
+ const dirs = [CUSTOM_SKILLS_DIR];
56
+ if (cwd) dirs.push(projectSkillsDir(cwd));
57
+ const skills: CategorizedSkill[] = [];
58
+ for (const dir of dirs) skills.push(...readSkillsDir(dir, "custom"));
59
+ return dedupeSkillsByName(skills);
60
+ }
61
+
62
+ /** Create the global custom-skills folder and seed a README the first time. */
63
+ export function ensureCustomSkillsDir(): string {
64
+ mkdirSync(CUSTOM_SKILLS_DIR, { recursive: true });
65
+ const readme = join(CUSTOM_SKILLS_DIR, "README.md");
66
+ if (!existsSync(readme)) writeFileSync(readme, CUSTOM_SKILLS_README);
67
+ return CUSTOM_SKILLS_DIR;
68
+ }
69
+
70
+ /** Keep one skill per name; the last occurrence wins. */
71
+ export function dedupeSkillsByName<T extends Skill>(skills: T[]): T[] {
72
+ const byName = new Map<string, T>();
73
+ for (const skill of skills) byName.set(skill.name, skill);
74
+ return [...byName.values()];
75
+ }
76
+
77
+ /** One vendor folder of the bundled tree — see `loadBundledSkills` for the layout. */
78
+ function readVendorDir(vendorDir: string, vendorName: string): CategorizedSkill[] {
79
+ const vendorCategory = prettifyCategory(vendorName);
80
+ const single = readSkill(vendorDir, vendorName, "bundled");
81
+ if (single) {
82
+ single.category = vendorCategory;
83
+ return [single];
84
+ }
85
+ const skills: CategorizedSkill[] = [];
86
+ for (const entry of readdirSync(vendorDir, { withFileTypes: true })) {
87
+ if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
88
+ const entryDir = join(vendorDir, entry.name);
89
+ const skill = readSkill(entryDir, entry.name, "bundled");
90
+ if (skill) {
91
+ skill.category = vendorCategory;
92
+ skills.push(skill);
93
+ continue;
94
+ }
95
+ for (const nested of readSkillsDir(entryDir, "bundled")) {
96
+ nested.category = prettifyCategory(entry.name);
97
+ skills.push(nested);
98
+ }
99
+ }
100
+ return skills;
101
+ }
102
+
103
+ /**
104
+ * Scan one flat skills folder: every child directory that holds a `SKILL.md` is
105
+ * a skill (symlinks are followed, so a skill can be linked in). Entries without
106
+ * a `SKILL.md` are ignored. Used per-category for the vendored bundle, and for
107
+ * the (flat) user skills dirs.
108
+ */
109
+ function readSkillsDir(dir: string, source: string): CategorizedSkill[] {
110
+ if (!existsSync(dir)) return [];
111
+ const skills: CategorizedSkill[] = [];
112
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
113
+ if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
114
+ const skill = readSkill(join(dir, entry.name), entry.name, source);
115
+ if (skill) skills.push(skill);
116
+ }
117
+ return skills;
118
+ }
119
+
120
+ /** Turn a category folder slug (`test-management`) into a label (`Test Management`). */
121
+ function prettifyCategory(folder: string): string {
122
+ return folder
123
+ .split(/[-_\s]+/)
124
+ .filter(Boolean)
125
+ .map((word) => word[0].toUpperCase() + word.slice(1))
126
+ .join(" ");
127
+ }
128
+
129
+ function readSkill(skillDir: string, fallbackName: string, source: string): CategorizedSkill | null {
130
+ const skillFile = join(skillDir, "SKILL.md");
131
+ if (!existsSync(skillFile)) return null;
132
+ const content = readFileSync(skillFile, "utf-8");
133
+ const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
134
+ const fm = fmMatch ? parseYaml(fmMatch[1]) : null;
135
+ const fmName = fm?.name?.toString().trim();
136
+ // A skill name is used as a mention token, so it must be a slug; fall back to
137
+ // the folder name when the frontmatter name isn't one (e.g. a spaced title).
138
+ const name = fmName && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(fmName) ? fmName : fallbackName;
139
+ const description = fm?.description?.toString().trim() || "";
140
+ return { name, description, filePath: skillFile, baseDir: skillDir, source };
141
+ }
142
+
143
+ const CUSTOM_SKILLS_README = dedent`
144
+ # Testeiya custom skills
145
+
146
+ Drop a skill here to make it available to the agent. A skill is a folder that
147
+ contains a \`SKILL.md\` file — YAML frontmatter with a \`name\` and
148
+ \`description\`, followed by the skill's instructions:
149
+
150
+ ~/.testeiya/skills/my-skill/SKILL.md
151
+
152
+ You can also symlink a skill that already lives in another repository:
153
+
154
+ ln -s /path/to/repo/skills/my-skill ~/.testeiya/skills/my-skill
155
+
156
+ After adding or linking a skill, click **Refresh** in the Skills menu.
157
+
158
+ Skills placed here are available in every workspace. To scope a skill to a
159
+ single project, put it in that workspace's \`.testeiya/skills/\` folder instead.
160
+ ` + "\n";
161
+
162
+ /** An SDK `Skill` plus the category folder it was discovered under, if any. */
163
+ export type CategorizedSkill = Skill & { category?: string };
@@ -0,0 +1,140 @@
1
+ // Tracks which manual-test files changed since the last Testomat.io sync.
2
+ //
3
+ // After every successful `check-tests` pull/push the synced files are
4
+ // content-hashed into `.testeiya/sync-snapshot.json` (the baseline = the state
5
+ // the remote agrees with). The file tree then diffs the current files against
6
+ // that baseline so a created/edited-but-not-pushed file can be flagged.
7
+
8
+ import crypto from "node:crypto";
9
+ import fs from "node:fs";
10
+ import path from "node:path";
11
+ import { readJson, writeJson } from "./json-store.js";
12
+ import { resolveManualTestsDir, VENDOR_DIRS } from "./workspace-model.js";
13
+ import { syncSnapshotPath } from "./project-dir.js";
14
+
15
+ const TEST_MD_RE = /\.test\.md$/i;
16
+ const MAX_FILES = 5000;
17
+
18
+ /**
19
+ * Snapshot the manual-test files `check-tests` just synced. `syncedDir` is the
20
+ * dir it ran in, relative to `cwd` (`"."` for a root project). Only that subtree
21
+ * is re-hashed, so multi-project workspaces (one snapshot, many synced subdirs)
22
+ * keep each other's entries.
23
+ *
24
+ * `onlyFiles` (cwd-relative paths) scopes a *partial* sync: a push/pull of a
25
+ * single suite or just the changed files re-baselines only those files, so the
26
+ * other un-pushed files keep their "changed" markers.
27
+ */
28
+ export function writeSyncSnapshot(cwd: string, syncedDir: string, onlyFiles?: string[]): void {
29
+ const snapshot = readJson<SyncSnapshot>(syncSnapshotPath(cwd), emptySnapshot());
30
+ if (onlyFiles) {
31
+ for (const rel of onlyFiles) {
32
+ const hash = hashFile(path.resolve(cwd, rel));
33
+ if (hash) snapshot.files[rel] = hash;
34
+ else delete snapshot.files[rel];
35
+ }
36
+ snapshot.syncedAt = new Date().toISOString();
37
+ writeJson(syncSnapshotPath(cwd), snapshot);
38
+ return;
39
+ }
40
+ const base = syncedDir === "." ? "" : syncedDir;
41
+ for (const key of Object.keys(snapshot.files)) {
42
+ if (isUnder(key, base)) delete snapshot.files[key];
43
+ }
44
+ hashDir(path.resolve(cwd, base), base, snapshot.files, { count: 0 });
45
+ snapshot.syncedAt = new Date().toISOString();
46
+ writeJson(syncSnapshotPath(cwd), snapshot);
47
+ }
48
+
49
+ /**
50
+ * Establish a baseline if the workspace has manual tests but never recorded one
51
+ * (e.g. a folder opened without a sync, or pulled before tracking existed). The
52
+ * current state becomes "the last synced state", so edits from now on are
53
+ * detected without forcing the user to push first.
54
+ */
55
+ export function ensureSyncBaseline(cwd: string): void {
56
+ const manualDir = resolveManualTestsDir(cwd);
57
+ if (manualDir === null) return;
58
+ if (fs.existsSync(syncSnapshotPath(cwd))) return;
59
+ writeSyncSnapshot(cwd, manualDir === "" ? "." : manualDir);
60
+ }
61
+
62
+ /**
63
+ * Map of `cwd`-relative path → status for manual-test files that differ from the
64
+ * last sync. Empty when nothing is loaded or no snapshot exists yet (so a
65
+ * freshly pulled workspace shows clean rather than lighting up entirely).
66
+ */
67
+ export function computeChangedFiles(cwd: string): Record<string, FileStatus> {
68
+ const manualDir = resolveManualTestsDir(cwd);
69
+ if (manualDir === null) return {};
70
+ const snapshot = readJson<SyncSnapshot | null>(syncSnapshotPath(cwd), null);
71
+ if (!snapshot) return {};
72
+
73
+ const current: Record<string, string> = {};
74
+ hashDir(path.resolve(cwd, manualDir), manualDir, current, { count: 0 });
75
+
76
+ const changed: Record<string, FileStatus> = {};
77
+ for (const rel of Object.keys(current)) {
78
+ const before = snapshot.files[rel];
79
+ if (!before) {
80
+ changed[rel] = "created";
81
+ continue;
82
+ }
83
+ if (before !== current[rel]) changed[rel] = "changed";
84
+ }
85
+ return changed;
86
+ }
87
+
88
+ function hashDir(
89
+ absDir: string,
90
+ relDir: string,
91
+ out: Record<string, string>,
92
+ state: { count: number }
93
+ ): void {
94
+ if (state.count >= MAX_FILES) return;
95
+ let entries: fs.Dirent[];
96
+ try {
97
+ entries = fs.readdirSync(absDir, { withFileTypes: true });
98
+ } catch {
99
+ return;
100
+ }
101
+ for (const entry of entries) {
102
+ if (state.count >= MAX_FILES) return;
103
+ if (entry.name.startsWith(".") || VENDOR_DIRS.has(entry.name)) continue;
104
+ const childAbs = path.join(absDir, entry.name);
105
+ const childRel = relDir ? `${relDir}/${entry.name}` : entry.name;
106
+ if (entry.isDirectory()) {
107
+ hashDir(childAbs, childRel, out, state);
108
+ continue;
109
+ }
110
+ if (!entry.isFile() || !TEST_MD_RE.test(entry.name)) continue;
111
+ const hash = hashFile(childAbs);
112
+ if (!hash) continue;
113
+ out[childRel] = hash;
114
+ state.count++;
115
+ }
116
+ }
117
+
118
+ function hashFile(absFile: string): string | null {
119
+ try {
120
+ return crypto.createHash("sha1").update(fs.readFileSync(absFile)).digest("hex");
121
+ } catch {
122
+ return null;
123
+ }
124
+ }
125
+
126
+ function isUnder(key: string, base: string): boolean {
127
+ if (base === "") return true;
128
+ return key === base || key.startsWith(`${base}/`);
129
+ }
130
+
131
+ function emptySnapshot(): SyncSnapshot {
132
+ return { syncedAt: "", files: {} };
133
+ }
134
+
135
+ export type FileStatus = "created" | "changed";
136
+
137
+ interface SyncSnapshot {
138
+ syncedAt: string;
139
+ files: Record<string, string>;
140
+ }
@@ -0,0 +1,239 @@
1
+ // OpenTelemetry → Langfuse observability for the agent.
2
+ //
3
+ // Two parts:
4
+ // 1. initTelemetry() — one-time NodeSDK + LangfuseSpanProcessor bootstrap,
5
+ // gated on LANGFUSE_PUBLIC_KEY + LANGFUSE_SECRET_KEY. A no-op (and no
6
+ // dependency cost at runtime) when the keys are absent. Called from
7
+ // app-server.ts right after the .env files are loaded.
8
+ // 2. createTelemetryExtension() — a per-session extension that turns the
9
+ // agent's hook events into a Langfuse trace tree:
10
+ // before_agent_start → root (agent) observation = one trace per prompt
11
+ // message_start/_end → child generation (LLM call) with usage + cost
12
+ // tool_execution_start/_end → child tool observation (args + result)
13
+ // agent_end → close the trace and flush
14
+ // All prompts of one agent session share the SDK sessionId, so Langfuse
15
+ // groups them into a single session.
16
+
17
+ import { NodeSDK } from "@opentelemetry/sdk-node";
18
+ import { LangfuseSpanProcessor } from "@langfuse/otel";
19
+ import { startObservation, LangfuseOtelSpanAttributes } from "@langfuse/tracing";
20
+ import type {
21
+ LangfuseAgent,
22
+ LangfuseGeneration,
23
+ LangfuseTool,
24
+ ObservationLevel,
25
+ } from "@langfuse/tracing";
26
+ import type { ExtensionFactory } from "@oh-my-pi/pi-coding-agent";
27
+
28
+ let processor: LangfuseSpanProcessor | undefined;
29
+ let sdk: NodeSDK | undefined;
30
+ let enabled = false;
31
+
32
+ export function initTelemetry(): void {
33
+ if (sdk) return;
34
+
35
+ const publicKey = process.env.LANGFUSE_PUBLIC_KEY;
36
+ const secretKey = process.env.LANGFUSE_SECRET_KEY;
37
+ if (!publicKey || !secretKey) {
38
+ console.log(
39
+ "[telemetry] Langfuse disabled — set LANGFUSE_PUBLIC_KEY + LANGFUSE_SECRET_KEY to enable",
40
+ );
41
+ return;
42
+ }
43
+
44
+ const baseUrl = process.env.LANGFUSE_BASE_URL ?? process.env.LANGFUSE_BASEURL;
45
+ processor = new LangfuseSpanProcessor({ publicKey, secretKey, baseUrl });
46
+ sdk = new NodeSDK({ spanProcessors: [processor] });
47
+ sdk.start();
48
+ enabled = true;
49
+ console.log(`[telemetry] Langfuse enabled → ${baseUrl ?? "https://cloud.langfuse.com"}`);
50
+ }
51
+
52
+ export function isTelemetryEnabled(): boolean {
53
+ return enabled;
54
+ }
55
+
56
+ export async function flushTelemetry(): Promise<void> {
57
+ if (!processor) return;
58
+ try {
59
+ await processor.forceFlush();
60
+ } catch (err) {
61
+ console.error(
62
+ "[telemetry] flush failed:",
63
+ err instanceof Error ? err.message : err,
64
+ );
65
+ }
66
+ }
67
+
68
+ export function createTelemetryExtension(meta: TelemetryMeta): ExtensionFactory {
69
+ return ((pi: any) => {
70
+ let root: LangfuseAgent | undefined;
71
+ let generation: LangfuseGeneration | undefined;
72
+ let contextMessages: unknown;
73
+ const tools = new Map<string, LangfuseTool>();
74
+
75
+ pi.on("before_agent_start", (event: any, ctx: any) => {
76
+ if (root) endTrace();
77
+ const prompt = event?.prompt ?? "";
78
+ const name = traceName(prompt);
79
+ root = startObservation(name, { input: prompt }, { asType: "agent" });
80
+ root.update({
81
+ metadata: {
82
+ cwd: meta.cwd,
83
+ model: meta.modelId,
84
+ provider: meta.provider,
85
+ projectIds: meta.projectIds,
86
+ },
87
+ });
88
+ const span = root.otelSpan;
89
+ span.setAttribute(LangfuseOtelSpanAttributes.TRACE_NAME, name);
90
+ span.setAttribute(LangfuseOtelSpanAttributes.TRACE_INPUT, serialize(prompt));
91
+ span.setAttribute(
92
+ LangfuseOtelSpanAttributes.TRACE_TAGS,
93
+ JSON.stringify(["testeiya", meta.mode]),
94
+ );
95
+ const sessionId = ctx?.sessionManager?.getSessionId?.();
96
+ if (sessionId) {
97
+ span.setAttribute(LangfuseOtelSpanAttributes.TRACE_SESSION_ID, sessionId);
98
+ }
99
+ });
100
+
101
+ pi.on("context", (event: any) => {
102
+ contextMessages = event?.messages;
103
+ });
104
+
105
+ pi.on("message_start", (event: any) => {
106
+ if (!root) return;
107
+ if (event?.message?.role !== "assistant") return;
108
+ generation = root.startObservation(
109
+ "llm-generation",
110
+ { input: contextMessages ?? [], model: meta.modelId },
111
+ { asType: "generation" },
112
+ );
113
+ });
114
+
115
+ pi.on("message_end", (event: any) => {
116
+ const msg = event?.message;
117
+ if (!generation || msg?.role !== "assistant") return;
118
+ generation.update({
119
+ model: msg.model ?? meta.modelId,
120
+ output: msg.content,
121
+ usageDetails: usageDetails(msg.usage),
122
+ costDetails: costDetails(msg.usage),
123
+ });
124
+ generation.end();
125
+ generation = undefined;
126
+ });
127
+
128
+ pi.on("tool_execution_start", (event: any) => {
129
+ if (!root) return;
130
+ const name = event?.toolName ?? "tool";
131
+ tools.set(
132
+ event.toolCallId,
133
+ root.startObservation(
134
+ name,
135
+ { input: event?.args, metadata: { toolName: name, intent: event?.intent } },
136
+ { asType: "tool" },
137
+ ),
138
+ );
139
+ });
140
+
141
+ pi.on("tool_execution_end", (event: any) => {
142
+ const span = tools.get(event?.toolCallId);
143
+ if (!span) return;
144
+ let level: ObservationLevel = "DEFAULT";
145
+ if (event?.isError) level = "ERROR";
146
+ span.update({ output: event?.result, level });
147
+ span.end();
148
+ tools.delete(event.toolCallId);
149
+ });
150
+
151
+ pi.on("agent_end", (event: any) => {
152
+ if (!root) return;
153
+ const output = finalText(event?.messages);
154
+ root.otelSpan.setAttribute(
155
+ LangfuseOtelSpanAttributes.TRACE_OUTPUT,
156
+ serialize(output),
157
+ );
158
+ root.update({ output });
159
+ endTrace();
160
+ void flushTelemetry();
161
+ });
162
+
163
+ function endTrace(): void {
164
+ for (const span of tools.values()) span.end();
165
+ tools.clear();
166
+ if (generation) {
167
+ generation.end();
168
+ generation = undefined;
169
+ }
170
+ if (root) {
171
+ root.end();
172
+ root = undefined;
173
+ }
174
+ }
175
+ }) as ExtensionFactory;
176
+ }
177
+
178
+ function usageDetails(usage: any): Record<string, number> | undefined {
179
+ if (!usage) return undefined;
180
+ return {
181
+ input: usage.input,
182
+ output: usage.output,
183
+ cache_read_input_tokens: usage.cacheRead,
184
+ cache_creation_input_tokens: usage.cacheWrite,
185
+ total: usage.totalTokens,
186
+ };
187
+ }
188
+
189
+ function costDetails(usage: any): Record<string, number> | undefined {
190
+ if (!usage?.cost) return undefined;
191
+ return {
192
+ input: usage.cost.input,
193
+ output: usage.cost.output,
194
+ total: usage.cost.total,
195
+ };
196
+ }
197
+
198
+ function finalText(messages: any): string | undefined {
199
+ if (!Array.isArray(messages)) return undefined;
200
+ for (let i = messages.length - 1; i >= 0; i--) {
201
+ if (messages[i]?.role === "assistant") return textOf(messages[i].content);
202
+ }
203
+ return undefined;
204
+ }
205
+
206
+ function textOf(content: any): string | undefined {
207
+ if (typeof content === "string") return content;
208
+ if (!Array.isArray(content)) return undefined;
209
+ return content
210
+ .filter((c) => c?.type === "text")
211
+ .map((c) => c.text)
212
+ .join("\n");
213
+ }
214
+
215
+ function traceName(prompt: unknown): string {
216
+ let text = "";
217
+ if (typeof prompt === "string") text = prompt;
218
+ const firstLine = text.split("\n")[0]?.trim() ?? "";
219
+ if (!firstLine) return "agent-run";
220
+ if (firstLine.length <= 60) return firstLine;
221
+ return `${firstLine.slice(0, 60)}…`;
222
+ }
223
+
224
+ function serialize(value: unknown): string {
225
+ if (typeof value === "string") return value;
226
+ try {
227
+ return JSON.stringify(value) ?? "";
228
+ } catch {
229
+ return String(value);
230
+ }
231
+ }
232
+
233
+ interface TelemetryMeta {
234
+ cwd: string;
235
+ mode: string;
236
+ modelId?: string;
237
+ provider?: string;
238
+ projectIds?: string[];
239
+ }