@aiwg/cli 0.0.0-bootstrap.0 → 2026.7.17
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 +21 -1
- package/bin/aiwg.mjs +349 -0
- package/dist/src/a2a/agent-card.js +145 -0
- package/dist/src/a2a/client.js +411 -0
- package/dist/src/a2a/hitl-cli.js +171 -0
- package/dist/src/a2a/hitl-driver.js +370 -0
- package/dist/src/a2a/hitl.js +181 -0
- package/dist/src/a2a/http.js +193 -0
- package/dist/src/a2a/jcs.js +128 -0
- package/dist/src/a2a/jws.js +187 -0
- package/dist/src/a2a/types.js +24 -0
- package/dist/src/a2a/webhook.js +240 -0
- package/dist/src/activity-log/cli.js +348 -0
- package/dist/src/activity-log/parser.js +81 -0
- package/dist/src/activity-log/types.js +50 -0
- package/dist/src/agents/agent-deployer.js +367 -0
- package/dist/src/agents/agent-packager.js +271 -0
- package/dist/src/agents/agent-validator.js +271 -0
- package/dist/src/agents/grounding/knowledge-base.js +161 -0
- package/dist/src/agents/grounding/types.js +12 -0
- package/dist/src/agents/index.js +10 -0
- package/dist/src/agents/packaged-agent-inventory.js +75 -0
- package/dist/src/agents/types.js +7 -0
- package/dist/src/api/index.d.ts +10 -0
- package/dist/src/api/index.js +10 -0
- package/dist/src/artifacts/address-parser.js +73 -0
- package/dist/src/artifacts/audit/cli.js +183 -0
- package/dist/src/artifacts/audit/drift.js +122 -0
- package/dist/src/artifacts/audit/types.js +12 -0
- package/dist/src/artifacts/backends/graphology-backend.js +160 -0
- package/dist/src/artifacts/backends/json-backend.js +129 -0
- package/dist/src/artifacts/backends/sqlite-backend.js +199 -0
- package/dist/src/artifacts/browser-export.js +622 -0
- package/dist/src/artifacts/capability-resolver.js +94 -0
- package/dist/src/artifacts/checksum-manifest.js +91 -0
- package/dist/src/artifacts/citation-parser.js +162 -0
- package/dist/src/artifacts/cli.js +1462 -0
- package/dist/src/artifacts/corpus-tools/citation-densify.js +311 -0
- package/dist/src/artifacts/corpus-tools/cli.js +393 -0
- package/dist/src/artifacts/corpus-tools/corpus-graph.js +225 -0
- package/dist/src/artifacts/corpus-tools/curator.js +186 -0
- package/dist/src/artifacts/corpus-tools/discovery-log.js +70 -0
- package/dist/src/artifacts/corpus-tools/funder-network.js +141 -0
- package/dist/src/artifacts/corpus-tools/induction-audit.js +233 -0
- package/dist/src/artifacts/corpus-tools/integrity-scan.js +202 -0
- package/dist/src/artifacts/corpus-tools/profile-communities.js +166 -0
- package/dist/src/artifacts/corpus-tools/profile-edges.js +72 -0
- package/dist/src/artifacts/corpus-tools/profile-embed.js +113 -0
- package/dist/src/artifacts/corpus-tools/profile-generate-fm.js +167 -0
- package/dist/src/artifacts/corpus-tools/profile-generate.js +181 -0
- package/dist/src/artifacts/corpus-tools/profile-metrics.js +98 -0
- package/dist/src/artifacts/corpus-tools/profile-status.js +86 -0
- package/dist/src/artifacts/corpus-tools/profile-temporal.js +139 -0
- package/dist/src/artifacts/corpus-tools/radar-init.js +93 -0
- package/dist/src/artifacts/corpus-tools/radar-report.js +118 -0
- package/dist/src/artifacts/corpus-tools/radar-shared.js +189 -0
- package/dist/src/artifacts/corpus-tools/radar-status.js +68 -0
- package/dist/src/artifacts/corpus-tools/sidecar-lint.js +233 -0
- package/dist/src/artifacts/corpus-tools/sidecar-repair.js +277 -0
- package/dist/src/artifacts/corpus-tools/snapshot.js +591 -0
- package/dist/src/artifacts/corpus-tools/source-types.js +164 -0
- package/dist/src/artifacts/corpus-tools/vision-extract.js +243 -0
- package/dist/src/artifacts/corpus-views/build.js +126 -0
- package/dist/src/artifacts/corpus-views/corpus-config.js +124 -0
- package/dist/src/artifacts/corpus-views/ref-parser.js +437 -0
- package/dist/src/artifacts/corpus-views/renderers.js +353 -0
- package/dist/src/artifacts/corpus-views/taxonomies.js +131 -0
- package/dist/src/artifacts/dep-graph.js +173 -0
- package/dist/src/artifacts/discover-facets.js +375 -0
- package/dist/src/artifacts/embedding-index.js +354 -0
- package/dist/src/artifacts/enrichment/cli.js +240 -0
- package/dist/src/artifacts/enrichment/prompt.js +47 -0
- package/dist/src/artifacts/enrichment/store.js +90 -0
- package/dist/src/artifacts/enrichment/types.js +12 -0
- package/dist/src/artifacts/fortemi-core-query-adapter.js +475 -0
- package/dist/src/artifacts/fortemi-core-sync.js +251 -0
- package/dist/src/artifacts/fortemi-shard-export.js +44 -0
- package/dist/src/artifacts/fulltext.js +108 -0
- package/dist/src/artifacts/graph-backend.js +51 -0
- package/dist/src/artifacts/graph-query.js +247 -0
- package/dist/src/artifacts/hybrid-query.js +225 -0
- package/dist/src/artifacts/index-builder.js +1089 -0
- package/dist/src/artifacts/index-reader.js +112 -0
- package/dist/src/artifacts/index-status.js +193 -0
- package/dist/src/artifacts/legacy-index-migration.js +169 -0
- package/dist/src/artifacts/move.js +154 -0
- package/dist/src/artifacts/operational-state.js +239 -0
- package/dist/src/artifacts/prebuilt-build-lock.js +49 -0
- package/dist/src/artifacts/query-engine.js +1955 -0
- package/dist/src/artifacts/source-graph.js +529 -0
- package/dist/src/artifacts/stats.js +169 -0
- package/dist/src/artifacts/types.js +606 -0
- package/dist/src/artifacts/views/cli.js +293 -0
- package/dist/src/artifacts/views/definition.js +170 -0
- package/dist/src/artifacts/views/store.js +149 -0
- package/dist/src/artifacts/views/types.js +8 -0
- package/dist/src/artifacts/watcher.js +255 -0
- package/dist/src/catalog/builtin-models.json +636 -0
- package/dist/src/catalog/cli.js +228 -0
- package/dist/src/catalog/cli.mjs +289 -0
- package/dist/src/catalog/index.js +15 -0
- package/dist/src/catalog/loader.js +217 -0
- package/dist/src/catalog/loader.mjs +251 -0
- package/dist/src/catalog/sources.json +41 -0
- package/dist/src/catalog/types.js +8 -0
- package/dist/src/channel/manager.mjs +504 -0
- package/dist/src/cli/agent-spawn.js +178 -0
- package/dist/src/cli/cli-extension-loader.js +245 -0
- package/dist/src/cli/command-log.js +275 -0
- package/dist/src/cli/config-loader.js +232 -0
- package/dist/src/cli/env.js +82 -0
- package/dist/src/cli/errors.js +150 -0
- package/dist/src/cli/find-package-root.js +40 -0
- package/dist/src/cli/git-hooks.js +250 -0
- package/dist/src/cli/handlers/agentcard.js +206 -0
- package/dist/src/cli/handlers/artifacts.js +76 -0
- package/dist/src/cli/handlers/best-practices-audit.js +280 -0
- package/dist/src/cli/handlers/cockpit.js +137 -0
- package/dist/src/cli/handlers/command-log.js +37 -0
- package/dist/src/cli/handlers/daemon.js +59 -0
- package/dist/src/cli/handlers/diagnose.js +300 -0
- package/dist/src/cli/handlers/execution-mode.js +105 -0
- package/dist/src/cli/handlers/feedback.js +341 -0
- package/dist/src/cli/handlers/help.js +147 -0
- package/dist/src/cli/handlers/index.js +302 -0
- package/dist/src/cli/handlers/init.js +179 -0
- package/dist/src/cli/handlers/install.js +129 -0
- package/dist/src/cli/handlers/issues.js +46 -0
- package/dist/src/cli/handlers/lint.js +42 -0
- package/dist/src/cli/handlers/local-executor.js +315 -0
- package/dist/src/cli/handlers/marketplace.js +168 -0
- package/dist/src/cli/handlers/mc.js +1010 -0
- package/dist/src/cli/handlers/models.js +352 -0
- package/dist/src/cli/handlers/packages.js +155 -0
- package/dist/src/cli/handlers/ralph-launcher.js +717 -0
- package/dist/src/cli/handlers/ralph.js +575 -0
- package/dist/src/cli/handlers/refresh.js +432 -0
- package/dist/src/cli/handlers/regenerate.js +336 -0
- package/dist/src/cli/handlers/repo-access.js +109 -0
- package/dist/src/cli/handlers/run.js +165 -0
- package/dist/src/cli/handlers/runtime-info.js +301 -0
- package/dist/src/cli/handlers/sandbox.js +197 -0
- package/dist/src/cli/handlers/scaffolding.js +149 -0
- package/dist/src/cli/handlers/script-runner.js +121 -0
- package/dist/src/cli/handlers/sdlc-accelerate.js +148 -0
- package/dist/src/cli/handlers/serve.js +1835 -0
- package/dist/src/cli/handlers/session.js +348 -0
- package/dist/src/cli/handlers/setup.js +440 -0
- package/dist/src/cli/handlers/skill-lint.js +367 -0
- package/dist/src/cli/handlers/skill-usage.js +74 -0
- package/dist/src/cli/handlers/steward.js +567 -0
- package/dist/src/cli/handlers/subcommands.js +1702 -0
- package/dist/src/cli/handlers/team.js +337 -0
- package/dist/src/cli/handlers/types.js +11 -0
- package/dist/src/cli/handlers/use.js +2772 -0
- package/dist/src/cli/handlers/utilities.js +703 -0
- package/dist/src/cli/handlers/version.js +134 -0
- package/dist/src/cli/handlers/workspace-context.js +93 -0
- package/dist/src/cli/handlers/workspace.js +126 -0
- package/dist/src/cli/help-generator.js +178 -0
- package/dist/src/cli/hooks/builtin/activity-log-hook.js +126 -0
- package/dist/src/cli/hooks/executor.js +96 -0
- package/dist/src/cli/hooks/index.js +15 -0
- package/dist/src/cli/hooks/registry.js +143 -0
- package/dist/src/cli/hooks/types.js +13 -0
- package/dist/src/cli/log.js +492 -0
- package/dist/src/cli/project-isolation/detect.js +70 -0
- package/dist/src/cli/project-isolation/index.js +7 -0
- package/dist/src/cli/project-isolation/signals.js +17 -0
- package/dist/src/cli/project-isolation/warning.js +102 -0
- package/dist/src/cli/prompt-utils.js +155 -0
- package/dist/src/cli/provider-deployment-plan.js +126 -0
- package/dist/src/cli/provider-resolution.js +119 -0
- package/dist/src/cli/router.js +305 -0
- package/dist/src/cli/scope-resolver.js +392 -0
- package/dist/src/cli/skill-usage.js +616 -0
- package/dist/src/cli/ui.js +224 -0
- package/dist/src/cli/watch-service.js +203 -0
- package/dist/src/cli/workflow-orchestrator.js +478 -0
- package/dist/src/cli/workspace-signals.js +321 -0
- package/dist/src/community/footer.js +14 -0
- package/dist/src/community/links.js +123 -0
- package/dist/src/community/milestones.js +46 -0
- package/dist/src/community/nudge-policy.js +93 -0
- package/dist/src/config/aiwg-config.js +883 -0
- package/dist/src/config/cli.js +703 -0
- package/dist/src/config/gitignore.js +156 -0
- package/dist/src/config/project-artifacts.js +76 -0
- package/dist/src/config/user-config.js +428 -0
- package/dist/src/config/user-registry.js +127 -0
- package/dist/src/config/workspace.js +276 -0
- package/dist/src/contributors/detect.js +39 -0
- package/dist/src/contributors/discover.js +172 -0
- package/dist/src/contributors/heuristic.js +186 -0
- package/dist/src/contributors/index.js +11 -0
- package/dist/src/contributors/types.js +13 -0
- package/dist/src/contributors/validation.js +116 -0
- package/dist/src/data/community.schema.json +43 -0
- package/dist/src/data/community.yaml +16 -0
- package/dist/src/extensions/capability-index.js +270 -0
- package/dist/src/extensions/claude-hooks-installer.js +268 -0
- package/dist/src/extensions/commands/definitions.js +3485 -0
- package/dist/src/extensions/deployment-registration.js +463 -0
- package/dist/src/extensions/index.js +22 -0
- package/dist/src/extensions/loader.js +132 -0
- package/dist/src/extensions/managed-marker.js +100 -0
- package/dist/src/extensions/manifest.js +196 -0
- package/dist/src/extensions/project-local-activity.js +114 -0
- package/dist/src/extensions/project-local-discovery.js +261 -0
- package/dist/src/extensions/project-local-doctor.js +281 -0
- package/dist/src/extensions/project-local-gitignore.js +176 -0
- package/dist/src/extensions/project-local-paths.js +121 -0
- package/dist/src/extensions/project-local-promote.js +218 -0
- package/dist/src/extensions/project-local-remove.js +373 -0
- package/dist/src/extensions/project-local-scaffold.js +252 -0
- package/dist/src/extensions/project-quickref.js +291 -0
- package/dist/src/extensions/registry.js +368 -0
- package/dist/src/extensions/shadow-resolver.js +271 -0
- package/dist/src/extensions/types.js +86 -0
- package/dist/src/extensions/upstream-registry.js +195 -0
- package/dist/src/extensions/validation.js +631 -0
- package/dist/src/features/catalog.js +88 -0
- package/dist/src/features/cli.js +197 -0
- package/dist/src/features/installer.js +57 -0
- package/dist/src/features/paths.js +14 -0
- package/dist/src/features/runtime.js +21 -0
- package/dist/src/features/status.js +134 -0
- package/dist/src/hooks/laziness-detection.js +532 -0
- package/dist/src/intake/git-history-analyzer.js +486 -0
- package/dist/src/intake/index.js +9 -0
- package/dist/src/issues/cli.js +327 -0
- package/dist/src/issues/index.js +5 -0
- package/dist/src/issues/live.js +154 -0
- package/dist/src/issues/local.js +666 -0
- package/dist/src/issues/sync.js +143 -0
- package/dist/src/issues/types.js +2 -0
- package/dist/src/issues/workflows.js +164 -0
- package/dist/src/kb/cli.js +173 -0
- package/dist/src/lint/cli.js +171 -0
- package/dist/src/lint/loader.js +225 -0
- package/dist/src/lint/reporters.js +141 -0
- package/dist/src/lint/runner.js +364 -0
- package/dist/src/lint/types.js +10 -0
- package/dist/src/marketplace/cache.js +110 -0
- package/dist/src/marketplace/identifier.js +63 -0
- package/dist/src/marketplace/registry.js +36 -0
- package/dist/src/marketplace/sources/clawhub.js +53 -0
- package/dist/src/marketplace/sources/git.js +45 -0
- package/dist/src/marketplace/types.js +9 -0
- package/dist/src/mcp/adapters/codex-runtime.js +224 -0
- package/dist/src/mcp/cli.mjs +1197 -0
- package/dist/src/mcp/elicitation.mjs +149 -0
- package/dist/src/mcp/helpers.mjs +287 -0
- package/dist/src/mcp/index.mjs +11 -0
- package/dist/src/mcp/profiles.js +263 -0
- package/dist/src/mcp/profiles.mjs +360 -0
- package/dist/src/mcp/registry.js +376 -0
- package/dist/src/mcp/registry.mjs +387 -0
- package/dist/src/mcp/server.mjs +633 -0
- package/dist/src/mcp/test-simple.mjs +271 -0
- package/dist/src/mcp/tools/command-run.mjs +101 -0
- package/dist/src/mcp/tools/discovery.mjs +291 -0
- package/dist/src/mcp/tools/interaction.mjs +87 -0
- package/dist/src/mcp/tools/orchestration.mjs +320 -0
- package/dist/src/mcp/tools/subsystems.mjs +640 -0
- package/dist/src/memory/cli.js +166 -0
- package/dist/src/memory/project-registry.js +282 -0
- package/dist/src/metrics/artifact-metrics.js +184 -0
- package/dist/src/metrics/context-budget.js +174 -0
- package/dist/src/metrics/token-counter.js +133 -0
- package/dist/src/models/config-loader.js +228 -0
- package/dist/src/models/index.js +22 -0
- package/dist/src/models/model-capabilities.v1.json +120 -0
- package/dist/src/models/model-catalog.v1.json +96 -0
- package/dist/src/models/model-discovery.js +521 -0
- package/dist/src/models/provider-models.js +73 -0
- package/dist/src/models/provider-policy.js +273 -0
- package/dist/src/models/resolver.js +245 -0
- package/dist/src/models/router.js +70 -0
- package/dist/src/models/types.js +8 -0
- package/dist/src/models/wrapper-deployment.js +178 -0
- package/dist/src/models/wrapper-route.js +54 -0
- package/dist/src/ops/cli.js +268 -0
- package/dist/src/ops/registry.js +623 -0
- package/dist/src/packages/adapters/clawhub.js +113 -0
- package/dist/src/packages/adapters/git.js +153 -0
- package/dist/src/packages/adapters/gitea.js +93 -0
- package/dist/src/packages/adapters/github.js +69 -0
- package/dist/src/packages/adapters/local-cache.js +89 -0
- package/dist/src/packages/package-registry.js +143 -0
- package/dist/src/packages/registry.js +238 -0
- package/dist/src/packages/types.js +11 -0
- package/dist/src/plugin/cross-framework-ops.js +475 -0
- package/dist/src/plugin/framework-config-loader.js +235 -0
- package/dist/src/plugin/framework-detector.js +186 -0
- package/dist/src/plugin/framework-isolator.js +341 -0
- package/dist/src/plugin/framework-migration.js +371 -0
- package/dist/src/plugin/metadata-validator.js +906 -0
- package/dist/src/plugin/plugin-installer.js +436 -0
- package/dist/src/plugin/plugin-status.js +369 -0
- package/dist/src/plugin/plugin-uninstaller.js +473 -0
- package/dist/src/plugin/registry-validator.js +344 -0
- package/dist/src/plugin/skill-command-translator.js +415 -0
- package/dist/src/plugin/workspace-creator.js +189 -0
- package/dist/src/plugin/workspace-migrator.js +821 -0
- package/dist/src/policy/authorization.js +390 -0
- package/dist/src/policy/repo-access.js +215 -0
- package/dist/src/provenance/cli.js +16 -0
- package/dist/src/providers/capability-matrix.js +300 -0
- package/dist/src/providers/capability-matrix.yaml +514 -0
- package/dist/src/providers/provider-definitions.js +977 -0
- package/dist/src/providers/provider-definitions.mjs +159 -0
- package/dist/src/providers/provider-inventory.js +169 -0
- package/dist/src/quality/feedback-ab.js +174 -0
- package/dist/src/quality/feedback-collector.js +176 -0
- package/dist/src/quality/feedback-tracker.js +123 -0
- package/dist/src/quality/patterns/adr.json +24 -0
- package/dist/src/quality/patterns/sad.json +24 -0
- package/dist/src/quality/patterns/test-plan.json +24 -0
- package/dist/src/quality/patterns/use-case.json +24 -0
- package/dist/src/quality/scoring.js +157 -0
- package/dist/src/reflections/cli.js +15 -0
- package/dist/src/release/plan.js +139 -0
- package/dist/src/research/cache/manager.js +227 -0
- package/dist/src/research/clients/arxiv.js +156 -0
- package/dist/src/research/clients/base.js +197 -0
- package/dist/src/research/clients/crossref.js +112 -0
- package/dist/src/research/clients/semantic-scholar.js +126 -0
- package/dist/src/research/clients/unpaywall.js +87 -0
- package/dist/src/research/index.js +14 -0
- package/dist/src/research/query-cli.js +336 -0
- package/dist/src/research/services/acquisition.js +313 -0
- package/dist/src/research/services/archival.js +225 -0
- package/dist/src/research/services/citation.js +279 -0
- package/dist/src/research/services/discovery.js +243 -0
- package/dist/src/research/services/documentation.js +269 -0
- package/dist/src/research/services/index.js +14 -0
- package/dist/src/research/services/provenance.js +279 -0
- package/dist/src/research/services/quality.js +370 -0
- package/dist/src/research/services/types.js +7 -0
- package/dist/src/research/storage-cli.js +20 -0
- package/dist/src/research/types.js +47 -0
- package/dist/src/resources/index.d.ts +2 -0
- package/dist/src/resources/index.js +2 -0
- package/dist/src/resources/web-release.d.ts +89 -0
- package/dist/src/resources/web-release.js +882 -0
- package/dist/src/rlm/cache/cli.js +162 -0
- package/dist/src/rlm/cache/hash.js +35 -0
- package/dist/src/rlm/cache/store.js +170 -0
- package/dist/src/rlm/cache/types.js +8 -0
- package/dist/src/rlm/cli.js +650 -0
- package/dist/src/serve/a2a-terminal-observer.js +120 -0
- package/dist/src/serve/agent-router.js +205 -0
- package/dist/src/serve/dispatch-router.js +171 -0
- package/dist/src/serve/executor-registry.js +715 -0
- package/dist/src/serve/mission-conductor.js +177 -0
- package/dist/src/serve/orchestrator-adapter.js +113 -0
- package/dist/src/serve/orchestrator-override.js +94 -0
- package/dist/src/serve/orchestrator-pty.js +133 -0
- package/dist/src/serve/pty-bridge.js +799 -0
- package/dist/src/serve/sandbox-registry.js +832 -0
- package/dist/src/serve/screen-reader.js +228 -0
- package/dist/src/serve/stack-adapters.js +68 -0
- package/dist/src/serve/telemetry.js +143 -0
- package/dist/src/skills/adapters/clawhub.js +250 -0
- package/dist/src/skills/adapters/local.js +335 -0
- package/dist/src/skills/adapters/openclaw.js +316 -0
- package/dist/src/skills/cli.js +334 -0
- package/dist/src/skills/registry.js +117 -0
- package/dist/src/skills/run.js +259 -0
- package/dist/src/skills/runtime.js +94 -0
- package/dist/src/skills/types.js +10 -0
- package/dist/src/smiths/agentsmith/demo.js +116 -0
- package/dist/src/smiths/agentsmith/examples.js +300 -0
- package/dist/src/smiths/agentsmith/generator.js +503 -0
- package/dist/src/smiths/agentsmith/index.js +11 -0
- package/dist/src/smiths/agentsmith/types.js +8 -0
- package/dist/src/smiths/commandsmith/example.js +220 -0
- package/dist/src/smiths/commandsmith/generator.js +288 -0
- package/dist/src/smiths/commandsmith/index.js +41 -0
- package/dist/src/smiths/commandsmith/templates.js +296 -0
- package/dist/src/smiths/commandsmith/types.js +7 -0
- package/dist/src/smiths/context-pipeline/aiwg-md.js +104 -0
- package/dist/src/smiths/context-pipeline/allowlist.js +195 -0
- package/dist/src/smiths/context-pipeline/claude-hook.js +127 -0
- package/dist/src/smiths/context-pipeline/discovery.js +187 -0
- package/dist/src/smiths/context-pipeline/external-links-section.js +49 -0
- package/dist/src/smiths/context-pipeline/finalization.js +147 -0
- package/dist/src/smiths/context-pipeline/generator.js +477 -0
- package/dist/src/smiths/context-pipeline/index.js +30 -0
- package/dist/src/smiths/context-pipeline/legacy-inject.js +103 -0
- package/dist/src/smiths/context-pipeline/managed-hook.js +95 -0
- package/dist/src/smiths/context-pipeline/overflow.js +212 -0
- package/dist/src/smiths/context-pipeline/parallelism-section.js +94 -0
- package/dist/src/smiths/context-pipeline/provider-policy.js +64 -0
- package/dist/src/smiths/context-pipeline/sanitizer.js +93 -0
- package/dist/src/smiths/context-pipeline/types.js +23 -0
- package/dist/src/smiths/context-pipeline/workspace-context.js +988 -0
- package/dist/src/smiths/hook-bridge/codex-translator.js +129 -0
- package/dist/src/smiths/hook-bridge/copilot-translator.js +64 -0
- package/dist/src/smiths/hook-bridge/factory-translator.js +43 -0
- package/dist/src/smiths/hook-bridge/hermes-translator.js +88 -0
- package/dist/src/smiths/hook-bridge/index.js +79 -0
- package/dist/src/smiths/hook-bridge/loader.js +116 -0
- package/dist/src/smiths/hook-bridge/shim.js +89 -0
- package/dist/src/smiths/hook-bridge/types.js +31 -0
- package/dist/src/smiths/index.js +39 -0
- package/dist/src/smiths/mcpsmith/analyzers/cli-analyzer.js +390 -0
- package/dist/src/smiths/mcpsmith/example.js +119 -0
- package/dist/src/smiths/mcpsmith/generator.js +236 -0
- package/dist/src/smiths/mcpsmith/index.js +17 -0
- package/dist/src/smiths/mcpsmith/types.js +10 -0
- package/dist/src/smiths/platform-paths.js +101 -0
- package/dist/src/smiths/skillsmith/codex-sidecar.js +85 -0
- package/dist/src/smiths/skillsmith/collision-detector.js +249 -0
- package/dist/src/smiths/skillsmith/demo.js +83 -0
- package/dist/src/smiths/skillsmith/examples.js +161 -0
- package/dist/src/smiths/skillsmith/generator.js +316 -0
- package/dist/src/smiths/skillsmith/index.js +12 -0
- package/dist/src/smiths/skillsmith/namespace-adapter.js +180 -0
- package/dist/src/smiths/skillsmith/platform-resolver.js +157 -0
- package/dist/src/smiths/skillsmith/types.js +9 -0
- package/dist/src/smiths/toolsmith/index.js +10 -0
- package/dist/src/smiths/toolsmith/runtime-discovery.mjs +710 -0
- package/dist/src/smiths/toolsmith/types.js +8 -0
- package/dist/src/storage/backends/fortemi.js +227 -0
- package/dist/src/storage/backends/fs.js +134 -0
- package/dist/src/storage/backends/logseq.js +309 -0
- package/dist/src/storage/backends/obsidian.js +233 -0
- package/dist/src/storage/cli.js +468 -0
- package/dist/src/storage/config.js +272 -0
- package/dist/src/storage/index.js +108 -0
- package/dist/src/storage/subsystem-cli.js +201 -0
- package/dist/src/storage/types.js +33 -0
- package/dist/src/testing/corpus/corpus-builder.js +383 -0
- package/dist/src/testing/corpus/ground-truth-manager.js +460 -0
- package/dist/src/testing/corpus/index.js +10 -0
- package/dist/src/testing/fixtures/index.js +9 -0
- package/dist/src/testing/fixtures/test-data-factory.js +472 -0
- package/dist/src/testing/generators/index.js +11 -0
- package/dist/src/testing/generators/test-case-generator.js +393 -0
- package/dist/src/testing/generators/test-code-generator.js +384 -0
- package/dist/src/testing/generators/use-case-parser.js +325 -0
- package/dist/src/testing/index.js +11 -0
- package/dist/src/tracker/capability-protocol.js +118 -0
- package/dist/src/update/checker.mjs +396 -0
- package/dist/src/update/notifier.mjs +235 -0
- package/dist/src/writing/content-diversifier.js +804 -0
- package/dist/src/writing/example-generator.js +959 -0
- package/dist/src/writing/example-templates.js +99 -0
- package/dist/src/writing/pattern-library.js +486 -0
- package/dist/src/writing/patterns/banned-phrases.json +4413 -0
- package/dist/src/writing/patterns/formulaic-structures.json +1300 -0
- package/dist/src/writing/patterns/generic-adjectives.json +1510 -0
- package/dist/src/writing/patterns/hedging-language.json +2096 -0
- package/dist/src/writing/patterns/transition-words.json +1285 -0
- package/dist/src/writing/patterns/weak-verbs.json +1112 -0
- package/dist/src/writing/prompt-optimizer.js +660 -0
- package/dist/src/writing/prompt-templates.js +583 -0
- package/dist/src/writing/scoring-config-loader.js +168 -0
- package/dist/src/writing/validation-engine.js +595 -0
- package/dist/src/writing/validation-rules.js +380 -0
- package/dist/src/writing/voice-analyzer.js +439 -0
- package/dist/src/writing/voice-calibration.js +661 -0
- package/dist/src/writing/voice-profiles.json +588 -0
- package/package.json +64 -9
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache manager for research API responses
|
|
3
|
+
*
|
|
4
|
+
* @module research/cache/manager
|
|
5
|
+
*/
|
|
6
|
+
import { promises as fs } from 'fs';
|
|
7
|
+
import { join, dirname } from 'path';
|
|
8
|
+
import { createHash } from 'crypto';
|
|
9
|
+
import { ResearchError, ResearchErrorCode, } from '../types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Cache manager for file-based caching
|
|
12
|
+
*/
|
|
13
|
+
export class CacheManager {
|
|
14
|
+
config;
|
|
15
|
+
constructor(config) {
|
|
16
|
+
this.config = {
|
|
17
|
+
cacheDir: '.aiwg/research/cache',
|
|
18
|
+
defaultTtl: 86400, // 24 hours
|
|
19
|
+
ttlByEndpoint: {
|
|
20
|
+
'semantic-scholar': 604800, // 7 days
|
|
21
|
+
'crossref': 604800, // 7 days
|
|
22
|
+
'arxiv': 2592000, // 30 days (preprints don't change)
|
|
23
|
+
'unpaywall': 86400, // 24 hours
|
|
24
|
+
},
|
|
25
|
+
...config,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get cached data
|
|
30
|
+
*/
|
|
31
|
+
async get(key) {
|
|
32
|
+
try {
|
|
33
|
+
const filePath = this.getFilePath(key);
|
|
34
|
+
const data = await fs.readFile(filePath, 'utf-8');
|
|
35
|
+
const entry = JSON.parse(data);
|
|
36
|
+
// Check if expired
|
|
37
|
+
if (this.isExpired(entry)) {
|
|
38
|
+
await this.delete(key);
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
return entry.data;
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
if (error.code === 'ENOENT') {
|
|
45
|
+
return null; // Cache miss
|
|
46
|
+
}
|
|
47
|
+
throw new ResearchError(ResearchErrorCode.RF_400, 'Cache read error', error);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Set cached data
|
|
52
|
+
*/
|
|
53
|
+
async set(key, data, endpoint) {
|
|
54
|
+
try {
|
|
55
|
+
const ttl = endpoint
|
|
56
|
+
? this.config.ttlByEndpoint?.[endpoint] || this.config.defaultTtl
|
|
57
|
+
: this.config.defaultTtl;
|
|
58
|
+
const entry = {
|
|
59
|
+
data,
|
|
60
|
+
cachedAt: new Date().toISOString(),
|
|
61
|
+
ttl,
|
|
62
|
+
key,
|
|
63
|
+
};
|
|
64
|
+
const filePath = this.getFilePath(key);
|
|
65
|
+
await this.ensureDir(dirname(filePath));
|
|
66
|
+
await fs.writeFile(filePath, JSON.stringify(entry, null, 2), 'utf-8');
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
throw new ResearchError(ResearchErrorCode.RF_401, 'Cache write error', error);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Delete cached data
|
|
74
|
+
*/
|
|
75
|
+
async delete(key) {
|
|
76
|
+
try {
|
|
77
|
+
const filePath = this.getFilePath(key);
|
|
78
|
+
await fs.unlink(filePath);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
if (error.code !== 'ENOENT') {
|
|
82
|
+
throw new ResearchError(ResearchErrorCode.RF_402, 'Cache deletion error', error);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Clear all cache
|
|
88
|
+
*/
|
|
89
|
+
async clear() {
|
|
90
|
+
try {
|
|
91
|
+
const files = await this.listCacheFiles();
|
|
92
|
+
await Promise.all(files.map((file) => fs.unlink(file)));
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
throw new ResearchError(ResearchErrorCode.RF_402, 'Cache clear error', error);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Clear expired entries
|
|
100
|
+
*/
|
|
101
|
+
async clearExpired() {
|
|
102
|
+
try {
|
|
103
|
+
const files = await this.listCacheFiles();
|
|
104
|
+
let cleared = 0;
|
|
105
|
+
for (const file of files) {
|
|
106
|
+
try {
|
|
107
|
+
const data = await fs.readFile(file, 'utf-8');
|
|
108
|
+
const entry = JSON.parse(data);
|
|
109
|
+
if (this.isExpired(entry)) {
|
|
110
|
+
await fs.unlink(file);
|
|
111
|
+
cleared++;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// Skip invalid files
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return cleared;
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
throw new ResearchError(ResearchErrorCode.RF_402, 'Cache cleanup error', error);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Get cache statistics
|
|
126
|
+
*/
|
|
127
|
+
async getStats() {
|
|
128
|
+
try {
|
|
129
|
+
const files = await this.listCacheFiles();
|
|
130
|
+
let expiredEntries = 0;
|
|
131
|
+
let sizeBytes = 0;
|
|
132
|
+
for (const file of files) {
|
|
133
|
+
try {
|
|
134
|
+
const stats = await fs.stat(file);
|
|
135
|
+
sizeBytes += stats.size;
|
|
136
|
+
const data = await fs.readFile(file, 'utf-8');
|
|
137
|
+
const entry = JSON.parse(data);
|
|
138
|
+
if (this.isExpired(entry)) {
|
|
139
|
+
expiredEntries++;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
// Skip invalid files
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
totalEntries: files.length,
|
|
148
|
+
expiredEntries,
|
|
149
|
+
sizeBytes,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
throw new ResearchError(ResearchErrorCode.RF_400, 'Cache stats error', error);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Generate cache key from input
|
|
158
|
+
*/
|
|
159
|
+
generateKey(endpoint, params) {
|
|
160
|
+
// Sort keys to ensure consistent hashing
|
|
161
|
+
const sortedKeys = Object.keys(params).sort();
|
|
162
|
+
const sortedParams = {};
|
|
163
|
+
for (const key of sortedKeys) {
|
|
164
|
+
sortedParams[key] = params[key];
|
|
165
|
+
}
|
|
166
|
+
const normalized = JSON.stringify({ endpoint, params: sortedParams });
|
|
167
|
+
return createHash('sha256').update(normalized).digest('hex');
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Check if cache entry is expired
|
|
171
|
+
*/
|
|
172
|
+
isExpired(entry) {
|
|
173
|
+
const cachedTime = new Date(entry.cachedAt).getTime();
|
|
174
|
+
const expiryTime = cachedTime + entry.ttl * 1000;
|
|
175
|
+
return Date.now() > expiryTime;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Get file path for cache key
|
|
179
|
+
*/
|
|
180
|
+
getFilePath(key) {
|
|
181
|
+
// Use first 2 chars for subdirectory to avoid too many files in one dir
|
|
182
|
+
const subdir = key.substring(0, 2);
|
|
183
|
+
return join(this.config.cacheDir, subdir, `${key}.json`);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Ensure directory exists
|
|
187
|
+
*/
|
|
188
|
+
async ensureDir(dir) {
|
|
189
|
+
try {
|
|
190
|
+
await fs.mkdir(dir, { recursive: true });
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
if (error.code !== 'EEXIST') {
|
|
194
|
+
throw error;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* List all cache files
|
|
200
|
+
*/
|
|
201
|
+
async listCacheFiles() {
|
|
202
|
+
const files = [];
|
|
203
|
+
try {
|
|
204
|
+
const entries = await fs.readdir(this.config.cacheDir, {
|
|
205
|
+
withFileTypes: true,
|
|
206
|
+
});
|
|
207
|
+
for (const entry of entries) {
|
|
208
|
+
const fullPath = join(this.config.cacheDir, entry.name);
|
|
209
|
+
if (entry.isDirectory()) {
|
|
210
|
+
const subFiles = await fs.readdir(fullPath);
|
|
211
|
+
for (const file of subFiles) {
|
|
212
|
+
if (file.endsWith('.json')) {
|
|
213
|
+
files.push(join(fullPath, file));
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
catch (error) {
|
|
220
|
+
if (error.code !== 'ENOENT') {
|
|
221
|
+
throw error;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return files;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* arXiv API client
|
|
3
|
+
*
|
|
4
|
+
* @module research/clients/arxiv
|
|
5
|
+
*/
|
|
6
|
+
import { BaseClient } from './base.js';
|
|
7
|
+
import { ResearchError, ResearchErrorCode, } from '../types.js';
|
|
8
|
+
/**
|
|
9
|
+
* arXiv API client
|
|
10
|
+
*/
|
|
11
|
+
export class ArxivClient extends BaseClient {
|
|
12
|
+
constructor(config) {
|
|
13
|
+
super({
|
|
14
|
+
baseUrl: 'http://export.arxiv.org/api',
|
|
15
|
+
timeout: 30000,
|
|
16
|
+
rateLimit: {
|
|
17
|
+
maxTokens: 3,
|
|
18
|
+
refillRate: 1 / 3, // 1 request per 3 seconds
|
|
19
|
+
currentTokens: 3,
|
|
20
|
+
lastRefill: Date.now(),
|
|
21
|
+
},
|
|
22
|
+
retry: {
|
|
23
|
+
maxRetries: 3,
|
|
24
|
+
initialDelay: 1000,
|
|
25
|
+
maxDelay: 10000,
|
|
26
|
+
backoffMultiplier: 2,
|
|
27
|
+
},
|
|
28
|
+
...config,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get paper by arXiv ID
|
|
33
|
+
*/
|
|
34
|
+
async getPaperById(arxivId) {
|
|
35
|
+
// Normalize arXiv ID (remove version if present)
|
|
36
|
+
const normalizedId = arxivId.replace(/v\d+$/, '');
|
|
37
|
+
const url = this.buildUrl('/query', {
|
|
38
|
+
id_list: normalizedId,
|
|
39
|
+
max_results: 1,
|
|
40
|
+
});
|
|
41
|
+
const xmlText = await this.requestXml(url);
|
|
42
|
+
const papers = this.parseAtomFeed(xmlText);
|
|
43
|
+
if (papers.length === 0) {
|
|
44
|
+
throw new ResearchError(ResearchErrorCode.RF_300, `arXiv paper not found: ${arxivId}`);
|
|
45
|
+
}
|
|
46
|
+
return papers[0];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Search papers by query
|
|
50
|
+
*/
|
|
51
|
+
async search(query, options = {}) {
|
|
52
|
+
const { limit = 10, offset = 0 } = options;
|
|
53
|
+
const url = this.buildUrl('/query', {
|
|
54
|
+
search_query: query,
|
|
55
|
+
start: offset,
|
|
56
|
+
max_results: limit,
|
|
57
|
+
});
|
|
58
|
+
const xmlText = await this.requestXml(url);
|
|
59
|
+
const papers = this.parseAtomFeed(xmlText);
|
|
60
|
+
// arXiv doesn't provide total count, so we estimate
|
|
61
|
+
const hasMore = papers.length === limit;
|
|
62
|
+
return {
|
|
63
|
+
total: hasMore ? offset + limit + 1 : offset + papers.length,
|
|
64
|
+
papers,
|
|
65
|
+
offset,
|
|
66
|
+
limit,
|
|
67
|
+
hasMore,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Request XML from arXiv API
|
|
72
|
+
*/
|
|
73
|
+
async requestXml(url) {
|
|
74
|
+
await this.rateLimiter.acquire();
|
|
75
|
+
const controller = new AbortController();
|
|
76
|
+
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
77
|
+
try {
|
|
78
|
+
const response = await fetch(url, {
|
|
79
|
+
signal: controller.signal,
|
|
80
|
+
});
|
|
81
|
+
if (!response.ok) {
|
|
82
|
+
throw new ResearchError(ResearchErrorCode.RF_200, `arXiv API error: ${response.status}`);
|
|
83
|
+
}
|
|
84
|
+
return await response.text();
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
88
|
+
throw new ResearchError(ResearchErrorCode.RF_104, `Request timeout after ${this.config.timeout}ms`, error);
|
|
89
|
+
}
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
clearTimeout(timeoutId);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Parse Atom XML feed from arXiv
|
|
98
|
+
*/
|
|
99
|
+
parseAtomFeed(xmlText) {
|
|
100
|
+
// Simple XML parsing for arXiv Atom feed
|
|
101
|
+
const papers = [];
|
|
102
|
+
// Extract entries
|
|
103
|
+
const entryRegex = /<entry>([\s\S]*?)<\/entry>/g;
|
|
104
|
+
const entries = xmlText.match(entryRegex) || [];
|
|
105
|
+
for (const entry of entries) {
|
|
106
|
+
papers.push(this.parseEntry(entry));
|
|
107
|
+
}
|
|
108
|
+
return papers;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Parse a single entry from the feed
|
|
112
|
+
*/
|
|
113
|
+
parseEntry(entry) {
|
|
114
|
+
const extractTag = (tag) => {
|
|
115
|
+
const regex = new RegExp(`<${tag}[^>]*>([\\s\\S]*?)</${tag}>`, 'i');
|
|
116
|
+
const match = entry.match(regex);
|
|
117
|
+
return match ? match[1].trim() : '';
|
|
118
|
+
};
|
|
119
|
+
const extractAllTags = (tag) => {
|
|
120
|
+
const regex = new RegExp(`<${tag}[^>]*>([\\s\\S]*?)</${tag}>`, 'gi');
|
|
121
|
+
const matches = entry.match(regex) || [];
|
|
122
|
+
return matches.map((m) => {
|
|
123
|
+
const contentMatch = m.match(new RegExp(`<${tag}[^>]*>([\\s\\S]*?)</${tag}>`, 'i'));
|
|
124
|
+
return contentMatch ? contentMatch[1].trim() : '';
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
const id = extractTag('id');
|
|
128
|
+
const arxivId = id.split('/').pop()?.replace(/v\d+$/, '') || '';
|
|
129
|
+
const title = extractTag('title').replace(/\s+/g, ' ');
|
|
130
|
+
const summary = extractTag('summary').replace(/\s+/g, ' ');
|
|
131
|
+
const published = extractTag('published');
|
|
132
|
+
const year = parseInt(published.substring(0, 4), 10) || 0;
|
|
133
|
+
const authorNames = extractAllTags('name');
|
|
134
|
+
const authors = authorNames.map((name) => ({ name }));
|
|
135
|
+
// Extract DOI if present
|
|
136
|
+
const doiMatch = entry.match(/doi:([^\s<]+)/i);
|
|
137
|
+
const doi = doiMatch ? doiMatch[1] : undefined;
|
|
138
|
+
// Extract PDF link
|
|
139
|
+
const pdfLinkMatch = entry.match(/<link[^>]*title="pdf"[^>]*href="([^"]+)"/i);
|
|
140
|
+
const pdfUrl = pdfLinkMatch ? pdfLinkMatch[1] : undefined;
|
|
141
|
+
return {
|
|
142
|
+
id: arxivId,
|
|
143
|
+
title,
|
|
144
|
+
authors,
|
|
145
|
+
year,
|
|
146
|
+
abstract: summary,
|
|
147
|
+
arxivId,
|
|
148
|
+
doi,
|
|
149
|
+
pdfUrl,
|
|
150
|
+
type: 'preprint',
|
|
151
|
+
source: 'arxiv',
|
|
152
|
+
retrievedAt: new Date().toISOString(),
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=arxiv.js.map
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base API client with rate limiting and retry logic
|
|
3
|
+
*
|
|
4
|
+
* @module research/clients/base
|
|
5
|
+
*/
|
|
6
|
+
import { ResearchError, ResearchErrorCode, } from '../types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Token bucket rate limiter
|
|
9
|
+
*/
|
|
10
|
+
export class RateLimiter {
|
|
11
|
+
config;
|
|
12
|
+
tokens;
|
|
13
|
+
lastRefill;
|
|
14
|
+
constructor(config) {
|
|
15
|
+
this.config = config;
|
|
16
|
+
this.tokens = config.currentTokens;
|
|
17
|
+
this.lastRefill = config.lastRefill; // Use config value, not Date.now()
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Refill tokens based on elapsed time
|
|
21
|
+
*/
|
|
22
|
+
refill() {
|
|
23
|
+
const now = Date.now();
|
|
24
|
+
const elapsed = (now - this.lastRefill) / 1000; // Convert to seconds
|
|
25
|
+
const tokensToAdd = elapsed * this.config.refillRate;
|
|
26
|
+
this.tokens = Math.min(this.config.maxTokens, this.tokens + tokensToAdd);
|
|
27
|
+
this.lastRefill = now;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Acquire a token, waiting if necessary
|
|
31
|
+
*/
|
|
32
|
+
async acquire() {
|
|
33
|
+
this.refill();
|
|
34
|
+
if (this.tokens >= 1) {
|
|
35
|
+
this.tokens -= 1;
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
// Calculate wait time
|
|
39
|
+
const deficit = 1 - this.tokens;
|
|
40
|
+
const waitMs = (deficit / this.config.refillRate) * 1000;
|
|
41
|
+
await this.sleep(waitMs);
|
|
42
|
+
// Refill again after waiting
|
|
43
|
+
this.refill();
|
|
44
|
+
this.tokens -= 1;
|
|
45
|
+
}
|
|
46
|
+
sleep(ms) {
|
|
47
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get current token count (for testing)
|
|
51
|
+
*/
|
|
52
|
+
getCurrentTokens() {
|
|
53
|
+
this.refill();
|
|
54
|
+
return this.tokens;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Base API client with common functionality
|
|
59
|
+
*/
|
|
60
|
+
export class BaseClient {
|
|
61
|
+
config;
|
|
62
|
+
rateLimiter;
|
|
63
|
+
retryConfig;
|
|
64
|
+
constructor(config) {
|
|
65
|
+
this.config = config;
|
|
66
|
+
this.rateLimiter = new RateLimiter(config.rateLimit);
|
|
67
|
+
this.retryConfig = config.retry;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Execute an HTTP request with rate limiting and retry logic
|
|
71
|
+
*/
|
|
72
|
+
async request(url, options = {}) {
|
|
73
|
+
// Apply rate limiting
|
|
74
|
+
await this.rateLimiter.acquire();
|
|
75
|
+
// Execute with retry
|
|
76
|
+
return this.executeWithRetry(url, options);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Execute request with exponential backoff retry
|
|
80
|
+
*/
|
|
81
|
+
async executeWithRetry(url, options, attempt = 0, firstError) {
|
|
82
|
+
const controller = new AbortController();
|
|
83
|
+
let timeoutId;
|
|
84
|
+
try {
|
|
85
|
+
// Create timeout promise
|
|
86
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
87
|
+
timeoutId = setTimeout(() => {
|
|
88
|
+
controller.abort();
|
|
89
|
+
reject(new ResearchError(ResearchErrorCode.RF_104, `Request timeout after ${this.config.timeout}ms`));
|
|
90
|
+
}, this.config.timeout);
|
|
91
|
+
});
|
|
92
|
+
// Create fetch promise
|
|
93
|
+
const fetchPromise = fetch(url, {
|
|
94
|
+
...options,
|
|
95
|
+
signal: controller.signal,
|
|
96
|
+
});
|
|
97
|
+
// Race between fetch and timeout
|
|
98
|
+
const response = await Promise.race([fetchPromise, timeoutPromise]);
|
|
99
|
+
// Clear timeout if fetch completed first
|
|
100
|
+
if (timeoutId) {
|
|
101
|
+
clearTimeout(timeoutId);
|
|
102
|
+
}
|
|
103
|
+
if (!response.ok) {
|
|
104
|
+
const error = await this.handleHttpError(response);
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
107
|
+
return (await response.json());
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
// Clear timeout on error
|
|
111
|
+
if (timeoutId) {
|
|
112
|
+
clearTimeout(timeoutId);
|
|
113
|
+
}
|
|
114
|
+
// Handle abort (timeout)
|
|
115
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
116
|
+
throw new ResearchError(ResearchErrorCode.RF_104, `Request timeout after ${this.config.timeout}ms`, error);
|
|
117
|
+
}
|
|
118
|
+
// Track the first error for better error reporting
|
|
119
|
+
const currentFirstError = firstError || (error instanceof ResearchError ? error : undefined);
|
|
120
|
+
// Don't retry ResearchErrors (they're already handled)
|
|
121
|
+
if (error instanceof ResearchError) {
|
|
122
|
+
// Retry on transient errors
|
|
123
|
+
if (this.isRetriable(error) && attempt < this.retryConfig.maxRetries) {
|
|
124
|
+
const delay = this.calculateBackoff(attempt);
|
|
125
|
+
await this.sleep(delay);
|
|
126
|
+
return this.executeWithRetry(url, options, attempt + 1, currentFirstError);
|
|
127
|
+
}
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
130
|
+
// Retry on network errors
|
|
131
|
+
if (attempt < this.retryConfig.maxRetries) {
|
|
132
|
+
const delay = this.calculateBackoff(attempt);
|
|
133
|
+
await this.sleep(delay);
|
|
134
|
+
return this.executeWithRetry(url, options, attempt + 1, currentFirstError);
|
|
135
|
+
}
|
|
136
|
+
// If we have a first error from an HTTP response, throw that instead of generic network error
|
|
137
|
+
if (currentFirstError) {
|
|
138
|
+
throw currentFirstError;
|
|
139
|
+
}
|
|
140
|
+
throw new ResearchError(ResearchErrorCode.RF_500, 'Network error', error);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Handle HTTP error responses
|
|
145
|
+
*/
|
|
146
|
+
async handleHttpError(response) {
|
|
147
|
+
const status = response.status;
|
|
148
|
+
if (status === 404) {
|
|
149
|
+
return new ResearchError(ResearchErrorCode.RF_300, 'Resource not found');
|
|
150
|
+
}
|
|
151
|
+
if (status === 429) {
|
|
152
|
+
return new ResearchError(ResearchErrorCode.RF_103, 'Rate limit exceeded');
|
|
153
|
+
}
|
|
154
|
+
if (status === 401 || status === 403) {
|
|
155
|
+
return new ResearchError(ResearchErrorCode.RF_102, 'Invalid API key or unauthorized');
|
|
156
|
+
}
|
|
157
|
+
if (status >= 500) {
|
|
158
|
+
return new ResearchError(ResearchErrorCode.RF_200, 'API server error');
|
|
159
|
+
}
|
|
160
|
+
return new ResearchError(ResearchErrorCode.RF_100, `HTTP error ${status}`);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Determine if an error is retriable
|
|
164
|
+
*/
|
|
165
|
+
isRetriable(error) {
|
|
166
|
+
if (error instanceof ResearchError) {
|
|
167
|
+
// Only retry on server errors (not rate limits or client errors)
|
|
168
|
+
return error.code === ResearchErrorCode.RF_200;
|
|
169
|
+
}
|
|
170
|
+
// Retry on network errors
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Calculate exponential backoff delay
|
|
175
|
+
*/
|
|
176
|
+
calculateBackoff(attempt) {
|
|
177
|
+
const delay = this.retryConfig.initialDelay *
|
|
178
|
+
Math.pow(this.retryConfig.backoffMultiplier, attempt);
|
|
179
|
+
return Math.min(delay, this.retryConfig.maxDelay);
|
|
180
|
+
}
|
|
181
|
+
sleep(ms) {
|
|
182
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Build URL with query parameters
|
|
186
|
+
*/
|
|
187
|
+
buildUrl(path, params) {
|
|
188
|
+
const url = new URL(path, this.config.baseUrl);
|
|
189
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
190
|
+
if (value !== undefined) {
|
|
191
|
+
url.searchParams.append(key, String(value));
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
return url.toString();
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=base.js.map
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CrossRef API client
|
|
3
|
+
*
|
|
4
|
+
* @module research/clients/crossref
|
|
5
|
+
*/
|
|
6
|
+
import { BaseClient } from './base.js';
|
|
7
|
+
/**
|
|
8
|
+
* CrossRef API client
|
|
9
|
+
*/
|
|
10
|
+
export class CrossRefClient extends BaseClient {
|
|
11
|
+
constructor(config) {
|
|
12
|
+
super({
|
|
13
|
+
baseUrl: 'https://api.crossref.org',
|
|
14
|
+
timeout: 30000,
|
|
15
|
+
rateLimit: {
|
|
16
|
+
maxTokens: 50,
|
|
17
|
+
refillRate: 1, // 1 request per second (polite pool)
|
|
18
|
+
currentTokens: 50,
|
|
19
|
+
lastRefill: Date.now(),
|
|
20
|
+
},
|
|
21
|
+
retry: {
|
|
22
|
+
maxRetries: 3,
|
|
23
|
+
initialDelay: 1000,
|
|
24
|
+
maxDelay: 10000,
|
|
25
|
+
backoffMultiplier: 2,
|
|
26
|
+
},
|
|
27
|
+
...config,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get paper by DOI
|
|
32
|
+
*/
|
|
33
|
+
async getPaperByDoi(doi) {
|
|
34
|
+
const url = this.buildUrl(`/works/${encodeURIComponent(doi)}`, {});
|
|
35
|
+
const response = await this.request(url);
|
|
36
|
+
return this.transformResponse(response.message);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Search papers by query
|
|
40
|
+
*/
|
|
41
|
+
async search(query, options = {}) {
|
|
42
|
+
const { limit = 10, offset = 0 } = options;
|
|
43
|
+
const url = this.buildUrl('/works', {
|
|
44
|
+
query,
|
|
45
|
+
rows: limit,
|
|
46
|
+
offset,
|
|
47
|
+
});
|
|
48
|
+
const response = await this.request(url);
|
|
49
|
+
return {
|
|
50
|
+
total: response.message['total-results'],
|
|
51
|
+
papers: response.message.items.map((paper) => this.transformResponse(paper)),
|
|
52
|
+
offset,
|
|
53
|
+
limit,
|
|
54
|
+
hasMore: offset + response.message.items.length < response.message['total-results'],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Transform CrossRef response to ResearchPaper
|
|
59
|
+
*/
|
|
60
|
+
transformResponse(response) {
|
|
61
|
+
const authors = response.author?.map((author) => {
|
|
62
|
+
const name = [author.given, author.family]
|
|
63
|
+
.filter(Boolean)
|
|
64
|
+
.join(' ');
|
|
65
|
+
const affiliations = author.affiliation?.map((aff) => aff.name) || [];
|
|
66
|
+
return {
|
|
67
|
+
name,
|
|
68
|
+
affiliations,
|
|
69
|
+
};
|
|
70
|
+
}) || [];
|
|
71
|
+
const year = response.published?.['date-parts']?.[0]?.[0] || 0;
|
|
72
|
+
const title = Array.isArray(response.title)
|
|
73
|
+
? response.title[0]
|
|
74
|
+
: response.title || '';
|
|
75
|
+
const venue = Array.isArray(response['container-title'])
|
|
76
|
+
? response['container-title'][0]
|
|
77
|
+
: response['container-title'] || '';
|
|
78
|
+
return {
|
|
79
|
+
id: response.DOI,
|
|
80
|
+
title,
|
|
81
|
+
authors,
|
|
82
|
+
year,
|
|
83
|
+
abstract: response.abstract,
|
|
84
|
+
doi: response.DOI,
|
|
85
|
+
venue,
|
|
86
|
+
citationCount: response['is-referenced-by-count'],
|
|
87
|
+
type: this.mapType(response.type),
|
|
88
|
+
source: 'crossref',
|
|
89
|
+
retrievedAt: new Date().toISOString(),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Map CrossRef type to ResearchPaper type
|
|
94
|
+
*/
|
|
95
|
+
mapType(crossrefType) {
|
|
96
|
+
if (!crossrefType)
|
|
97
|
+
return 'other';
|
|
98
|
+
const type = crossrefType.toLowerCase();
|
|
99
|
+
if (type.includes('journal'))
|
|
100
|
+
return 'journal';
|
|
101
|
+
if (type.includes('proceedings'))
|
|
102
|
+
return 'conference';
|
|
103
|
+
if (type.includes('posted-content'))
|
|
104
|
+
return 'preprint';
|
|
105
|
+
if (type.includes('book'))
|
|
106
|
+
return 'book';
|
|
107
|
+
if (type.includes('dissertation') || type.includes('thesis'))
|
|
108
|
+
return 'thesis';
|
|
109
|
+
return 'other';
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=crossref.js.map
|