prose-qa 0.1.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/LICENSE +21 -0
- package/README.md +570 -0
- package/dist/agent/bash.d.ts +52 -0
- package/dist/agent/bash.d.ts.map +1 -0
- package/dist/agent/bash.js +186 -0
- package/dist/agent/bash.js.map +1 -0
- package/dist/agent/bash.test.d.ts +2 -0
- package/dist/agent/bash.test.d.ts.map +1 -0
- package/dist/agent/bash.test.js +70 -0
- package/dist/agent/bash.test.js.map +1 -0
- package/dist/agent/llm-model.d.ts +5 -0
- package/dist/agent/llm-model.d.ts.map +1 -0
- package/dist/agent/llm-model.js +29 -0
- package/dist/agent/llm-model.js.map +1 -0
- package/dist/agent/llm-model.test.d.ts +2 -0
- package/dist/agent/llm-model.test.d.ts.map +1 -0
- package/dist/agent/llm-model.test.js +28 -0
- package/dist/agent/llm-model.test.js.map +1 -0
- package/dist/agent/prompt.d.ts +17 -0
- package/dist/agent/prompt.d.ts.map +1 -0
- package/dist/agent/prompt.js +97 -0
- package/dist/agent/prompt.js.map +1 -0
- package/dist/agent/prompt.test.d.ts +2 -0
- package/dist/agent/prompt.test.d.ts.map +1 -0
- package/dist/agent/prompt.test.js +124 -0
- package/dist/agent/prompt.test.js.map +1 -0
- package/dist/agent/provider-options.d.ts +8 -0
- package/dist/agent/provider-options.d.ts.map +1 -0
- package/dist/agent/provider-options.js +115 -0
- package/dist/agent/provider-options.js.map +1 -0
- package/dist/agent/provider-options.test.d.ts +2 -0
- package/dist/agent/provider-options.test.d.ts.map +1 -0
- package/dist/agent/provider-options.test.js +114 -0
- package/dist/agent/provider-options.test.js.map +1 -0
- package/dist/agent/runner.d.ts +27 -0
- package/dist/agent/runner.d.ts.map +1 -0
- package/dist/agent/runner.js +291 -0
- package/dist/agent/runner.js.map +1 -0
- package/dist/agent/verdict-retry-prompt.d.ts +3 -0
- package/dist/agent/verdict-retry-prompt.d.ts.map +1 -0
- package/dist/agent/verdict-retry-prompt.js +18 -0
- package/dist/agent/verdict-retry-prompt.js.map +1 -0
- package/dist/agent/verdict-retry-prompt.test.d.ts +2 -0
- package/dist/agent/verdict-retry-prompt.test.d.ts.map +1 -0
- package/dist/agent/verdict-retry-prompt.test.js +25 -0
- package/dist/agent/verdict-retry-prompt.test.js.map +1 -0
- package/dist/agent/verdict.d.ts +31 -0
- package/dist/agent/verdict.d.ts.map +1 -0
- package/dist/agent/verdict.js +123 -0
- package/dist/agent/verdict.js.map +1 -0
- package/dist/agent/verdict.test.d.ts +2 -0
- package/dist/agent/verdict.test.d.ts.map +1 -0
- package/dist/agent/verdict.test.js +156 -0
- package/dist/agent/verdict.test.js.map +1 -0
- package/dist/analyze/build-context.d.ts +58 -0
- package/dist/analyze/build-context.d.ts.map +1 -0
- package/dist/analyze/build-context.js +141 -0
- package/dist/analyze/build-context.js.map +1 -0
- package/dist/analyze/build-context.test.d.ts +2 -0
- package/dist/analyze/build-context.test.d.ts.map +1 -0
- package/dist/analyze/build-context.test.js +118 -0
- package/dist/analyze/build-context.test.js.map +1 -0
- package/dist/analyze/compare-runs.d.ts +49 -0
- package/dist/analyze/compare-runs.d.ts.map +1 -0
- package/dist/analyze/compare-runs.js +214 -0
- package/dist/analyze/compare-runs.js.map +1 -0
- package/dist/analyze/compare-runs.test.d.ts +2 -0
- package/dist/analyze/compare-runs.test.d.ts.map +1 -0
- package/dist/analyze/compare-runs.test.js +139 -0
- package/dist/analyze/compare-runs.test.js.map +1 -0
- package/dist/analyze/diff-hunks.d.ts +16 -0
- package/dist/analyze/diff-hunks.d.ts.map +1 -0
- package/dist/analyze/diff-hunks.js +287 -0
- package/dist/analyze/diff-hunks.js.map +1 -0
- package/dist/analyze/diff-hunks.test.d.ts +2 -0
- package/dist/analyze/diff-hunks.test.d.ts.map +1 -0
- package/dist/analyze/diff-hunks.test.js +54 -0
- package/dist/analyze/diff-hunks.test.js.map +1 -0
- package/dist/analyze/hunk-editor.d.ts +8 -0
- package/dist/analyze/hunk-editor.d.ts.map +1 -0
- package/dist/analyze/hunk-editor.js +129 -0
- package/dist/analyze/hunk-editor.js.map +1 -0
- package/dist/analyze/hunk-editor.test.d.ts +2 -0
- package/dist/analyze/hunk-editor.test.d.ts.map +1 -0
- package/dist/analyze/hunk-editor.test.js +48 -0
- package/dist/analyze/hunk-editor.test.js.map +1 -0
- package/dist/analyze/index.d.ts +23 -0
- package/dist/analyze/index.d.ts.map +1 -0
- package/dist/analyze/index.js +122 -0
- package/dist/analyze/index.js.map +1 -0
- package/dist/analyze/llm-fix.d.ts +11 -0
- package/dist/analyze/llm-fix.d.ts.map +1 -0
- package/dist/analyze/llm-fix.js +76 -0
- package/dist/analyze/llm-fix.js.map +1 -0
- package/dist/analyze/parse-proposal.d.ts +41 -0
- package/dist/analyze/parse-proposal.d.ts.map +1 -0
- package/dist/analyze/parse-proposal.js +53 -0
- package/dist/analyze/parse-proposal.js.map +1 -0
- package/dist/analyze/parse-proposal.test.d.ts +2 -0
- package/dist/analyze/parse-proposal.test.d.ts.map +1 -0
- package/dist/analyze/parse-proposal.test.js +40 -0
- package/dist/analyze/parse-proposal.test.js.map +1 -0
- package/dist/analyze/repl.d.ts +28 -0
- package/dist/analyze/repl.d.ts.map +1 -0
- package/dist/analyze/repl.js +284 -0
- package/dist/analyze/repl.js.map +1 -0
- package/dist/analyze/repl.test.d.ts +2 -0
- package/dist/analyze/repl.test.d.ts.map +1 -0
- package/dist/analyze/repl.test.js +101 -0
- package/dist/analyze/repl.test.js.map +1 -0
- package/dist/analyze/suggest.d.ts +5 -0
- package/dist/analyze/suggest.d.ts.map +1 -0
- package/dist/analyze/suggest.js +75 -0
- package/dist/analyze/suggest.js.map +1 -0
- package/dist/analyze/suggest.test.d.ts +2 -0
- package/dist/analyze/suggest.test.d.ts.map +1 -0
- package/dist/analyze/suggest.test.js +53 -0
- package/dist/analyze/suggest.test.js.map +1 -0
- package/dist/analyze/validate-markdown.d.ts +3 -0
- package/dist/analyze/validate-markdown.d.ts.map +1 -0
- package/dist/analyze/validate-markdown.js +25 -0
- package/dist/analyze/validate-markdown.js.map +1 -0
- package/dist/artifacts/policy.d.ts +9 -0
- package/dist/artifacts/policy.d.ts.map +1 -0
- package/dist/artifacts/policy.js +46 -0
- package/dist/artifacts/policy.js.map +1 -0
- package/dist/artifacts/policy.test.d.ts +2 -0
- package/dist/artifacts/policy.test.d.ts.map +1 -0
- package/dist/artifacts/policy.test.js +73 -0
- package/dist/artifacts/policy.test.js.map +1 -0
- package/dist/auth/resolve.d.ts +22 -0
- package/dist/auth/resolve.d.ts.map +1 -0
- package/dist/auth/resolve.js +148 -0
- package/dist/auth/resolve.js.map +1 -0
- package/dist/auth/store.d.ts +23 -0
- package/dist/auth/store.d.ts.map +1 -0
- package/dist/auth/store.js +103 -0
- package/dist/auth/store.js.map +1 -0
- package/dist/cache/generate.d.ts +8 -0
- package/dist/cache/generate.d.ts.map +1 -0
- package/dist/cache/generate.js +61 -0
- package/dist/cache/generate.js.map +1 -0
- package/dist/cache/hash.d.ts +5 -0
- package/dist/cache/hash.d.ts.map +1 -0
- package/dist/cache/hash.js +21 -0
- package/dist/cache/hash.js.map +1 -0
- package/dist/cache/hash.test.d.ts +2 -0
- package/dist/cache/hash.test.d.ts.map +1 -0
- package/dist/cache/hash.test.js +42 -0
- package/dist/cache/hash.test.js.map +1 -0
- package/dist/cache/resolve.d.ts +5 -0
- package/dist/cache/resolve.d.ts.map +1 -0
- package/dist/cache/resolve.js +8 -0
- package/dist/cache/resolve.js.map +1 -0
- package/dist/cache/store.d.ts +20 -0
- package/dist/cache/store.d.ts.map +1 -0
- package/dist/cache/store.js +90 -0
- package/dist/cache/store.js.map +1 -0
- package/dist/cache/store.test.d.ts +2 -0
- package/dist/cache/store.test.d.ts.map +1 -0
- package/dist/cache/store.test.js +101 -0
- package/dist/cache/store.test.js.map +1 -0
- package/dist/cli/analyze.d.ts +21 -0
- package/dist/cli/analyze.d.ts.map +1 -0
- package/dist/cli/analyze.js +148 -0
- package/dist/cli/analyze.js.map +1 -0
- package/dist/cli/concurrency.d.ts +17 -0
- package/dist/cli/concurrency.d.ts.map +1 -0
- package/dist/cli/concurrency.js +56 -0
- package/dist/cli/concurrency.js.map +1 -0
- package/dist/cli/concurrency.test.d.ts +2 -0
- package/dist/cli/concurrency.test.d.ts.map +1 -0
- package/dist/cli/concurrency.test.js +74 -0
- package/dist/cli/concurrency.test.js.map +1 -0
- package/dist/cli/config.d.ts +2 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +14 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/help.d.ts +23 -0
- package/dist/cli/help.d.ts.map +1 -0
- package/dist/cli/help.js +458 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/help.test.d.ts +2 -0
- package/dist/cli/help.test.d.ts.map +1 -0
- package/dist/cli/help.test.js +41 -0
- package/dist/cli/help.test.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +300 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/mcp.d.ts +6 -0
- package/dist/cli/mcp.d.ts.map +1 -0
- package/dist/cli/mcp.js +17 -0
- package/dist/cli/mcp.js.map +1 -0
- package/dist/cli/record.d.ts +27 -0
- package/dist/cli/record.d.ts.map +1 -0
- package/dist/cli/record.js +244 -0
- package/dist/cli/record.js.map +1 -0
- package/dist/cli/run.d.ts +11 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +676 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/subprocess.d.ts +19 -0
- package/dist/cli/subprocess.d.ts.map +1 -0
- package/dist/cli/subprocess.js +142 -0
- package/dist/cli/subprocess.js.map +1 -0
- package/dist/cli/subprocess.test.d.ts +2 -0
- package/dist/cli/subprocess.test.d.ts.map +1 -0
- package/dist/cli/subprocess.test.js +76 -0
- package/dist/cli/subprocess.test.js.map +1 -0
- package/dist/cli/tags.d.ts +5 -0
- package/dist/cli/tags.d.ts.map +1 -0
- package/dist/cli/tags.js +33 -0
- package/dist/cli/tags.js.map +1 -0
- package/dist/cli/tags.test.d.ts +2 -0
- package/dist/cli/tags.test.d.ts.map +1 -0
- package/dist/cli/tags.test.js +31 -0
- package/dist/cli/tags.test.js.map +1 -0
- package/dist/config/env-vars.d.ts +2 -0
- package/dist/config/env-vars.d.ts.map +1 -0
- package/dist/config/env-vars.js +14 -0
- package/dist/config/env-vars.js.map +1 -0
- package/dist/config/env.d.ts +2 -0
- package/dist/config/env.d.ts.map +1 -0
- package/dist/config/env.js +9 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/lightpanda.d.ts +6 -0
- package/dist/config/lightpanda.d.ts.map +1 -0
- package/dist/config/lightpanda.js +38 -0
- package/dist/config/lightpanda.js.map +1 -0
- package/dist/config/lightpanda.test.d.ts +2 -0
- package/dist/config/lightpanda.test.d.ts.map +1 -0
- package/dist/config/lightpanda.test.js +46 -0
- package/dist/config/lightpanda.test.js.map +1 -0
- package/dist/config/load.d.ts +22 -0
- package/dist/config/load.d.ts.map +1 -0
- package/dist/config/load.js +242 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/load.test.d.ts +2 -0
- package/dist/config/load.test.d.ts.map +1 -0
- package/dist/config/load.test.js +86 -0
- package/dist/config/load.test.js.map +1 -0
- package/dist/config/set.d.ts +8 -0
- package/dist/config/set.d.ts.map +1 -0
- package/dist/config/set.js +93 -0
- package/dist/config/set.js.map +1 -0
- package/dist/config/set.test.d.ts +2 -0
- package/dist/config/set.test.d.ts.map +1 -0
- package/dist/config/set.test.js +98 -0
- package/dist/config/set.test.js.map +1 -0
- package/dist/healing/classify.d.ts +15 -0
- package/dist/healing/classify.d.ts.map +1 -0
- package/dist/healing/classify.js +209 -0
- package/dist/healing/classify.js.map +1 -0
- package/dist/healing/classify.test.d.ts +2 -0
- package/dist/healing/classify.test.d.ts.map +1 -0
- package/dist/healing/classify.test.js +167 -0
- package/dist/healing/classify.test.js.map +1 -0
- package/dist/healing/recovery-prompt.d.ts +3 -0
- package/dist/healing/recovery-prompt.d.ts.map +1 -0
- package/dist/healing/recovery-prompt.js +22 -0
- package/dist/healing/recovery-prompt.js.map +1 -0
- package/dist/mcp/inline-scenario.d.ts +13 -0
- package/dist/mcp/inline-scenario.d.ts.map +1 -0
- package/dist/mcp/inline-scenario.js +23 -0
- package/dist/mcp/inline-scenario.js.map +1 -0
- package/dist/mcp/server.d.ts +4 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +186 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/skill.d.ts +5 -0
- package/dist/mcp/skill.d.ts.map +1 -0
- package/dist/mcp/skill.js +38 -0
- package/dist/mcp/skill.js.map +1 -0
- package/dist/mcp/skill.test.d.ts +2 -0
- package/dist/mcp/skill.test.d.ts.map +1 -0
- package/dist/mcp/skill.test.js +18 -0
- package/dist/mcp/skill.test.js.map +1 -0
- package/dist/paths.d.ts +12 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +61 -0
- package/dist/paths.js.map +1 -0
- package/dist/prompt/load.d.ts +4 -0
- package/dist/prompt/load.d.ts.map +1 -0
- package/dist/prompt/load.js +19 -0
- package/dist/prompt/load.js.map +1 -0
- package/dist/recorder/bridge-process.d.ts +14 -0
- package/dist/recorder/bridge-process.d.ts.map +1 -0
- package/dist/recorder/bridge-process.js +133 -0
- package/dist/recorder/bridge-process.js.map +1 -0
- package/dist/recorder/bridge-process.test.d.ts +2 -0
- package/dist/recorder/bridge-process.test.d.ts.map +1 -0
- package/dist/recorder/bridge-process.test.js +36 -0
- package/dist/recorder/bridge-process.test.js.map +1 -0
- package/dist/recorder/bridge-worker.d.ts +2 -0
- package/dist/recorder/bridge-worker.d.ts.map +1 -0
- package/dist/recorder/bridge-worker.js +76 -0
- package/dist/recorder/bridge-worker.js.map +1 -0
- package/dist/recorder/bridge.d.ts +12 -0
- package/dist/recorder/bridge.d.ts.map +1 -0
- package/dist/recorder/bridge.js +61 -0
- package/dist/recorder/bridge.js.map +1 -0
- package/dist/recorder/bridge.test.d.ts +2 -0
- package/dist/recorder/bridge.test.d.ts.map +1 -0
- package/dist/recorder/bridge.test.js +21 -0
- package/dist/recorder/bridge.test.js.map +1 -0
- package/dist/recorder/enrich-event.d.ts +31 -0
- package/dist/recorder/enrich-event.d.ts.map +1 -0
- package/dist/recorder/enrich-event.js +91 -0
- package/dist/recorder/enrich-event.js.map +1 -0
- package/dist/recorder/events.d.ts +11 -0
- package/dist/recorder/events.d.ts.map +1 -0
- package/dist/recorder/events.js +42 -0
- package/dist/recorder/events.js.map +1 -0
- package/dist/recorder/events.test.d.ts +2 -0
- package/dist/recorder/events.test.d.ts.map +1 -0
- package/dist/recorder/events.test.js +40 -0
- package/dist/recorder/events.test.js.map +1 -0
- package/dist/recorder/generate-scenario.d.ts +16 -0
- package/dist/recorder/generate-scenario.d.ts.map +1 -0
- package/dist/recorder/generate-scenario.js +78 -0
- package/dist/recorder/generate-scenario.js.map +1 -0
- package/dist/recorder/in-page-helpers.d.ts +6 -0
- package/dist/recorder/in-page-helpers.d.ts.map +1 -0
- package/dist/recorder/in-page-helpers.js +238 -0
- package/dist/recorder/in-page-helpers.js.map +1 -0
- package/dist/recorder/in-page-helpers.test.d.ts +2 -0
- package/dist/recorder/in-page-helpers.test.d.ts.map +1 -0
- package/dist/recorder/in-page-helpers.test.js +186 -0
- package/dist/recorder/in-page-helpers.test.js.map +1 -0
- package/dist/recorder/page-script.d.ts +7 -0
- package/dist/recorder/page-script.d.ts.map +1 -0
- package/dist/recorder/page-script.js +132 -0
- package/dist/recorder/page-script.js.map +1 -0
- package/dist/recorder/redact.d.ts +8 -0
- package/dist/recorder/redact.d.ts.map +1 -0
- package/dist/recorder/redact.js +26 -0
- package/dist/recorder/redact.js.map +1 -0
- package/dist/recorder/redact.test.d.ts +2 -0
- package/dist/recorder/redact.test.d.ts.map +1 -0
- package/dist/recorder/redact.test.js +27 -0
- package/dist/recorder/redact.test.js.map +1 -0
- package/dist/recorder/session.d.ts +8 -0
- package/dist/recorder/session.d.ts.map +1 -0
- package/dist/recorder/session.js +28 -0
- package/dist/recorder/session.js.map +1 -0
- package/dist/recorder/snapshot-match.d.ts +22 -0
- package/dist/recorder/snapshot-match.d.ts.map +1 -0
- package/dist/recorder/snapshot-match.js +102 -0
- package/dist/recorder/snapshot-match.js.map +1 -0
- package/dist/recorder/snapshot-match.test.d.ts +2 -0
- package/dist/recorder/snapshot-match.test.d.ts.map +1 -0
- package/dist/recorder/snapshot-match.test.js +34 -0
- package/dist/recorder/snapshot-match.test.js.map +1 -0
- package/dist/redact/env-secrets.d.ts +14 -0
- package/dist/redact/env-secrets.d.ts.map +1 -0
- package/dist/redact/env-secrets.js +86 -0
- package/dist/redact/env-secrets.js.map +1 -0
- package/dist/redact/env-secrets.test.d.ts +2 -0
- package/dist/redact/env-secrets.test.d.ts.map +1 -0
- package/dist/redact/env-secrets.test.js +103 -0
- package/dist/redact/env-secrets.test.js.map +1 -0
- package/dist/reporter/export.d.ts +14 -0
- package/dist/reporter/export.d.ts.map +1 -0
- package/dist/reporter/export.js +53 -0
- package/dist/reporter/export.js.map +1 -0
- package/dist/reporter/export.test.d.ts +2 -0
- package/dist/reporter/export.test.d.ts.map +1 -0
- package/dist/reporter/export.test.js +100 -0
- package/dist/reporter/export.test.js.map +1 -0
- package/dist/reporter/index.d.ts +11 -0
- package/dist/reporter/index.d.ts.map +1 -0
- package/dist/reporter/index.js +161 -0
- package/dist/reporter/index.js.map +1 -0
- package/dist/reporter/index.test.d.ts +2 -0
- package/dist/reporter/index.test.d.ts.map +1 -0
- package/dist/reporter/index.test.js +61 -0
- package/dist/reporter/index.test.js.map +1 -0
- package/dist/scenarios/globs.d.ts +15 -0
- package/dist/scenarios/globs.d.ts.map +1 -0
- package/dist/scenarios/globs.js +48 -0
- package/dist/scenarios/globs.js.map +1 -0
- package/dist/scenarios/globs.test.d.ts +2 -0
- package/dist/scenarios/globs.test.d.ts.map +1 -0
- package/dist/scenarios/globs.test.js +53 -0
- package/dist/scenarios/globs.test.js.map +1 -0
- package/dist/scenarios/parser.d.ts +15 -0
- package/dist/scenarios/parser.d.ts.map +1 -0
- package/dist/scenarios/parser.js +278 -0
- package/dist/scenarios/parser.js.map +1 -0
- package/dist/scenarios/parser.test.d.ts +2 -0
- package/dist/scenarios/parser.test.d.ts.map +1 -0
- package/dist/scenarios/parser.test.js +373 -0
- package/dist/scenarios/parser.test.js.map +1 -0
- package/dist/skills/loader.d.ts +10 -0
- package/dist/skills/loader.d.ts.map +1 -0
- package/dist/skills/loader.js +98 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/types/config.d.ts +131 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +2 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/recorder.d.ts +71 -0
- package/dist/types/recorder.d.ts.map +1 -0
- package/dist/types/recorder.js +2 -0
- package/dist/types/recorder.js.map +1 -0
- package/dist/types/scenario.d.ts +41 -0
- package/dist/types/scenario.d.ts.map +1 -0
- package/dist/types/scenario.js +2 -0
- package/dist/types/scenario.js.map +1 -0
- package/dist/types/skill.d.ts +20 -0
- package/dist/types/skill.d.ts.map +1 -0
- package/dist/types/skill.js +13 -0
- package/dist/types/skill.js.map +1 -0
- package/dist/types/verdict.d.ts +82 -0
- package/dist/types/verdict.d.ts.map +1 -0
- package/dist/types/verdict.js +13 -0
- package/dist/types/verdict.js.map +1 -0
- package/package.json +75 -0
- package/pqa.config.ts +82 -0
- package/prompt/ANALYZE-FLAKY.md +62 -0
- package/prompt/ANALYZE.md +110 -0
- package/prompt/CACHE-HINTS.md +49 -0
- package/prompt/RECORD.md +114 -0
- package/prompt/SYSTEM.md +118 -0
- package/skills/agent-browser/SKILL.md +2438 -0
- package/skills/create-pqa-scenario/SKILL.md +273 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { existsSync, unlinkSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
/** Browser failure captures written by the agent under $PQA_ARTIFACT_DIR */
|
|
4
|
+
export const BROWSER_ARTIFACT_FILES = ["failure.png", "snapshot.json"];
|
|
5
|
+
export function formatArtifactsRuntimeHint(mode) {
|
|
6
|
+
switch (mode) {
|
|
7
|
+
case "never":
|
|
8
|
+
return [
|
|
9
|
+
"Browser failure artifacts: disabled.",
|
|
10
|
+
"Do NOT write failure.png or snapshot.json under $PQA_ARTIFACT_DIR.",
|
|
11
|
+
].join("\n");
|
|
12
|
+
case "always":
|
|
13
|
+
return [
|
|
14
|
+
"Browser failure artifacts: always.",
|
|
15
|
+
"After verifying all Then checkpoints (pass or fail), capture to $PQA_ARTIFACT_DIR:",
|
|
16
|
+
' agent-browser screenshot "$PQA_ARTIFACT_DIR/failure.png"',
|
|
17
|
+
' agent-browser snapshot -i --json > "$PQA_ARTIFACT_DIR/snapshot.json"',
|
|
18
|
+
].join("\n");
|
|
19
|
+
default:
|
|
20
|
+
return [
|
|
21
|
+
"Browser failure artifacts: on failure only.",
|
|
22
|
+
"If any Then checkpoint fails, capture to $PQA_ARTIFACT_DIR:",
|
|
23
|
+
' agent-browser screenshot "$PQA_ARTIFACT_DIR/failure.png"',
|
|
24
|
+
' agent-browser snapshot -i --json > "$PQA_ARTIFACT_DIR/snapshot.json"',
|
|
25
|
+
].join("\n");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export function pruneBrowserArtifacts(artifactDir) {
|
|
29
|
+
for (const name of BROWSER_ARTIFACT_FILES) {
|
|
30
|
+
const filePath = path.join(artifactDir, name);
|
|
31
|
+
if (existsSync(filePath)) {
|
|
32
|
+
unlinkSync(filePath);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/** Enforce --artifacts policy after a scenario (harness transcripts are unaffected). */
|
|
37
|
+
export function applyArtifactsPolicy(artifactDir, mode, result) {
|
|
38
|
+
if (mode === "never") {
|
|
39
|
+
pruneBrowserArtifacts(artifactDir);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (mode === "on-failure" && result.status === "pass") {
|
|
43
|
+
pruneBrowserArtifacts(artifactDir);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/artifacts/policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B,4EAA4E;AAC5E,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,aAAa,EAAE,eAAe,CAAU,CAAC;AAEhF,MAAM,UAAU,0BAA0B,CAAC,IAAmB;IAC5D,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,OAAO;YACV,OAAO;gBACL,sCAAsC;gBACtC,oEAAoE;aACrE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf,KAAK,QAAQ;YACX,OAAO;gBACL,oCAAoC;gBACpC,oFAAoF;gBACpF,4DAA4D;gBAC5D,wEAAwE;aACzE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf;YACE,OAAO;gBACL,6CAA6C;gBAC7C,6DAA6D;gBAC7D,4DAA4D;gBAC5D,wEAAwE;aACzE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,WAAmB;IACvD,KAAK,MAAM,IAAI,IAAI,sBAAsB,EAAE,CAAC;QAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAC9C,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,UAAU,CAAC,QAAQ,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;AACH,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,oBAAoB,CAClC,WAAmB,EACnB,IAAmB,EACnB,MAAsC;IAEtC,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,qBAAqB,CAAC,WAAW,CAAC,CAAC;QACnC,OAAO;IACT,CAAC;IACD,IAAI,IAAI,KAAK,YAAY,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QACtD,qBAAqB,CAAC,WAAW,CAAC,CAAC;IACrC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.test.d.ts","sourceRoot":"","sources":["../../src/artifacts/policy.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { mkdirSync, writeFileSync, existsSync } from "node:fs";
|
|
3
|
+
import { mkdtempSync } from "node:fs";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { describe, it } from "node:test";
|
|
7
|
+
import { applyArtifactsPolicy, BROWSER_ARTIFACT_FILES, formatArtifactsRuntimeHint, pruneBrowserArtifacts, } from "./policy.js";
|
|
8
|
+
function seedBrowserArtifacts(dir) {
|
|
9
|
+
for (const name of BROWSER_ARTIFACT_FILES) {
|
|
10
|
+
writeFileSync(path.join(dir, name), "test");
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
describe("formatArtifactsRuntimeHint", () => {
|
|
14
|
+
it("documents never mode", () => {
|
|
15
|
+
const hint = formatArtifactsRuntimeHint("never");
|
|
16
|
+
assert.match(hint, /disabled/i);
|
|
17
|
+
assert.match(hint, /Do NOT write failure\.png/);
|
|
18
|
+
});
|
|
19
|
+
it("documents always mode", () => {
|
|
20
|
+
const hint = formatArtifactsRuntimeHint("always");
|
|
21
|
+
assert.match(hint, /pass or fail/i);
|
|
22
|
+
assert.match(hint, /failure\.png/);
|
|
23
|
+
});
|
|
24
|
+
it("documents on-failure mode", () => {
|
|
25
|
+
const hint = formatArtifactsRuntimeHint("on-failure");
|
|
26
|
+
assert.match(hint, /on failure only/i);
|
|
27
|
+
assert.match(hint, /failure\.png/);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
describe("applyArtifactsPolicy", () => {
|
|
31
|
+
it("removes browser artifacts when mode is never", () => {
|
|
32
|
+
const dir = mkdtempSync(path.join(tmpdir(), "pqa-artifacts-"));
|
|
33
|
+
seedBrowserArtifacts(dir);
|
|
34
|
+
applyArtifactsPolicy(dir, "never", { status: "fail" });
|
|
35
|
+
for (const name of BROWSER_ARTIFACT_FILES) {
|
|
36
|
+
assert.equal(existsSync(path.join(dir, name)), false);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
it("removes browser artifacts on pass when mode is on-failure", () => {
|
|
40
|
+
const dir = mkdtempSync(path.join(tmpdir(), "pqa-artifacts-"));
|
|
41
|
+
seedBrowserArtifacts(dir);
|
|
42
|
+
writeFileSync(path.join(dir, "transcript.json"), "{}");
|
|
43
|
+
applyArtifactsPolicy(dir, "on-failure", { status: "pass" });
|
|
44
|
+
for (const name of BROWSER_ARTIFACT_FILES) {
|
|
45
|
+
assert.equal(existsSync(path.join(dir, name)), false);
|
|
46
|
+
}
|
|
47
|
+
assert.equal(existsSync(path.join(dir, "transcript.json")), true);
|
|
48
|
+
});
|
|
49
|
+
it("keeps browser artifacts on fail when mode is on-failure", () => {
|
|
50
|
+
const dir = mkdtempSync(path.join(tmpdir(), "pqa-artifacts-"));
|
|
51
|
+
seedBrowserArtifacts(dir);
|
|
52
|
+
applyArtifactsPolicy(dir, "on-failure", { status: "fail" });
|
|
53
|
+
for (const name of BROWSER_ARTIFACT_FILES) {
|
|
54
|
+
assert.equal(existsSync(path.join(dir, name)), true);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
it("keeps browser artifacts on pass when mode is always", () => {
|
|
58
|
+
const dir = mkdtempSync(path.join(tmpdir(), "pqa-artifacts-"));
|
|
59
|
+
seedBrowserArtifacts(dir);
|
|
60
|
+
applyArtifactsPolicy(dir, "always", { status: "pass" });
|
|
61
|
+
for (const name of BROWSER_ARTIFACT_FILES) {
|
|
62
|
+
assert.equal(existsSync(path.join(dir, name)), true);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe("pruneBrowserArtifacts", () => {
|
|
67
|
+
it("is a no-op when files are missing", () => {
|
|
68
|
+
const dir = mkdtempSync(path.join(tmpdir(), "pqa-artifacts-"));
|
|
69
|
+
mkdirSync(dir, { recursive: true });
|
|
70
|
+
assert.doesNotThrow(() => pruneBrowserArtifacts(dir));
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
//# sourceMappingURL=policy.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.test.js","sourceRoot":"","sources":["../../src/artifacts/policy.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,aAAa,CAAC;AAErB,SAAS,oBAAoB,CAAC,GAAW;IACvC,KAAK,MAAM,IAAI,IAAI,sBAAsB,EAAE,CAAC;QAC1C,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC;AAED,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAC9B,MAAM,IAAI,GAAG,0BAA0B,CAAC,OAAO,CAAC,CAAC;QACjD,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,2BAA2B,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,IAAI,GAAG,0BAA0B,CAAC,QAAQ,CAAC,CAAC;QAClD,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,IAAI,GAAG,0BAA0B,CAAC,YAAY,CAAC,CAAC;QACtD,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;QACvC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAC/D,oBAAoB,CAAC,GAAG,CAAC,CAAC;QAC1B,oBAAoB,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACvD,KAAK,MAAM,IAAI,IAAI,sBAAsB,EAAE,CAAC;YAC1C,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACxD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAC/D,oBAAoB,CAAC,GAAG,CAAC,CAAC;QAC1B,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,iBAAiB,CAAC,EAAE,IAAI,CAAC,CAAC;QACvD,oBAAoB,CAAC,GAAG,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAC5D,KAAK,MAAM,IAAI,IAAI,sBAAsB,EAAE,CAAC;YAC1C,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACxD,CAAC;QACD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAC/D,oBAAoB,CAAC,GAAG,CAAC,CAAC;QAC1B,oBAAoB,CAAC,GAAG,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAC5D,KAAK,MAAM,IAAI,IAAI,sBAAsB,EAAE,CAAC;YAC1C,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QACvD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAC/D,oBAAoB,CAAC,GAAG,CAAC,CAAC;QAC1B,oBAAoB,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,KAAK,MAAM,IAAI,IAAI,sBAAsB,EAAE,CAAC;YAC1C,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QACvD,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAC/D,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpC,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ArtifactsMode, PqaConfig } from "../types/config.js";
|
|
2
|
+
import type { Scenario } from "../types/scenario.js";
|
|
3
|
+
import type { Skill } from "../types/skill.js";
|
|
4
|
+
import type { EnvRedactor } from "../redact/env-secrets.js";
|
|
5
|
+
export interface EnsureAuthContext {
|
|
6
|
+
config: PqaConfig;
|
|
7
|
+
allSkills: Skill[];
|
|
8
|
+
baseSkillNames: string[];
|
|
9
|
+
cwd: string;
|
|
10
|
+
runDir: string;
|
|
11
|
+
headed: boolean;
|
|
12
|
+
verbose?: boolean;
|
|
13
|
+
allScenarios: Scenario[];
|
|
14
|
+
authRefresh?: boolean;
|
|
15
|
+
keepBrowser?: boolean;
|
|
16
|
+
artifacts: ArtifactsMode;
|
|
17
|
+
redactor: EnvRedactor;
|
|
18
|
+
}
|
|
19
|
+
export declare function ensureAuthProfile(ctx: EnsureAuthContext, profile: string): Promise<string>;
|
|
20
|
+
export declare function ensureAuthProfiles(ctx: EnsureAuthContext, profiles: Iterable<string>): Promise<Map<string, string>>;
|
|
21
|
+
export declare function resolveConsumerAuthState(config: PqaConfig, authName: string | undefined, cwd: string, preResolved?: Map<string, string>): string | undefined;
|
|
22
|
+
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/auth/resolve.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAG/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAU5D,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,SAAS,CAAC;IAClB,SAAS,EAAE,KAAK,EAAE,CAAC;IACnB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,QAAQ,EAAE,CAAC;IACzB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,aAAa,CAAC;IACzB,QAAQ,EAAE,WAAW,CAAC;CACvB;AAsFD,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,iBAAiB,EACtB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CA4FjB;AAED,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,iBAAiB,EACtB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,GACzB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAS9B;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,GAAG,EAAE,MAAM,EACX,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,MAAM,GAAG,SAAS,CAapB"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { mkdirSync, readFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { runScenario } from "../agent/runner.js";
|
|
4
|
+
import { buildBrowserEnv, closeBrowserSession, runBash } from "../agent/bash.js";
|
|
5
|
+
import { applyArtifactsPolicy } from "../artifacts/policy.js";
|
|
6
|
+
import { resolveSkills } from "../skills/loader.js";
|
|
7
|
+
import { scenarioArtifactDir } from "../reporter/index.js";
|
|
8
|
+
import { clear as clearAuthStore, getAuthEntry, hasState, record, resolveProfilePath, resolveStatePath, } from "./store.js";
|
|
9
|
+
function findScenarioByName(scenarios, name) {
|
|
10
|
+
return scenarios.find((s) => s.frontmatter.name === name);
|
|
11
|
+
}
|
|
12
|
+
function assertNonEmptyAuthState(statePath, profile) {
|
|
13
|
+
let parsed;
|
|
14
|
+
try {
|
|
15
|
+
parsed = JSON.parse(readFileSync(statePath, "utf-8"));
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
throw new Error(`Auth state for profile "${profile}" is not valid JSON at ${statePath}`);
|
|
19
|
+
}
|
|
20
|
+
const cookieCount = Array.isArray(parsed.cookies) ? parsed.cookies.length : 0;
|
|
21
|
+
if (cookieCount === 0) {
|
|
22
|
+
throw new Error(`Auth state for profile "${profile}" has no cookies at ${statePath}. ` +
|
|
23
|
+
"The auth browser session was likely closed before the harness could save state. " +
|
|
24
|
+
"Re-run auth without agent-browser close/state save commands.");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async function saveBrowserState(ctx, profile, statePath) {
|
|
28
|
+
mkdirSync(path.dirname(statePath), { recursive: true });
|
|
29
|
+
mkdirSync(resolveProfilePath(ctx.cwd, profile), { recursive: true });
|
|
30
|
+
const bashEnv = buildBrowserEnv({
|
|
31
|
+
cwd: ctx.cwd,
|
|
32
|
+
headed: ctx.headed,
|
|
33
|
+
sessionName: `pqa-auth-${profile}`,
|
|
34
|
+
engine: ctx.config.browser.engine,
|
|
35
|
+
lightpanda: ctx.config.browser.lightpanda,
|
|
36
|
+
profilePath: resolveProfilePath(ctx.cwd, profile),
|
|
37
|
+
artifactDir: ctx.cwd,
|
|
38
|
+
});
|
|
39
|
+
const urlEntry = await runBash("agent-browser get url", {
|
|
40
|
+
cwd: ctx.cwd,
|
|
41
|
+
timeoutMs: ctx.config.agent.bashTimeoutMs,
|
|
42
|
+
env: bashEnv,
|
|
43
|
+
});
|
|
44
|
+
const currentUrl = urlEntry.stdout.trim();
|
|
45
|
+
if (urlEntry.exitCode !== 0 ||
|
|
46
|
+
!currentUrl ||
|
|
47
|
+
currentUrl === "about:blank") {
|
|
48
|
+
throw new Error(`Cannot save auth state for profile "${profile}": browser session is not on a signed-in page ` +
|
|
49
|
+
`(url=${currentUrl || "(empty)"}). Do not run agent-browser close before the harness saves state.`);
|
|
50
|
+
}
|
|
51
|
+
const saveEntry = await runBash(`agent-browser state save "${statePath}"`, {
|
|
52
|
+
cwd: ctx.cwd,
|
|
53
|
+
timeoutMs: ctx.config.agent.bashTimeoutMs,
|
|
54
|
+
env: bashEnv,
|
|
55
|
+
});
|
|
56
|
+
if (saveEntry.exitCode !== 0) {
|
|
57
|
+
throw new Error(`Failed to save auth state for profile "${profile}": ${saveEntry.stderr || saveEntry.stdout}`);
|
|
58
|
+
}
|
|
59
|
+
assertNonEmptyAuthState(statePath, profile);
|
|
60
|
+
}
|
|
61
|
+
export async function ensureAuthProfile(ctx, profile) {
|
|
62
|
+
const authEntry = getAuthEntry(ctx.config, profile);
|
|
63
|
+
if (!authEntry) {
|
|
64
|
+
throw new Error(`Auth profile "${profile}" not configured in pqa.config.ts`);
|
|
65
|
+
}
|
|
66
|
+
const statePath = resolveStatePath(ctx.cwd, profile, ctx.config);
|
|
67
|
+
if (!authEntry.scenario) {
|
|
68
|
+
if (!authEntry.statePath && !hasState(ctx.cwd, profile, ctx.config)) {
|
|
69
|
+
throw new Error(`Auth profile "${profile}" has no scenario and no state file at ${statePath}`);
|
|
70
|
+
}
|
|
71
|
+
return statePath;
|
|
72
|
+
}
|
|
73
|
+
if (ctx.authRefresh) {
|
|
74
|
+
clearAuthStore(ctx.cwd, profile);
|
|
75
|
+
}
|
|
76
|
+
if (hasState(ctx.cwd, profile, ctx.config)) {
|
|
77
|
+
return statePath;
|
|
78
|
+
}
|
|
79
|
+
const authScenario = findScenarioByName(ctx.allScenarios, authEntry.scenario);
|
|
80
|
+
if (!authScenario) {
|
|
81
|
+
throw new Error(`Auth scenario "${authEntry.scenario}" not found for profile "${profile}"`);
|
|
82
|
+
}
|
|
83
|
+
const artifactDir = scenarioArtifactDir(ctx.runDir, `auth-${profile}`);
|
|
84
|
+
const sessionName = `pqa-auth-${profile}`;
|
|
85
|
+
const profilePath = resolveProfilePath(ctx.cwd, profile);
|
|
86
|
+
mkdirSync(profilePath, { recursive: true });
|
|
87
|
+
try {
|
|
88
|
+
const skills = resolveSkills(ctx.allSkills, ctx.baseSkillNames, authScenario.skills);
|
|
89
|
+
const result = await runScenario({
|
|
90
|
+
config: ctx.config,
|
|
91
|
+
skills,
|
|
92
|
+
scenario: authScenario,
|
|
93
|
+
cwd: ctx.cwd,
|
|
94
|
+
artifactDir,
|
|
95
|
+
headed: ctx.headed,
|
|
96
|
+
verbose: ctx.verbose,
|
|
97
|
+
artifacts: ctx.artifacts,
|
|
98
|
+
sessionName,
|
|
99
|
+
authProfile: profile,
|
|
100
|
+
profilePath,
|
|
101
|
+
redactor: ctx.redactor,
|
|
102
|
+
});
|
|
103
|
+
applyArtifactsPolicy(artifactDir, ctx.artifacts, result);
|
|
104
|
+
if (result.status !== "pass") {
|
|
105
|
+
throw new Error(`Auth scenario "${authEntry.scenario}" failed for profile "${profile}"${result.error ? `: ${result.error}` : ""}`);
|
|
106
|
+
}
|
|
107
|
+
await saveBrowserState(ctx, profile, statePath);
|
|
108
|
+
record(ctx.cwd, profile, {
|
|
109
|
+
statePath,
|
|
110
|
+
scenario: authEntry.scenario,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
if (!ctx.keepBrowser) {
|
|
115
|
+
await closeBrowserSession({
|
|
116
|
+
cwd: ctx.cwd,
|
|
117
|
+
timeoutMs: ctx.config.agent.bashTimeoutMs,
|
|
118
|
+
sessionName,
|
|
119
|
+
headed: ctx.headed,
|
|
120
|
+
engine: ctx.config.browser.engine,
|
|
121
|
+
lightpanda: ctx.config.browser.lightpanda,
|
|
122
|
+
verbose: ctx.verbose,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return statePath;
|
|
127
|
+
}
|
|
128
|
+
export async function ensureAuthProfiles(ctx, profiles) {
|
|
129
|
+
const resolved = new Map();
|
|
130
|
+
const unique = [...new Set(profiles)];
|
|
131
|
+
for (const profile of unique) {
|
|
132
|
+
resolved.set(profile, await ensureAuthProfile(ctx, profile));
|
|
133
|
+
}
|
|
134
|
+
return resolved;
|
|
135
|
+
}
|
|
136
|
+
export function resolveConsumerAuthState(config, authName, cwd, preResolved) {
|
|
137
|
+
if (!authName)
|
|
138
|
+
return undefined;
|
|
139
|
+
if (preResolved?.has(authName)) {
|
|
140
|
+
return preResolved.get(authName);
|
|
141
|
+
}
|
|
142
|
+
const entry = config.auth[authName];
|
|
143
|
+
if (!entry) {
|
|
144
|
+
throw new Error(`Auth profile "${authName}" not configured in pqa.config.ts`);
|
|
145
|
+
}
|
|
146
|
+
return resolveStatePath(cwd, authName, config);
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/auth/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAI9D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,EACL,KAAK,IAAI,cAAc,EACvB,YAAY,EACZ,QAAQ,EACR,MAAM,EACN,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAiBpB,SAAS,kBAAkB,CACzB,SAAqB,EACrB,IAAY;IAEZ,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AAC5D,CAAC;AAOD,SAAS,uBAAuB,CAAC,SAAiB,EAAE,OAAe;IACjE,IAAI,MAAyB,CAAC;IAC9B,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAsB,CAAC;IAC7E,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,2BAA2B,OAAO,0BAA0B,SAAS,EAAE,CACxE,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,2BAA2B,OAAO,uBAAuB,SAAS,IAAI;YACpE,kFAAkF;YAClF,8DAA8D,CACjE,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC7B,GAAsB,EACtB,OAAe,EACf,SAAiB;IAEjB,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,SAAS,CAAC,kBAAkB,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrE,MAAM,OAAO,GAAG,eAAe,CAAC;QAC9B,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,WAAW,EAAE,YAAY,OAAO,EAAE;QAClC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM;QACjC,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU;QACzC,WAAW,EAAE,kBAAkB,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC;QACjD,WAAW,EAAE,GAAG,CAAC,GAAG;KACrB,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,uBAAuB,EAAE;QACtD,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa;QACzC,GAAG,EAAE,OAAO;KACb,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAC1C,IACE,QAAQ,CAAC,QAAQ,KAAK,CAAC;QACvB,CAAC,UAAU;QACX,UAAU,KAAK,aAAa,EAC5B,CAAC;QACD,MAAM,IAAI,KAAK,CACb,uCAAuC,OAAO,gDAAgD;YAC5F,QAAQ,UAAU,IAAI,SAAS,mEAAmE,CACrG,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,OAAO,CAC7B,6BAA6B,SAAS,GAAG,EACzC;QACE,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa;QACzC,GAAG,EAAE,OAAO;KACb,CACF,CAAC;IAEF,IAAI,SAAS,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CACb,0CAA0C,OAAO,MAAM,SAAS,CAAC,MAAM,IAAI,SAAS,CAAC,MAAM,EAAE,CAC9F,CAAC;IACJ,CAAC;IAED,uBAAuB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,GAAsB,EACtB,OAAe;IAEf,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,iBAAiB,OAAO,mCAAmC,CAAC,CAAC;IAC/E,CAAC;IAED,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAEjE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;QACxB,IAAI,CAAC,SAAS,CAAC,SAAS,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACpE,MAAM,IAAI,KAAK,CACb,iBAAiB,OAAO,0CAA0C,SAAS,EAAE,CAC9E,CAAC;QACJ,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;QACpB,cAAc,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACnC,CAAC;IAED,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3C,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,YAAY,GAAG,kBAAkB,CACrC,GAAG,CAAC,YAAY,EAChB,SAAS,CAAC,QAAQ,CACnB,CAAC;IACF,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CACb,kBAAkB,SAAS,CAAC,QAAQ,4BAA4B,OAAO,GAAG,CAC3E,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,mBAAmB,CACrC,GAAG,CAAC,MAAM,EACV,QAAQ,OAAO,EAAE,CAClB,CAAC;IACF,MAAM,WAAW,GAAG,YAAY,OAAO,EAAE,CAAC;IAC1C,MAAM,WAAW,GAAG,kBAAkB,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACzD,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE5C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,aAAa,CAC1B,GAAG,CAAC,SAAS,EACb,GAAG,CAAC,cAAc,EAClB,YAAY,CAAC,MAAM,CACpB,CAAC;QACF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC;YAC/B,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,MAAM;YACN,QAAQ,EAAE,YAAY;YACtB,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,WAAW;YACX,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,WAAW;YACX,WAAW,EAAE,OAAO;YACpB,WAAW;YACX,QAAQ,EAAE,GAAG,CAAC,QAAQ;SACvB,CAAC,CAAC;QAEH,oBAAoB,CAAC,WAAW,EAAE,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAEzD,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CACb,kBAAkB,SAAS,CAAC,QAAQ,yBAAyB,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAClH,CAAC;QACJ,CAAC;QAED,MAAM,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE;YACvB,SAAS;YACT,QAAQ,EAAE,SAAS,CAAC,QAAQ;SAC7B,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YACrB,MAAM,mBAAmB,CAAC;gBACxB,GAAG,EAAE,GAAG,CAAC,GAAG;gBACZ,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa;gBACzC,WAAW;gBACX,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM;gBACjC,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU;gBACzC,OAAO,EAAE,GAAG,CAAC,OAAO;aACrB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,GAAsB,EACtB,QAA0B;IAE1B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC3C,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEtC,KAAK,MAAM,OAAO,IAAI,MAAM,EAAE,CAAC;QAC7B,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,iBAAiB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,MAAiB,EACjB,QAA4B,EAC5B,GAAW,EACX,WAAiC;IAEjC,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAC;IAEhC,IAAI,WAAW,EAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/B,OAAO,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,iBAAiB,QAAQ,mCAAmC,CAAC,CAAC;IAChF,CAAC;IAED,OAAO,gBAAgB,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AuthProfileConfig, PqaConfig } from "../types/config.js";
|
|
2
|
+
export interface AuthStoreEntry {
|
|
3
|
+
profile: string;
|
|
4
|
+
statePath: string;
|
|
5
|
+
scenario?: string;
|
|
6
|
+
savedAt: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function defaultStatePath(cwd: string, profile: string): string;
|
|
9
|
+
export declare function resolveProfilePath(cwd: string, profile: string): string;
|
|
10
|
+
export declare function hasProfile(cwd: string, profile: string): boolean;
|
|
11
|
+
export declare function clearProfile(cwd: string, profile: string): void;
|
|
12
|
+
export declare function resolveStatePath(cwd: string, profile: string, config: PqaConfig): string;
|
|
13
|
+
export declare function hasState(cwd: string, profile: string, config: PqaConfig): boolean;
|
|
14
|
+
export declare function record(cwd: string, profile: string, meta: {
|
|
15
|
+
statePath: string;
|
|
16
|
+
scenario?: string;
|
|
17
|
+
}): void;
|
|
18
|
+
export declare function list(cwd: string): AuthStoreEntry[];
|
|
19
|
+
export declare function clear(cwd: string, profile?: string): void;
|
|
20
|
+
export declare function getAuthScenarioNames(config: PqaConfig): Set<string>;
|
|
21
|
+
export declare function getAuthEntry(config: PqaConfig, profile: string): AuthProfileConfig | undefined;
|
|
22
|
+
export declare function findProfileForAuthScenario(config: PqaConfig, scenarioName: string): string | undefined;
|
|
23
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/auth/store.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEvE,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AA6BD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAErE;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvE;AASD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAEhE;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAE/D;AAED,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,SAAS,GAChB,MAAM,CAMR;AAED,wBAAgB,QAAQ,CACtB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,SAAS,GAChB,OAAO,CAET;AAED,wBAAgB,MAAM,CACpB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7C,IAAI,CAUN;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,EAAE,CAMlD;AAED,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAqBzD;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,CAMnE;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,MAAM,GACd,iBAAiB,GAAG,SAAS,CAE/B;AAED,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,SAAS,EACjB,YAAY,EAAE,MAAM,GACnB,MAAM,GAAG,SAAS,CAKpB"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
function authDir(cwd) {
|
|
4
|
+
return path.resolve(cwd, ".pqa", "auth");
|
|
5
|
+
}
|
|
6
|
+
function indexPath(cwd) {
|
|
7
|
+
return path.join(authDir(cwd), "index.json");
|
|
8
|
+
}
|
|
9
|
+
function readIndex(cwd) {
|
|
10
|
+
const file = indexPath(cwd);
|
|
11
|
+
if (!existsSync(file))
|
|
12
|
+
return { profiles: {} };
|
|
13
|
+
try {
|
|
14
|
+
return JSON.parse(readFileSync(file, "utf-8"));
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return { profiles: {} };
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function writeIndex(cwd, index) {
|
|
21
|
+
mkdirSync(authDir(cwd), { recursive: true });
|
|
22
|
+
writeFileSync(indexPath(cwd), JSON.stringify(index, null, 2));
|
|
23
|
+
}
|
|
24
|
+
export function defaultStatePath(cwd, profile) {
|
|
25
|
+
return path.resolve(cwd, ".pqa", "auth", `${profile}.json`);
|
|
26
|
+
}
|
|
27
|
+
export function resolveProfilePath(cwd, profile) {
|
|
28
|
+
return path.resolve(cwd, ".pqa", "profiles", profile);
|
|
29
|
+
}
|
|
30
|
+
function profileHasBrowserData(profilePath) {
|
|
31
|
+
return (existsSync(path.join(profilePath, "Default", "Cookies")) ||
|
|
32
|
+
existsSync(path.join(profilePath, "Default", "Network", "Cookies")));
|
|
33
|
+
}
|
|
34
|
+
export function hasProfile(cwd, profile) {
|
|
35
|
+
return profileHasBrowserData(resolveProfilePath(cwd, profile));
|
|
36
|
+
}
|
|
37
|
+
export function clearProfile(cwd, profile) {
|
|
38
|
+
rmSync(resolveProfilePath(cwd, profile), { recursive: true, force: true });
|
|
39
|
+
}
|
|
40
|
+
export function resolveStatePath(cwd, profile, config) {
|
|
41
|
+
const entry = config.auth[profile];
|
|
42
|
+
if (entry?.statePath) {
|
|
43
|
+
return path.resolve(cwd, entry.statePath);
|
|
44
|
+
}
|
|
45
|
+
return defaultStatePath(cwd, profile);
|
|
46
|
+
}
|
|
47
|
+
export function hasState(cwd, profile, config) {
|
|
48
|
+
return hasProfile(cwd, profile);
|
|
49
|
+
}
|
|
50
|
+
export function record(cwd, profile, meta) {
|
|
51
|
+
const resolved = path.resolve(meta.statePath);
|
|
52
|
+
mkdirSync(path.dirname(resolved), { recursive: true });
|
|
53
|
+
const index = readIndex(cwd);
|
|
54
|
+
index.profiles[profile] = {
|
|
55
|
+
statePath: resolved,
|
|
56
|
+
scenario: meta.scenario,
|
|
57
|
+
savedAt: new Date().toISOString(),
|
|
58
|
+
};
|
|
59
|
+
writeIndex(cwd, index);
|
|
60
|
+
}
|
|
61
|
+
export function list(cwd) {
|
|
62
|
+
const index = readIndex(cwd);
|
|
63
|
+
return Object.entries(index.profiles).map(([profile, entry]) => ({
|
|
64
|
+
profile,
|
|
65
|
+
...entry,
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
export function clear(cwd, profile) {
|
|
69
|
+
const index = readIndex(cwd);
|
|
70
|
+
if (profile) {
|
|
71
|
+
const entry = index.profiles[profile];
|
|
72
|
+
if (entry?.statePath && existsSync(entry.statePath)) {
|
|
73
|
+
unlinkSync(entry.statePath);
|
|
74
|
+
}
|
|
75
|
+
clearProfile(cwd, profile);
|
|
76
|
+
delete index.profiles[profile];
|
|
77
|
+
writeIndex(cwd, index);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
for (const [profileName, entry] of Object.entries(index.profiles)) {
|
|
81
|
+
if (entry.statePath && existsSync(entry.statePath)) {
|
|
82
|
+
unlinkSync(entry.statePath);
|
|
83
|
+
}
|
|
84
|
+
clearProfile(cwd, profileName);
|
|
85
|
+
}
|
|
86
|
+
writeIndex(cwd, { profiles: {} });
|
|
87
|
+
}
|
|
88
|
+
export function getAuthScenarioNames(config) {
|
|
89
|
+
return new Set(Object.values(config.auth)
|
|
90
|
+
.map((entry) => entry.scenario)
|
|
91
|
+
.filter((name) => Boolean(name)));
|
|
92
|
+
}
|
|
93
|
+
export function getAuthEntry(config, profile) {
|
|
94
|
+
return config.auth[profile];
|
|
95
|
+
}
|
|
96
|
+
export function findProfileForAuthScenario(config, scenarioName) {
|
|
97
|
+
for (const [profile, entry] of Object.entries(config.auth)) {
|
|
98
|
+
if (entry.scenario === scenarioName)
|
|
99
|
+
return profile;
|
|
100
|
+
}
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/auth/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PqaConfig } from "../types/config.js";
|
|
2
|
+
import type { Scenario } from "../types/scenario.js";
|
|
3
|
+
import type { ScenarioResult } from "../types/verdict.js";
|
|
4
|
+
export declare function generateOrMergeScenarioCacheHints(config: PqaConfig, cwd: string, scenario: Scenario, result: ScenarioResult): Promise<{
|
|
5
|
+
ok: boolean;
|
|
6
|
+
error?: string;
|
|
7
|
+
}>;
|
|
8
|
+
//# sourceMappingURL=generate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/cache/generate.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAsD1D,wBAAsB,iCAAiC,CACrD,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA8B1C"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { generateText } from "ai";
|
|
3
|
+
import { createLlmModel } from "../agent/llm-model.js";
|
|
4
|
+
import { buildProviderOptions } from "../agent/provider-options.js";
|
|
5
|
+
import { truncateScenarioResult } from "../analyze/build-context.js";
|
|
6
|
+
import { formatScenarioForPrompt } from "../scenarios/parser.js";
|
|
7
|
+
import { resolveBundledPath } from "../paths.js";
|
|
8
|
+
import { readScenarioCacheMeta, writeScenarioCache, loadScenarioCache, } from "./store.js";
|
|
9
|
+
function buildCacheUserPrompt(scenario, result, existingHints) {
|
|
10
|
+
const truncated = truncateScenarioResult(result);
|
|
11
|
+
const parts = [
|
|
12
|
+
"## Scenario",
|
|
13
|
+
formatScenarioForPrompt(scenario),
|
|
14
|
+
"",
|
|
15
|
+
"## Successful run",
|
|
16
|
+
"```json",
|
|
17
|
+
JSON.stringify({
|
|
18
|
+
durationMs: truncated.durationMs,
|
|
19
|
+
verdict: truncated.verdict,
|
|
20
|
+
healing: truncated.healing,
|
|
21
|
+
transcript: truncated.transcript,
|
|
22
|
+
}, null, 2),
|
|
23
|
+
"```",
|
|
24
|
+
];
|
|
25
|
+
if (existingHints?.trim()) {
|
|
26
|
+
parts.push("", "## Existing hints (merge and improve)", existingHints.trim());
|
|
27
|
+
}
|
|
28
|
+
parts.push("", "Produce updated scenario replay hints for the next agent run. " +
|
|
29
|
+
"Only include advice specific to this scenario and transcript — no generic testing tips.");
|
|
30
|
+
return parts.join("\n");
|
|
31
|
+
}
|
|
32
|
+
export async function generateOrMergeScenarioCacheHints(config, cwd, scenario, result) {
|
|
33
|
+
try {
|
|
34
|
+
const systemPath = resolveBundledPath(cwd, "prompt/CACHE-HINTS.md");
|
|
35
|
+
const system = readFileSync(systemPath, "utf-8");
|
|
36
|
+
const name = scenario.frontmatter.name;
|
|
37
|
+
const existingHints = loadScenarioCache(cwd, config, scenario);
|
|
38
|
+
const existingMeta = readScenarioCacheMeta(cwd, config, name);
|
|
39
|
+
const { text } = await generateText({
|
|
40
|
+
model: createLlmModel(config),
|
|
41
|
+
system,
|
|
42
|
+
prompt: buildCacheUserPrompt(scenario, result, existingHints),
|
|
43
|
+
maxOutputTokens: 4096,
|
|
44
|
+
// force thinking off for cache hints generation
|
|
45
|
+
providerOptions: buildProviderOptions({
|
|
46
|
+
...config,
|
|
47
|
+
llm: { ...config.llm, thinking: { enabled: false } },
|
|
48
|
+
}),
|
|
49
|
+
});
|
|
50
|
+
const hints = text.trim();
|
|
51
|
+
if (!hints) {
|
|
52
|
+
return { ok: false, error: "LLM returned empty hints" };
|
|
53
|
+
}
|
|
54
|
+
writeScenarioCache(cwd, config, scenario, hints, existingMeta);
|
|
55
|
+
return { ok: true };
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
return { ok: false, error: String(err) };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=generate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/cache/generate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Scenario } from "../types/scenario.js";
|
|
2
|
+
/** Canonical payload used for cache invalidation (post-expansion content). */
|
|
3
|
+
export declare function scenarioContentPayload(scenario: Scenario): Record<string, unknown>;
|
|
4
|
+
export declare function hashScenarioContent(scenario: Scenario): string;
|
|
5
|
+
//# sourceMappingURL=hash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/cache/hash.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,8EAA8E;AAC9E,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAYlF;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAI9D"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
/** Canonical payload used for cache invalidation (post-expansion content). */
|
|
3
|
+
export function scenarioContentPayload(scenario) {
|
|
4
|
+
const { name, url, auth, tags, skills } = scenario.frontmatter;
|
|
5
|
+
return {
|
|
6
|
+
name,
|
|
7
|
+
url: url ?? null,
|
|
8
|
+
auth: auth ?? null,
|
|
9
|
+
tags: tags ?? [],
|
|
10
|
+
skills: skills ?? scenario.skills,
|
|
11
|
+
goal: scenario.goal.trim(),
|
|
12
|
+
steps: scenario.steps.trim(),
|
|
13
|
+
then: scenario.then.map((t) => t.trim()),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export function hashScenarioContent(scenario) {
|
|
17
|
+
const payload = scenarioContentPayload(scenario);
|
|
18
|
+
const json = JSON.stringify(payload);
|
|
19
|
+
return createHash("sha256").update(json, "utf8").digest("hex");
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=hash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/cache/hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,8EAA8E;AAC9E,MAAM,UAAU,sBAAsB,CAAC,QAAkB;IACvD,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC,WAAW,CAAC;IAC/D,OAAO;QACL,IAAI;QACJ,GAAG,EAAE,GAAG,IAAI,IAAI;QAChB,IAAI,EAAE,IAAI,IAAI,IAAI;QAClB,IAAI,EAAE,IAAI,IAAI,EAAE;QAChB,MAAM,EAAE,MAAM,IAAI,QAAQ,CAAC,MAAM;QACjC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE;QAC1B,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE;QAC5B,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;KACzC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAkB;IACpD,MAAM,OAAO,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACjE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.test.d.ts","sourceRoot":"","sources":["../../src/cache/hash.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { describe, it } from "node:test";
|
|
3
|
+
import { hashScenarioContent } from "./hash.js";
|
|
4
|
+
function makeScenario(overrides = {}) {
|
|
5
|
+
return {
|
|
6
|
+
filePath: "/tmp/example.md",
|
|
7
|
+
frontmatter: { name: "example-smoke" },
|
|
8
|
+
skills: [],
|
|
9
|
+
goal: "Verify the dashboard loads.",
|
|
10
|
+
steps: "1. Open the app.",
|
|
11
|
+
then: ['url contains "/dashboard"'],
|
|
12
|
+
rawCheckpoints: ['url contains "/dashboard"'],
|
|
13
|
+
checkpoints: [
|
|
14
|
+
{ raw: 'url contains "/dashboard"', kind: "url_contains", value: "/dashboard" },
|
|
15
|
+
],
|
|
16
|
+
...overrides,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
describe("hashScenarioContent", () => {
|
|
20
|
+
it("is stable for the same expanded content", () => {
|
|
21
|
+
const a = makeScenario();
|
|
22
|
+
const b = makeScenario({ filePath: "/other/path.md" });
|
|
23
|
+
assert.equal(hashScenarioContent(a), hashScenarioContent(b));
|
|
24
|
+
});
|
|
25
|
+
it("changes when steps change", () => {
|
|
26
|
+
const before = makeScenario();
|
|
27
|
+
const after = makeScenario({ steps: "1. Open the app.\n2. Click Save." });
|
|
28
|
+
assert.notEqual(hashScenarioContent(before), hashScenarioContent(after));
|
|
29
|
+
});
|
|
30
|
+
it("changes when then checkpoints change", () => {
|
|
31
|
+
const before = makeScenario();
|
|
32
|
+
const after = makeScenario({
|
|
33
|
+
then: ['page shows "Done"'],
|
|
34
|
+
rawCheckpoints: ['page shows "Done"'],
|
|
35
|
+
checkpoints: [
|
|
36
|
+
{ raw: 'page shows "Done"', kind: "page_shows", value: "Done" },
|
|
37
|
+
],
|
|
38
|
+
});
|
|
39
|
+
assert.notEqual(hashScenarioContent(before), hashScenarioContent(after));
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=hash.test.js.map
|