@howlil/ez-agents 3.4.2 → 4.0.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/README.md +735 -462
- package/agents/ez-architect-agent.md +267 -0
- package/agents/ez-backend-agent.md +303 -0
- package/agents/ez-chief-strategist.md +271 -0
- package/agents/ez-codebase-mapper.md +770 -770
- package/agents/ez-context-manager.md +319 -0
- package/agents/ez-debugger.md +1255 -1255
- package/agents/ez-design-expert.md +347 -0
- package/agents/ez-devops-agent.md +331 -0
- package/agents/ez-executor.md +487 -487
- package/agents/ez-frontend-agent.md +322 -0
- package/agents/ez-phase-researcher.md +553 -553
- package/agents/ez-planner.md +1307 -1307
- package/agents/ez-product-engineer.md +435 -0
- package/agents/ez-project-researcher.md +629 -629
- package/agents/ez-qa-agent.md +320 -0
- package/agents/ez-release-agent.md +333 -0
- package/agents/ez-requirements-agent.md +377 -0
- package/agents/ez-roadmapper.md +650 -650
- package/agents/ez-technical-writer.md +551 -0
- package/agents/ez-ux-expert.md +393 -0
- package/agents/ez-verifier.md +579 -579
- package/bin/guards/autonomy-guard.cjs +346 -0
- package/bin/guards/context-budget-guard.cjs +278 -0
- package/bin/guards/hallucination-guard.cjs +380 -0
- package/bin/guards/hidden-state-guard.cjs +182 -0
- package/bin/guards/team-overhead-guard.cjs +266 -0
- package/bin/guards/tool-sprawl-guard.cjs +271 -0
- package/bin/install.js +3221 -3272
- package/bin/lib/analytics/analytics-collector.cjs +86 -0
- package/bin/lib/analytics/analytics-reporter.cjs +130 -0
- package/bin/lib/analytics/cohort-analyzer.cjs +138 -0
- package/bin/lib/analytics/funnel-analyzer.cjs +147 -0
- package/bin/lib/analytics/nps-tracker.cjs +147 -0
- package/bin/lib/archetype-detector.cjs +289 -0
- package/bin/lib/assistant-adapter.cjs +361 -0
- package/bin/lib/audit-exec.cjs +175 -0
- package/bin/lib/auth.cjs +176 -0
- package/bin/lib/backup-service.cjs +422 -0
- package/bin/lib/bdd-validator.cjs +622 -0
- package/bin/lib/business-flow-mapper.cjs +429 -0
- package/bin/lib/circuit-breaker.cjs +276 -0
- package/bin/lib/code-complexity-analyzer.cjs +360 -0
- package/bin/lib/codebase-analyzer.cjs +241 -0
- package/bin/lib/commands.cjs +691 -0
- package/bin/lib/config.cjs +236 -0
- package/bin/lib/constraint-extractor.cjs +526 -0
- package/bin/lib/content-scanner.cjs +238 -0
- package/bin/lib/context-cache.cjs +154 -0
- package/bin/lib/context-compressor.cjs +102 -0
- package/bin/lib/context-deduplicator.cjs +105 -0
- package/bin/lib/context-errors.cjs +78 -0
- package/bin/lib/context-manager.cjs +338 -0
- package/bin/lib/context-metadata-tracker.cjs +140 -0
- package/bin/lib/context-relevance-scorer.cjs +99 -0
- package/bin/lib/core.cjs +507 -0
- package/bin/lib/cost-alerts.cjs +174 -0
- package/bin/lib/cost-tracker.cjs +275 -0
- package/bin/lib/crash-recovery.cjs +220 -0
- package/bin/lib/dependency-graph.cjs +319 -0
- package/bin/lib/deploy/deploy-audit-log.cjs +76 -0
- package/bin/lib/deploy/deploy-detector.cjs +69 -0
- package/bin/lib/deploy/deploy-env-manager.cjs +109 -0
- package/bin/lib/deploy/deploy-health-check.cjs +88 -0
- package/bin/lib/deploy/deploy-pre-flight.cjs +57 -0
- package/bin/lib/deploy/deploy-rollback.cjs +72 -0
- package/bin/lib/deploy/deploy-runner.cjs +97 -0
- package/bin/lib/deploy/deploy-status.cjs +74 -0
- package/bin/lib/discussion-synthesizer.cjs +439 -0
- package/bin/lib/error-cache.cjs +114 -0
- package/bin/lib/error-registry.cjs +177 -0
- package/bin/lib/file-access.cjs +207 -0
- package/bin/lib/file-lock.cjs +236 -0
- package/bin/lib/finops/budget-enforcer.cjs +126 -0
- package/bin/lib/finops/cost-reporter.cjs +132 -0
- package/bin/lib/finops/finops-analyzer.cjs +112 -0
- package/bin/lib/finops/spot-manager.cjs +118 -0
- package/bin/lib/framework-detector.cjs +396 -0
- package/bin/lib/frontmatter.cjs +313 -0
- package/bin/lib/fs-utils.cjs +153 -0
- package/bin/lib/gate-executor.cjs +272 -0
- package/bin/lib/gates/README.md +374 -0
- package/bin/lib/gates/gate-01-requirement.cjs +303 -0
- package/bin/lib/gates/gate-02-architecture.cjs +555 -0
- package/bin/lib/gates/gate-03-code.cjs +635 -0
- package/bin/lib/gates/gate-04-security.cjs +829 -0
- package/bin/lib/git-errors.cjs +83 -0
- package/bin/lib/git-utils.cjs +321 -0
- package/bin/lib/git-workflow-engine.cjs +1157 -0
- package/bin/lib/health-check.cjs +227 -0
- package/bin/lib/index.cjs +279 -0
- package/bin/lib/init.cjs +725 -0
- package/bin/lib/lock-logger.cjs +194 -0
- package/bin/lib/lock-state.cjs +263 -0
- package/bin/lib/lockfile-validator.cjs +227 -0
- package/bin/lib/log-rotation.cjs +71 -0
- package/bin/lib/logger.cjs +125 -0
- package/bin/lib/memory-compression.cjs +256 -0
- package/bin/lib/milestone.cjs +247 -0
- package/bin/lib/model-provider.cjs +241 -0
- package/bin/lib/package-manager-detector.cjs +203 -0
- package/bin/lib/package-manager-executor.cjs +385 -0
- package/bin/lib/package-manager-service.cjs +216 -0
- package/bin/lib/perf/api-monitor.cjs +88 -0
- package/bin/lib/perf/db-optimizer.cjs +78 -0
- package/bin/lib/perf/frontend-performance.cjs +56 -0
- package/bin/lib/perf/perf-analyzer.cjs +77 -0
- package/bin/lib/perf/perf-baseline.cjs +102 -0
- package/bin/lib/perf/perf-reporter.cjs +117 -0
- package/bin/lib/perf/regression-detector.cjs +92 -0
- package/bin/lib/phase.cjs +963 -0
- package/bin/lib/planning-write.cjs +123 -0
- package/bin/lib/project-reporter.cjs +565 -0
- package/bin/lib/quality-gate.cjs +332 -0
- package/bin/lib/quality-metrics.cjs +324 -0
- package/bin/lib/recovery-manager.cjs +98 -0
- package/bin/lib/release-validator.cjs +617 -0
- package/bin/lib/retry.cjs +119 -0
- package/bin/lib/roadmap.cjs +309 -0
- package/bin/lib/safe-exec.cjs +173 -0
- package/bin/lib/safe-path.cjs +130 -0
- package/bin/lib/security-errors.cjs +62 -0
- package/bin/lib/session-chain.cjs +304 -0
- package/bin/lib/session-errors.cjs +81 -0
- package/bin/lib/session-export.cjs +251 -0
- package/bin/lib/session-import.cjs +262 -0
- package/bin/lib/session-manager.cjs +280 -0
- package/bin/lib/skill-context.cjs +148 -0
- package/bin/lib/skill-matcher.cjs +236 -0
- package/bin/lib/skill-registry.cjs +360 -0
- package/bin/lib/skill-resolver.cjs +449 -0
- package/bin/lib/skill-triggers.cjs +90 -0
- package/bin/lib/skill-validator.cjs +270 -0
- package/bin/lib/skill-versioning.cjs +355 -0
- package/bin/lib/stack-detector.cjs +399 -0
- package/bin/lib/state.cjs +736 -0
- package/bin/lib/tech-debt-analyzer.cjs +309 -0
- package/bin/lib/temp-file.cjs +239 -0
- package/bin/lib/template.cjs +223 -0
- package/bin/lib/test-file-lock.cjs +112 -0
- package/bin/lib/test-graceful.cjs +93 -0
- package/bin/lib/test-logger.cjs +60 -0
- package/bin/lib/test-safe-exec.cjs +38 -0
- package/bin/lib/test-safe-path.cjs +33 -0
- package/bin/lib/test-temp-file.cjs +125 -0
- package/bin/lib/tier-manager.cjs +428 -0
- package/bin/lib/timeout-exec.cjs +63 -0
- package/bin/lib/tradeoff-analyzer.cjs +284 -0
- package/bin/lib/url-fetch.cjs +170 -0
- package/bin/lib/verify.cjs +863 -0
- package/bin/update.js +217 -214
- package/commands/deploy.cjs +53 -0
- package/commands/ez/add-tests.md +41 -41
- package/commands/ez/audit-milestone.md +36 -36
- package/commands/ez/complete-milestone.md +136 -136
- package/commands/ez/discuss-phase.md +90 -90
- package/commands/ez/execute-phase.md +52 -41
- package/commands/ez/help.md +22 -22
- package/commands/ez/map-codebase.md +71 -71
- package/commands/ez/new-milestone.md +44 -44
- package/commands/ez/new-project.md +51 -42
- package/commands/ez/plan-phase.md +53 -45
- package/commands/ez/progress.md +36 -24
- package/commands/ez/quick.md +45 -45
- package/commands/ez/resume-work.md +40 -40
- package/commands/ez/run-phase.md +580 -0
- package/commands/ez/settings.md +36 -36
- package/commands/ez/update.md +37 -37
- package/commands/ez/verify-work.md +402 -38
- package/commands/health-check.cjs +44 -0
- package/commands/rollback.cjs +47 -0
- package/ez-agents/bin/ez-tools.cjs +1692 -716
- package/ez-agents/bin/guards/autonomy-guard.cjs +346 -0
- package/ez-agents/bin/guards/context-budget-guard.cjs +247 -0
- package/ez-agents/bin/guards/hallucination-guard.cjs +271 -0
- package/ez-agents/bin/guards/hidden-state-guard.cjs +182 -0
- package/ez-agents/bin/guards/team-overhead-guard.cjs +266 -0
- package/ez-agents/bin/guards/tool-sprawl-guard.cjs +271 -0
- package/ez-agents/bin/lib/analytics/analytics-collector.cjs +86 -0
- package/ez-agents/bin/lib/analytics/analytics-reporter.cjs +130 -0
- package/ez-agents/bin/lib/analytics/cohort-analyzer.cjs +138 -0
- package/ez-agents/bin/lib/analytics/funnel-analyzer.cjs +147 -0
- package/ez-agents/bin/lib/analytics/nps-tracker.cjs +147 -0
- package/ez-agents/bin/lib/archetype-detector.cjs +289 -0
- package/ez-agents/bin/lib/audit-exec.cjs +166 -167
- package/ez-agents/bin/lib/auth.cjs +176 -176
- package/ez-agents/bin/lib/backup-service.cjs +422 -0
- package/ez-agents/bin/lib/bdd-validator.cjs +622 -0
- package/ez-agents/bin/lib/business-flow-mapper.cjs +429 -0
- package/ez-agents/bin/lib/code-complexity-analyzer.cjs +360 -0
- package/ez-agents/bin/lib/codebase-analyzer.cjs +241 -0
- package/ez-agents/bin/lib/commands.cjs +685 -685
- package/ez-agents/bin/lib/config.cjs +41 -1
- package/ez-agents/bin/lib/constraint-extractor.cjs +526 -0
- package/ez-agents/bin/lib/content-scanner.cjs +238 -0
- package/ez-agents/bin/lib/context-cache.cjs +154 -0
- package/ez-agents/bin/lib/context-errors.cjs +71 -0
- package/ez-agents/bin/lib/context-manager.cjs +220 -0
- package/ez-agents/bin/lib/core.cjs +507 -512
- package/ez-agents/bin/lib/cost-tracker.cjs +243 -0
- package/ez-agents/bin/lib/crash-recovery.cjs +172 -0
- package/ez-agents/bin/lib/dependency-graph.cjs +319 -0
- package/ez-agents/bin/lib/deploy/deploy-audit-log.cjs +76 -0
- package/ez-agents/bin/lib/deploy/deploy-detector.cjs +69 -0
- package/ez-agents/bin/lib/deploy/deploy-env-manager.cjs +109 -0
- package/ez-agents/bin/lib/deploy/deploy-health-check.cjs +88 -0
- package/ez-agents/bin/lib/deploy/deploy-pre-flight.cjs +57 -0
- package/ez-agents/bin/lib/deploy/deploy-rollback.cjs +72 -0
- package/ez-agents/bin/lib/deploy/deploy-runner.cjs +97 -0
- package/ez-agents/bin/lib/deploy/deploy-status.cjs +74 -0
- package/ez-agents/bin/lib/discussion-synthesizer.cjs +458 -0
- package/ez-agents/bin/lib/file-access.cjs +207 -0
- package/ez-agents/bin/lib/finops/budget-enforcer.cjs +126 -0
- package/ez-agents/bin/lib/finops/cost-reporter.cjs +132 -0
- package/ez-agents/bin/lib/finops/finops-analyzer.cjs +112 -0
- package/ez-agents/bin/lib/finops/spot-manager.cjs +118 -0
- package/ez-agents/bin/lib/framework-detector.cjs +396 -0
- package/ez-agents/bin/lib/frontmatter.cjs +3 -1
- package/ez-agents/bin/lib/gates/README.md +374 -0
- package/ez-agents/bin/lib/gates/gate-01-requirement.cjs +303 -0
- package/ez-agents/bin/lib/gates/gate-02-architecture.cjs +555 -0
- package/ez-agents/bin/lib/gates/gate-03-code.cjs +635 -0
- package/ez-agents/bin/lib/gates/gate-04-security.cjs +829 -0
- package/ez-agents/bin/lib/git-errors.cjs +83 -0
- package/ez-agents/bin/lib/git-utils.cjs +118 -0
- package/ez-agents/bin/lib/git-workflow-engine.cjs +1157 -0
- package/ez-agents/bin/lib/health-check.cjs +162 -162
- package/ez-agents/bin/lib/index.cjs +40 -2
- package/ez-agents/bin/lib/init.cjs +0 -2
- package/ez-agents/bin/lib/lockfile-validator.cjs +227 -0
- package/ez-agents/bin/lib/log-rotation.cjs +71 -0
- package/ez-agents/bin/lib/logger.cjs +99 -154
- package/ez-agents/bin/lib/memory-compression.cjs +256 -0
- package/ez-agents/bin/lib/package-manager-detector.cjs +203 -0
- package/ez-agents/bin/lib/package-manager-executor.cjs +385 -0
- package/ez-agents/bin/lib/package-manager-service.cjs +216 -0
- package/ez-agents/bin/lib/perf/api-monitor.cjs +88 -0
- package/ez-agents/bin/lib/perf/db-optimizer.cjs +78 -0
- package/ez-agents/bin/lib/perf/frontend-performance.cjs +56 -0
- package/ez-agents/bin/lib/perf/perf-analyzer.cjs +77 -0
- package/ez-agents/bin/lib/perf/perf-baseline.cjs +102 -0
- package/ez-agents/bin/lib/perf/perf-reporter.cjs +117 -0
- package/ez-agents/bin/lib/perf/regression-detector.cjs +92 -0
- package/ez-agents/bin/lib/project-reporter.cjs +502 -0
- package/ez-agents/bin/lib/quality-gate.cjs +332 -0
- package/ez-agents/bin/lib/recovery-manager.cjs +98 -0
- package/ez-agents/bin/lib/release-validator.cjs +617 -0
- package/ez-agents/bin/lib/safe-exec.cjs +128 -214
- package/ez-agents/bin/lib/security-errors.cjs +62 -0
- package/ez-agents/bin/lib/session-chain.cjs +304 -0
- package/ez-agents/bin/lib/session-errors.cjs +81 -0
- package/ez-agents/bin/lib/session-export.cjs +251 -0
- package/ez-agents/bin/lib/session-import.cjs +262 -0
- package/ez-agents/bin/lib/session-manager.cjs +280 -0
- package/ez-agents/bin/lib/skill-context.cjs +148 -0
- package/ez-agents/bin/lib/skill-matcher.cjs +236 -0
- package/ez-agents/bin/lib/skill-registry.cjs +341 -0
- package/ez-agents/bin/lib/skill-resolver.cjs +449 -0
- package/ez-agents/bin/lib/skill-triggers.cjs +90 -0
- package/ez-agents/bin/lib/skill-validator.cjs +270 -0
- package/ez-agents/bin/lib/skill-versioning.cjs +355 -0
- package/ez-agents/bin/lib/stack-detector.cjs +399 -0
- package/ez-agents/bin/lib/tech-debt-analyzer.cjs +309 -0
- package/ez-agents/bin/lib/tier-manager.cjs +428 -0
- package/ez-agents/bin/lib/tradeoff-analyzer.cjs +284 -0
- package/ez-agents/bin/lib/url-fetch.cjs +170 -0
- package/ez-agents/bin/lib/verify.cjs +863 -863
- package/ez-agents/references/decimal-phase-calculation.md +65 -65
- package/ez-agents/references/git-integration.md +248 -248
- package/ez-agents/references/git-planning-commit.md +38 -38
- package/ez-agents/references/metrics-schema.md +118 -0
- package/ez-agents/references/model-profile-resolution.md +34 -34
- package/ez-agents/references/model-profiles.md +93 -93
- package/ez-agents/references/phase-argument-parsing.md +61 -61
- package/ez-agents/references/planning-config.md +340 -200
- package/ez-agents/references/tier-strategy.md +103 -0
- package/ez-agents/references/ui-brand.md +160 -160
- package/ez-agents/references/verification-patterns.md +612 -612
- package/ez-agents/templates/DEBUG.md +164 -164
- package/ez-agents/templates/UAT.md +247 -247
- package/ez-agents/templates/agent-output-format.md +404 -0
- package/ez-agents/templates/bdd-feature.md +173 -0
- package/ez-agents/templates/codebase/architecture.md +255 -255
- package/ez-agents/templates/codebase/structure.md +285 -285
- package/ez-agents/templates/copilot-instructions.md +7 -7
- package/ez-agents/templates/debug-subagent-prompt.md +91 -91
- package/ez-agents/templates/discovery.md +146 -146
- package/ez-agents/templates/discussion.md +68 -0
- package/ez-agents/templates/handoff-protocol.md +294 -0
- package/ez-agents/templates/incident-runbook.md +205 -0
- package/ez-agents/templates/mode-workflow-templates.md +301 -0
- package/ez-agents/templates/phase-prompt.md +610 -610
- package/ez-agents/templates/planner-subagent-prompt.md +117 -117
- package/ez-agents/templates/project.md +184 -184
- package/ez-agents/templates/release-checklist.md +136 -0
- package/ez-agents/templates/research.md +552 -552
- package/ez-agents/templates/rollback-plan.md +201 -0
- package/ez-agents/templates/security-user-setup.md +244 -0
- package/ez-agents/templates/skill-validation-rules.md +476 -0
- package/ez-agents/templates/state.md +180 -176
- package/ez-agents/templates/summary-complex.md +59 -59
- package/ez-agents/tests/gates/gate-01-02.test.cjs +812 -0
- package/ez-agents/tests/gates/gate-03-04.test.cjs +762 -0
- package/ez-agents/tests/gates/gate-05-validator.test.cjs +145 -0
- package/ez-agents/tests/gates/gate-06-docs-validator.test.cjs +244 -0
- package/ez-agents/tests/gates/gate-07-release-validator.test.cjs +219 -0
- package/ez-agents/tests/guards/context-budget-guard.test.cjs +145 -0
- package/ez-agents/tests/guards/edge-case-guards.test.cjs +238 -0
- package/ez-agents/tests/guards/hallucination-guard.test.cjs +124 -0
- package/ez-agents/workflows/audit-milestone.md +1 -1
- package/ez-agents/workflows/autonomous.md +131 -30
- package/ez-agents/workflows/complete-milestone.md +1 -1
- package/ez-agents/workflows/discuss-phase.md +1 -1
- package/ez-agents/workflows/execute-phase.md +169 -3
- package/ez-agents/workflows/help.md +86 -133
- package/ez-agents/workflows/hotfix.md +291 -0
- package/ez-agents/workflows/new-milestone.md +340 -11
- package/ez-agents/workflows/new-project.md +294 -318
- package/ez-agents/workflows/plan-phase.md +22 -40
- package/ez-agents/workflows/progress.md +15 -25
- package/ez-agents/workflows/release.md +253 -0
- package/ez-agents/workflows/resume-session.md +215 -0
- package/ez-agents/workflows/run-phase.md +531 -0
- package/ez-agents/workflows/settings.md +2 -35
- package/hooks/dist/ez-check-update.js +81 -81
- package/hooks/dist/ez-context-monitor.js +148 -141
- package/hooks/dist/ez-statusline.js +115 -115
- package/package.json +78 -64
- package/scripts/fix-qwen-installation.js +144 -144
- package/agents/ez-integration-checker.md +0 -443
- package/agents/ez-nyquist-auditor.md +0 -176
- package/agents/ez-plan-checker.md +0 -706
- package/agents/ez-research-synthesizer.md +0 -247
- package/agents/ez-ui-auditor.md +0 -439
- package/agents/ez-ui-checker.md +0 -300
- package/agents/ez-ui-researcher.md +0 -353
- package/commands/ez/add-phase.md +0 -43
- package/commands/ez/add-todo.md +0 -47
- package/commands/ez/auth.md +0 -87
- package/commands/ez/autonomous.md +0 -41
- package/commands/ez/check-todos.md +0 -45
- package/commands/ez/cleanup.md +0 -18
- package/commands/ez/debug.md +0 -168
- package/commands/ez/health.md +0 -22
- package/commands/ez/insert-phase.md +0 -32
- package/commands/ez/join-discord.md +0 -18
- package/commands/ez/list-phase-assumptions.md +0 -46
- package/commands/ez/pause-work.md +0 -38
- package/commands/ez/plan-milestone-gaps.md +0 -34
- package/commands/ez/reapply-patches.md +0 -124
- package/commands/ez/remove-phase.md +0 -31
- package/commands/ez/research-phase.md +0 -190
- package/commands/ez/set-profile.md +0 -34
- package/commands/ez/stats.md +0 -18
- package/commands/ez/ui-phase.md +0 -34
- package/commands/ez/ui-review.md +0 -32
- package/commands/ez/validate-phase.md +0 -35
- package/ez-agents/templates/UI-SPEC.md +0 -100
- package/ez-agents/templates/VALIDATION.md +0 -76
- package/ez-agents/templates/context.md +0 -352
- package/ez-agents/templates/verification-report.md +0 -322
- package/ez-agents/workflows/research-phase.md +0 -74
- package/ez-agents/workflows/ui-phase.md +0 -290
- package/ez-agents/workflows/ui-review.md +0 -157
- package/ez-agents/workflows/validate-phase.md +0 -167
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Content Security Scanner
|
|
5
|
+
*
|
|
6
|
+
* Scans fetched content for XSS vectors, malicious scripts, and dangerous patterns.
|
|
7
|
+
* Detects script tags, JavaScript URLs, event handlers, and other security threats.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { SecurityScanError } = require('./context-errors.cjs');
|
|
11
|
+
|
|
12
|
+
class ContentSecurityScanner {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.maxSize = 1048576; // 1MB
|
|
15
|
+
|
|
16
|
+
// XSS detection patterns with severity levels
|
|
17
|
+
this.patterns = [
|
|
18
|
+
{
|
|
19
|
+
name: 'script_tag_open',
|
|
20
|
+
regex: /<script\b[^>]*>/gi,
|
|
21
|
+
severity: 'high',
|
|
22
|
+
description: 'Opening script tag'
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: 'script_tag_close',
|
|
26
|
+
regex: /<\/script>/gi,
|
|
27
|
+
severity: 'high',
|
|
28
|
+
description: 'Closing script tag'
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'javascript_url',
|
|
32
|
+
regex: /javascript\s*:/gi,
|
|
33
|
+
severity: 'high',
|
|
34
|
+
description: 'JavaScript URL protocol'
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'vbscript_url',
|
|
38
|
+
regex: /vbscript\s*:/gi,
|
|
39
|
+
severity: 'high',
|
|
40
|
+
description: 'VBScript URL protocol'
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'data_html_url',
|
|
44
|
+
regex: /data\s*:\s*text\/html/gi,
|
|
45
|
+
severity: 'high',
|
|
46
|
+
description: 'Data URL with HTML content'
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: 'event_handler',
|
|
50
|
+
regex: /\bon\w+\s*=/gi,
|
|
51
|
+
severity: 'medium',
|
|
52
|
+
description: 'Event handler attribute'
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: 'iframe_tag',
|
|
56
|
+
regex: /<iframe\b[^>]*>/gi,
|
|
57
|
+
severity: 'medium',
|
|
58
|
+
description: 'IFRAME tag'
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'embed_tag',
|
|
62
|
+
regex: /<embed\b[^>]*>/gi,
|
|
63
|
+
severity: 'medium',
|
|
64
|
+
description: 'EMBED tag'
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: 'object_tag',
|
|
68
|
+
regex: /<object\b[^>]*>/gi,
|
|
69
|
+
severity: 'medium',
|
|
70
|
+
description: 'OBJECT tag'
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: 'svg_tag',
|
|
74
|
+
regex: /<svg\b[^>]*>/gi,
|
|
75
|
+
severity: 'medium',
|
|
76
|
+
description: 'SVG tag (potential XSS vector)'
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: 'img_onerror',
|
|
80
|
+
regex: /<img[^>]*\s+onerror\s*=/gi,
|
|
81
|
+
severity: 'high',
|
|
82
|
+
description: 'IMG tag with onerror handler'
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: 'expression_css',
|
|
86
|
+
regex: /expression\s*\(/gi,
|
|
87
|
+
severity: 'medium',
|
|
88
|
+
description: 'CSS expression (IE XSS vector)'
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: 'eval_call',
|
|
92
|
+
regex: /\beval\s*\(/gi,
|
|
93
|
+
severity: 'high',
|
|
94
|
+
description: 'eval() call'
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: 'document_cookie',
|
|
98
|
+
regex: /document\.cookie/gi,
|
|
99
|
+
severity: 'medium',
|
|
100
|
+
description: 'Document cookie access'
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: 'window_location',
|
|
104
|
+
regex: /window\.location/gi,
|
|
105
|
+
severity: 'low',
|
|
106
|
+
description: 'Window location access'
|
|
107
|
+
}
|
|
108
|
+
];
|
|
109
|
+
|
|
110
|
+
// Binary content types to reject
|
|
111
|
+
this.binaryContentTypes = [
|
|
112
|
+
'application/octet-stream',
|
|
113
|
+
'image/',
|
|
114
|
+
'video/',
|
|
115
|
+
'audio/',
|
|
116
|
+
'application/pdf',
|
|
117
|
+
'application/zip',
|
|
118
|
+
'application/x-rar',
|
|
119
|
+
'application/x-executable'
|
|
120
|
+
];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Scan content for security issues
|
|
125
|
+
* @param {string} content - The content to scan
|
|
126
|
+
* @param {string} contentType - Optional content type header
|
|
127
|
+
* @returns {{safe: boolean, findings: Array}} - Scan results
|
|
128
|
+
*/
|
|
129
|
+
scan(content, contentType = '') {
|
|
130
|
+
const findings = [];
|
|
131
|
+
|
|
132
|
+
// Check content size
|
|
133
|
+
if (content && content.length > this.maxSize) {
|
|
134
|
+
return {
|
|
135
|
+
safe: false,
|
|
136
|
+
findings: [{
|
|
137
|
+
type: 'size_limit',
|
|
138
|
+
severity: 'high',
|
|
139
|
+
description: `Content exceeds maximum size (${content.length} > ${this.maxSize} bytes)`,
|
|
140
|
+
pattern: null,
|
|
141
|
+
matches: []
|
|
142
|
+
}]
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Check for binary content types
|
|
147
|
+
if (contentType) {
|
|
148
|
+
const lowerContentType = contentType.toLowerCase();
|
|
149
|
+
for (const binaryType of this.binaryContentTypes) {
|
|
150
|
+
if (lowerContentType.includes(binaryType.toLowerCase())) {
|
|
151
|
+
return {
|
|
152
|
+
safe: false,
|
|
153
|
+
findings: [{
|
|
154
|
+
type: 'binary_content',
|
|
155
|
+
severity: 'high',
|
|
156
|
+
description: `Binary content type detected: ${contentType}`,
|
|
157
|
+
pattern: null,
|
|
158
|
+
matches: []
|
|
159
|
+
}]
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Scan for XSS patterns
|
|
166
|
+
if (content) {
|
|
167
|
+
for (const pattern of this.patterns) {
|
|
168
|
+
// Reset regex lastIndex
|
|
169
|
+
pattern.regex.lastIndex = 0;
|
|
170
|
+
|
|
171
|
+
const matches = [];
|
|
172
|
+
let match;
|
|
173
|
+
|
|
174
|
+
while ((match = pattern.regex.exec(content)) !== null) {
|
|
175
|
+
matches.push(match[0]);
|
|
176
|
+
// Limit matches to prevent memory issues
|
|
177
|
+
if (matches.length >= 5) {
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (matches.length > 0) {
|
|
183
|
+
findings.push({
|
|
184
|
+
type: pattern.name,
|
|
185
|
+
severity: pattern.severity,
|
|
186
|
+
description: pattern.description,
|
|
187
|
+
pattern: pattern.regex.toString(),
|
|
188
|
+
matches: [...new Set(matches)] // Deduplicate
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return {
|
|
195
|
+
safe: findings.length === 0,
|
|
196
|
+
findings
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Get severity level for a pattern
|
|
202
|
+
* @param {string} patternName - The pattern name
|
|
203
|
+
* @returns {string} - 'high', 'medium', or 'low'
|
|
204
|
+
*/
|
|
205
|
+
getSeverity(patternName) {
|
|
206
|
+
const pattern = this.patterns.find(p => p.name === patternName);
|
|
207
|
+
if (!pattern) {
|
|
208
|
+
return 'low';
|
|
209
|
+
}
|
|
210
|
+
return pattern.severity;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Check if content is safe (convenience method)
|
|
215
|
+
* @param {string} content - The content to check
|
|
216
|
+
* @param {string} contentType - Optional content type
|
|
217
|
+
* @returns {boolean} - True if safe
|
|
218
|
+
*/
|
|
219
|
+
isSafe(content, contentType = '') {
|
|
220
|
+
return this.scan(content, contentType).safe;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Validate content and throw error if unsafe
|
|
225
|
+
* @param {string} content - The content to validate
|
|
226
|
+
* @param {string} contentType - Optional content type
|
|
227
|
+
* @throws {SecurityScanError} - If content is unsafe
|
|
228
|
+
*/
|
|
229
|
+
validate(content, contentType = '') {
|
|
230
|
+
const result = this.scan(content, contentType);
|
|
231
|
+
if (!result.safe) {
|
|
232
|
+
throw new SecurityScanError(result.findings);
|
|
233
|
+
}
|
|
234
|
+
return result;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
module.exports = ContentSecurityScanner;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Context Cache (Session-Only)
|
|
5
|
+
*
|
|
6
|
+
* Provides temporary, session-only caching for fetched content.
|
|
7
|
+
* Cache is stored in system temp directory and auto-cleared on process exit.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const os = require('os');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
|
|
14
|
+
class ContextCache {
|
|
15
|
+
constructor() {
|
|
16
|
+
// Cache stored in system temp directory with PID for isolation
|
|
17
|
+
this.cacheDir = path.join(os.tmpdir(), `ez-agents-context-${process.pid}`);
|
|
18
|
+
this.cache = new Map();
|
|
19
|
+
|
|
20
|
+
// Register process exit handlers
|
|
21
|
+
this._registerExitHandlers();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Register process exit handlers to clean up cache
|
|
26
|
+
* @private
|
|
27
|
+
*/
|
|
28
|
+
_registerExitHandlers() {
|
|
29
|
+
// Clean up on normal exit
|
|
30
|
+
process.on('exit', () => {
|
|
31
|
+
this.clear();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Clean up on SIGINT (Ctrl+C)
|
|
35
|
+
process.on('SIGINT', () => {
|
|
36
|
+
this.clear();
|
|
37
|
+
process.exit(130);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Clean up on SIGTERM
|
|
41
|
+
process.on('SIGTERM', () => {
|
|
42
|
+
this.clear();
|
|
43
|
+
process.exit(143);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Clean up on uncaught exceptions
|
|
47
|
+
process.on('uncaughtException', () => {
|
|
48
|
+
this.clear();
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Get cached content by key
|
|
54
|
+
* @param {string} key - The cache key (usually URL or file path)
|
|
55
|
+
* @returns {{content: string, timestamp: number, type: string, contentType?: string}|undefined}
|
|
56
|
+
*/
|
|
57
|
+
get(key) {
|
|
58
|
+
return this.cache.get(key);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Store content in cache
|
|
63
|
+
* @param {string} key - The cache key
|
|
64
|
+
* @param {string} content - The content to cache
|
|
65
|
+
* @param {Object} metadata - Additional metadata (type, contentType, etc.)
|
|
66
|
+
*/
|
|
67
|
+
set(key, content, metadata = {}) {
|
|
68
|
+
this.cache.set(key, {
|
|
69
|
+
content,
|
|
70
|
+
...metadata,
|
|
71
|
+
timestamp: Date.now()
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Check if key exists in cache
|
|
77
|
+
* @param {string} key - The cache key
|
|
78
|
+
* @returns {boolean} - True if key exists
|
|
79
|
+
*/
|
|
80
|
+
has(key) {
|
|
81
|
+
return this.cache.has(key);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Remove item from cache
|
|
86
|
+
* @param {string} key - The cache key
|
|
87
|
+
* @returns {boolean} - True if item was removed
|
|
88
|
+
*/
|
|
89
|
+
delete(key) {
|
|
90
|
+
return this.cache.delete(key);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Get the size of the cache
|
|
95
|
+
* @returns {number} - Number of items in cache
|
|
96
|
+
*/
|
|
97
|
+
size() {
|
|
98
|
+
return this.cache.size;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Clear all cached content and remove temp directory
|
|
103
|
+
*/
|
|
104
|
+
clear() {
|
|
105
|
+
// Clear the in-memory cache
|
|
106
|
+
this.cache.clear();
|
|
107
|
+
|
|
108
|
+
// Remove temp directory if it exists
|
|
109
|
+
if (fs.existsSync(this.cacheDir)) {
|
|
110
|
+
try {
|
|
111
|
+
fs.rmSync(this.cacheDir, { recursive: true, force: true });
|
|
112
|
+
} catch (err) {
|
|
113
|
+
// Ignore errors during cleanup (directory may already be gone)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Get cache directory path
|
|
120
|
+
* @returns {string} - Path to cache directory
|
|
121
|
+
*/
|
|
122
|
+
getCacheDir() {
|
|
123
|
+
return this.cacheDir;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Get all cache keys
|
|
128
|
+
* @returns {Array<string>} - Array of cache keys
|
|
129
|
+
*/
|
|
130
|
+
keys() {
|
|
131
|
+
return Array.from(this.cache.keys());
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Get all cached entries
|
|
136
|
+
* @returns {Array<{key: string, value: Object}>} - Array of key-value pairs
|
|
137
|
+
*/
|
|
138
|
+
entries() {
|
|
139
|
+
return Array.from(this.cache.entries()).map(([key, value]) => ({ key, value }));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Get cache statistics
|
|
144
|
+
* @returns {{size: number, keys: Array<string>}} - Cache statistics
|
|
145
|
+
*/
|
|
146
|
+
stats() {
|
|
147
|
+
return {
|
|
148
|
+
size: this.cache.size,
|
|
149
|
+
keys: this.keys()
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
module.exports = ContextCache;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Context Compressor — Compress context to reduce token usage
|
|
5
|
+
*
|
|
6
|
+
* Strategies:
|
|
7
|
+
* - Remove redundant information
|
|
8
|
+
* - Summarize verbose sections
|
|
9
|
+
* - Compress repeated patterns
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
class ContextCompressor {
|
|
13
|
+
/**
|
|
14
|
+
* Create a ContextCompressor instance
|
|
15
|
+
*/
|
|
16
|
+
constructor() {
|
|
17
|
+
this.compressionThreshold = 0.8; // Compress if over 80% of limit
|
|
18
|
+
this.defaultLimit = 100000; // Default token limit
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Compress context content
|
|
23
|
+
* @param {string} content - Content to compress
|
|
24
|
+
* @param {Object} options - Compression options
|
|
25
|
+
* @returns {string} Compressed content
|
|
26
|
+
*/
|
|
27
|
+
compress(content, options = {}) {
|
|
28
|
+
if (!content) return '';
|
|
29
|
+
|
|
30
|
+
let result = content;
|
|
31
|
+
const limit = options.limit || this.defaultLimit;
|
|
32
|
+
|
|
33
|
+
// Remove excessive whitespace
|
|
34
|
+
result = this._removeExtraWhitespace(result);
|
|
35
|
+
|
|
36
|
+
// Check if compression is needed
|
|
37
|
+
if (result.length < limit * this.compressionThreshold) {
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Apply aggressive compression
|
|
42
|
+
result = this._summarizeSections(result, options);
|
|
43
|
+
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Remove extra whitespace from content
|
|
49
|
+
* @param {string} content - Content to process
|
|
50
|
+
* @returns {string} Processed content
|
|
51
|
+
*/
|
|
52
|
+
_removeExtraWhitespace(content) {
|
|
53
|
+
return content
|
|
54
|
+
.replace(/\n{3,}/g, '\n\n') // Max 2 consecutive newlines
|
|
55
|
+
.replace(/[ \t]+$/gm, '') // Remove trailing whitespace
|
|
56
|
+
.replace(/^\s*\n/gm, ''); // Remove leading blank lines
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Summarize long sections
|
|
61
|
+
* @param {string} content - Content to summarize
|
|
62
|
+
* @param {Object} options - Options
|
|
63
|
+
* @returns {string} Summarized content
|
|
64
|
+
*/
|
|
65
|
+
_summarizeSections(content, options = {}) {
|
|
66
|
+
const maxLength = options.maxLength || 50000;
|
|
67
|
+
|
|
68
|
+
if (content.length <= maxLength) {
|
|
69
|
+
return content;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Keep first and last parts, summarize middle
|
|
73
|
+
const keepLength = Math.floor(maxLength / 3);
|
|
74
|
+
const start = content.slice(0, keepLength);
|
|
75
|
+
const end = content.slice(-keepLength);
|
|
76
|
+
const omitted = content.length - (keepLength * 2);
|
|
77
|
+
|
|
78
|
+
return `${start}\n\n[... ${omitted} characters omitted ...]\n\n${end}`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Get compression statistics
|
|
83
|
+
* @param {string} original - Original content
|
|
84
|
+
* @param {string} compressed - Compressed content
|
|
85
|
+
* @returns {Object} Compression statistics
|
|
86
|
+
*/
|
|
87
|
+
getStats(original, compressed) {
|
|
88
|
+
const originalLength = original?.length || 0;
|
|
89
|
+
const compressedLength = compressed?.length || 0;
|
|
90
|
+
const saved = originalLength - compressedLength;
|
|
91
|
+
const ratio = originalLength > 0 ? (saved / originalLength) * 100 : 0;
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
original: originalLength,
|
|
95
|
+
compressed: compressedLength,
|
|
96
|
+
saved,
|
|
97
|
+
ratio: Math.round(ratio * 100) / 100
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
module.exports = ContextCompressor;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Context Deduplicator — Remove duplicate context items
|
|
5
|
+
*
|
|
6
|
+
* Identifies and removes:
|
|
7
|
+
* - Exact duplicates
|
|
8
|
+
* - Near-duplicates (similar content)
|
|
9
|
+
* - Redundant information
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
class ContextDeduplicator {
|
|
13
|
+
/**
|
|
14
|
+
* Create a ContextDeduplicator instance
|
|
15
|
+
*/
|
|
16
|
+
constructor() {
|
|
17
|
+
this.seen = new Set();
|
|
18
|
+
this.similarityThreshold = 0.9; // 90% similar = duplicate
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Generate a hash for content
|
|
23
|
+
* @param {string} content - Content to hash
|
|
24
|
+
* @returns {string} Hash value
|
|
25
|
+
*/
|
|
26
|
+
_hash(content) {
|
|
27
|
+
// Simple hash for deduplication
|
|
28
|
+
let hash = 0;
|
|
29
|
+
for (let i = 0; i < content.length; i++) {
|
|
30
|
+
const char = content.charCodeAt(i);
|
|
31
|
+
hash = ((hash << 5) - hash) + char;
|
|
32
|
+
hash = hash & hash; // Convert to 32-bit integer
|
|
33
|
+
}
|
|
34
|
+
return hash.toString(36);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Check if content is a duplicate
|
|
39
|
+
* @param {string} content - Content to check
|
|
40
|
+
* @returns {boolean} True if duplicate
|
|
41
|
+
*/
|
|
42
|
+
isDuplicate(content) {
|
|
43
|
+
const hash = this._hash(content);
|
|
44
|
+
return this.seen.has(hash);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Mark content as seen
|
|
49
|
+
* @param {string} content - Content to mark
|
|
50
|
+
*/
|
|
51
|
+
markSeen(content) {
|
|
52
|
+
const hash = this._hash(content);
|
|
53
|
+
this.seen.add(hash);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Deduplicate an array of items
|
|
58
|
+
* @param {Array} items - Items to deduplicate
|
|
59
|
+
* @param {string} keyField - Field to use for deduplication
|
|
60
|
+
* @returns {Array} Deduplicated items
|
|
61
|
+
*/
|
|
62
|
+
deduplicate(items, keyField = 'content') {
|
|
63
|
+
const seen = new Set();
|
|
64
|
+
const result = [];
|
|
65
|
+
|
|
66
|
+
for (const item of items) {
|
|
67
|
+
const key = item[keyField] || JSON.stringify(item);
|
|
68
|
+
const hash = this._hash(key);
|
|
69
|
+
|
|
70
|
+
if (!seen.has(hash)) {
|
|
71
|
+
seen.add(hash);
|
|
72
|
+
result.push(item);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Clear the seen set
|
|
81
|
+
*/
|
|
82
|
+
clear() {
|
|
83
|
+
this.seen.clear();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Get deduplication statistics
|
|
88
|
+
* @param {Array} original - Original items
|
|
89
|
+
* @param {Array} deduplicated - Deduplicated items
|
|
90
|
+
* @returns {Object} Statistics
|
|
91
|
+
*/
|
|
92
|
+
getStats(original, deduplicated) {
|
|
93
|
+
const removed = original.length - deduplicated.length;
|
|
94
|
+
const ratio = original.length > 0 ? (removed / original.length) * 100 : 0;
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
original: original.length,
|
|
98
|
+
deduplicated: deduplicated.length,
|
|
99
|
+
removed,
|
|
100
|
+
ratio: Math.round(ratio * 100) / 100
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
module.exports = ContextDeduplicator;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Context Access Error Classes
|
|
5
|
+
*
|
|
6
|
+
* Provides structured error handling for context access operations
|
|
7
|
+
* including file access, URL fetching, and security scanning.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { SEVERITY, getErrorCode } = require('./error-registry.cjs');
|
|
11
|
+
|
|
12
|
+
class ContextAccessError extends Error {
|
|
13
|
+
constructor(message, options = {}) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = 'ContextAccessError';
|
|
16
|
+
this.code = options.code || getErrorCode('CONTEXT', 'ACCESS_DENIED')?.code || 'CONTEXT_ACCESS_ERROR';
|
|
17
|
+
this.severity = options.severity || getErrorCode('CONTEXT', 'ACCESS_DENIED')?.severity || SEVERITY.ERROR;
|
|
18
|
+
this.details = options.details || {};
|
|
19
|
+
this.timestamp = new Date().toISOString();
|
|
20
|
+
Error.captureStackTrace(this, ContextAccessError);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
toJSON() {
|
|
24
|
+
return {
|
|
25
|
+
name: this.name,
|
|
26
|
+
code: this.code,
|
|
27
|
+
severity: this.severity,
|
|
28
|
+
message: this.message,
|
|
29
|
+
details: this.details,
|
|
30
|
+
timestamp: this.timestamp
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
class URLFetchError extends ContextAccessError {
|
|
36
|
+
constructor(url, reason, options = {}) {
|
|
37
|
+
super(`Failed to fetch URL: ${reason}`, {
|
|
38
|
+
code: getErrorCode('CONTEXT', 'URL_FETCH_FAILED')?.code || 'URL_FETCH_ERROR',
|
|
39
|
+
severity: SEVERITY.ERROR,
|
|
40
|
+
details: { url, reason, ...options.details }
|
|
41
|
+
});
|
|
42
|
+
this.name = 'URLFetchError';
|
|
43
|
+
this.url = url;
|
|
44
|
+
this.reason = reason;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
class FileAccessError extends ContextAccessError {
|
|
49
|
+
constructor(path, reason, options = {}) {
|
|
50
|
+
super(`Failed to access file: ${reason}`, {
|
|
51
|
+
code: getErrorCode('CONTEXT', 'FILE_ACCESS_FAILED')?.code || 'FILE_ACCESS_ERROR',
|
|
52
|
+
severity: SEVERITY.ERROR,
|
|
53
|
+
details: { path, reason, ...options.details }
|
|
54
|
+
});
|
|
55
|
+
this.name = 'FileAccessError';
|
|
56
|
+
this.path = path;
|
|
57
|
+
this.reason = reason;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
class SecurityScanError extends ContextAccessError {
|
|
62
|
+
constructor(findings, options = {}) {
|
|
63
|
+
super(`Security scan failed: ${findings.length} issue(s) detected`, {
|
|
64
|
+
code: getErrorCode('CONTEXT', 'SECURITY_SCAN_FAILED')?.code || 'SECURITY_SCAN_ERROR',
|
|
65
|
+
severity: SEVERITY.CRITICAL,
|
|
66
|
+
details: { findings, ...options.details }
|
|
67
|
+
});
|
|
68
|
+
this.name = 'SecurityScanError';
|
|
69
|
+
this.findings = findings;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
module.exports = {
|
|
74
|
+
ContextAccessError,
|
|
75
|
+
URLFetchError,
|
|
76
|
+
FileAccessError,
|
|
77
|
+
SecurityScanError
|
|
78
|
+
};
|