@nac3/forge-cli 0.2.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +45 -0
- package/README.md +371 -0
- package/dist/bin/yf.d.ts +5 -0
- package/dist/bin/yf.d.ts.map +1 -0
- package/dist/bin/yf.js +86 -0
- package/dist/bin/yf.js.map +1 -0
- package/dist/chat/claude.d.ts +100 -0
- package/dist/chat/claude.d.ts.map +1 -0
- package/dist/chat/claude.js +228 -0
- package/dist/chat/claude.js.map +1 -0
- package/dist/chat/ingest_session.d.ts +97 -0
- package/dist/chat/ingest_session.d.ts.map +1 -0
- package/dist/chat/ingest_session.js +99 -0
- package/dist/chat/ingest_session.js.map +1 -0
- package/dist/chat/panel.d.ts +15 -0
- package/dist/chat/panel.d.ts.map +1 -0
- package/dist/chat/panel.js +1526 -0
- package/dist/chat/panel.js.map +1 -0
- package/dist/chat/persistence.d.ts +37 -0
- package/dist/chat/persistence.d.ts.map +1 -0
- package/dist/chat/persistence.js +91 -0
- package/dist/chat/persistence.js.map +1 -0
- package/dist/chat/server.d.ts +34 -0
- package/dist/chat/server.d.ts.map +1 -0
- package/dist/chat/server.js +1540 -0
- package/dist/chat/server.js.map +1 -0
- package/dist/chat/spec_extract.d.ts +35 -0
- package/dist/chat/spec_extract.d.ts.map +1 -0
- package/dist/chat/spec_extract.js +152 -0
- package/dist/chat/spec_extract.js.map +1 -0
- package/dist/chat/spec_plan.d.ts +65 -0
- package/dist/chat/spec_plan.d.ts.map +1 -0
- package/dist/chat/spec_plan.js +160 -0
- package/dist/chat/spec_plan.js.map +1 -0
- package/dist/chat/spec_scaffold.d.ts +95 -0
- package/dist/chat/spec_scaffold.d.ts.map +1 -0
- package/dist/chat/spec_scaffold.js +220 -0
- package/dist/chat/spec_scaffold.js.map +1 -0
- package/dist/chat/tools/git.d.ts +59 -0
- package/dist/chat/tools/git.d.ts.map +1 -0
- package/dist/chat/tools/git.js +313 -0
- package/dist/chat/tools/git.js.map +1 -0
- package/dist/chat/tools/github.d.ts +59 -0
- package/dist/chat/tools/github.d.ts.map +1 -0
- package/dist/chat/tools/github.js +310 -0
- package/dist/chat/tools/github.js.map +1 -0
- package/dist/chat/tools/lifecycle.d.ts +82 -0
- package/dist/chat/tools/lifecycle.d.ts.map +1 -0
- package/dist/chat/tools/lifecycle.js +295 -0
- package/dist/chat/tools/lifecycle.js.map +1 -0
- package/dist/chat/tools/manual.d.ts +26 -0
- package/dist/chat/tools/manual.d.ts.map +1 -0
- package/dist/chat/tools/manual.js +164 -0
- package/dist/chat/tools/manual.js.map +1 -0
- package/dist/chat/tools/reader.d.ts +80 -0
- package/dist/chat/tools/reader.d.ts.map +1 -0
- package/dist/chat/tools/reader.js +471 -0
- package/dist/chat/tools/reader.js.map +1 -0
- package/dist/chat/tools.d.ts +106 -0
- package/dist/chat/tools.d.ts.map +1 -0
- package/dist/chat/tools.js +587 -0
- package/dist/chat/tools.js.map +1 -0
- package/dist/codegen/e2e.d.ts +106 -0
- package/dist/codegen/e2e.d.ts.map +1 -0
- package/dist/codegen/e2e.js +931 -0
- package/dist/codegen/e2e.js.map +1 -0
- package/dist/codegen/v3_flow_emit.d.ts +70 -0
- package/dist/codegen/v3_flow_emit.d.ts.map +1 -0
- package/dist/codegen/v3_flow_emit.js +225 -0
- package/dist/codegen/v3_flow_emit.js.map +1 -0
- package/dist/commands/_stub.d.ts +2 -0
- package/dist/commands/_stub.d.ts.map +1 -0
- package/dist/commands/_stub.js +21 -0
- package/dist/commands/_stub.js.map +1 -0
- package/dist/commands/app.d.ts +31 -0
- package/dist/commands/app.d.ts.map +1 -0
- package/dist/commands/app.js +331 -0
- package/dist/commands/app.js.map +1 -0
- package/dist/commands/chat.d.ts +18 -0
- package/dist/commands/chat.d.ts.map +1 -0
- package/dist/commands/chat.js +76 -0
- package/dist/commands/chat.js.map +1 -0
- package/dist/commands/deploy.d.ts +21 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +121 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/doctor.d.ts +14 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +280 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/figma.d.ts +32 -0
- package/dist/commands/figma.d.ts.map +1 -0
- package/dist/commands/figma.js +141 -0
- package/dist/commands/figma.js.map +1 -0
- package/dist/commands/gen-flow-tests.d.ts +8 -0
- package/dist/commands/gen-flow-tests.d.ts.map +1 -0
- package/dist/commands/gen-flow-tests.js +78 -0
- package/dist/commands/gen-flow-tests.js.map +1 -0
- package/dist/commands/gen-tests.d.ts +9 -0
- package/dist/commands/gen-tests.d.ts.map +1 -0
- package/dist/commands/gen-tests.js +118 -0
- package/dist/commands/gen-tests.js.map +1 -0
- package/dist/commands/license.d.ts +14 -0
- package/dist/commands/license.d.ts.map +1 -0
- package/dist/commands/license.js +182 -0
- package/dist/commands/license.js.map +1 -0
- package/dist/commands/log.d.ts +19 -0
- package/dist/commands/log.d.ts.map +1 -0
- package/dist/commands/log.js +101 -0
- package/dist/commands/log.js.map +1 -0
- package/dist/commands/migrate.d.ts +118 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +1410 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/mobile.d.ts +27 -0
- package/dist/commands/mobile.d.ts.map +1 -0
- package/dist/commands/mobile.js +90 -0
- package/dist/commands/mobile.js.map +1 -0
- package/dist/commands/new.d.ts +32 -0
- package/dist/commands/new.d.ts.map +1 -0
- package/dist/commands/new.js +107 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/pilot.d.ts +8 -0
- package/dist/commands/pilot.d.ts.map +1 -0
- package/dist/commands/pilot.js +104 -0
- package/dist/commands/pilot.js.map +1 -0
- package/dist/commands/projects.d.ts +21 -0
- package/dist/commands/projects.d.ts.map +1 -0
- package/dist/commands/projects.js +238 -0
- package/dist/commands/projects.js.map +1 -0
- package/dist/commands/publish.d.ts +35 -0
- package/dist/commands/publish.d.ts.map +1 -0
- package/dist/commands/publish.js +194 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/repo.d.ts +59 -0
- package/dist/commands/repo.d.ts.map +1 -0
- package/dist/commands/repo.js +178 -0
- package/dist/commands/repo.js.map +1 -0
- package/dist/commands/review-screens.d.ts +28 -0
- package/dist/commands/review-screens.d.ts.map +1 -0
- package/dist/commands/review-screens.js +345 -0
- package/dist/commands/review-screens.js.map +1 -0
- package/dist/commands/scenarios.d.ts +23 -0
- package/dist/commands/scenarios.d.ts.map +1 -0
- package/dist/commands/scenarios.js +304 -0
- package/dist/commands/scenarios.js.map +1 -0
- package/dist/commands/ship.d.ts +18 -0
- package/dist/commands/ship.d.ts.map +1 -0
- package/dist/commands/ship.js +41 -0
- package/dist/commands/ship.js.map +1 -0
- package/dist/commands/test.d.ts +29 -0
- package/dist/commands/test.d.ts.map +1 -0
- package/dist/commands/test.js +62 -0
- package/dist/commands/test.js.map +1 -0
- package/dist/commands/tunnel.d.ts +22 -0
- package/dist/commands/tunnel.d.ts.map +1 -0
- package/dist/commands/tunnel.js +77 -0
- package/dist/commands/tunnel.js.map +1 -0
- package/dist/commands/validate.d.ts +14 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +51 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/commands/vault.d.ts +32 -0
- package/dist/commands/vault.d.ts.map +1 -0
- package/dist/commands/vault.js +489 -0
- package/dist/commands/vault.js.map +1 -0
- package/dist/commands/voice.d.ts +16 -0
- package/dist/commands/voice.d.ts.map +1 -0
- package/dist/commands/voice.js +69 -0
- package/dist/commands/voice.js.map +1 -0
- package/dist/core/cascade_router.d.ts +90 -0
- package/dist/core/cascade_router.d.ts.map +1 -0
- package/dist/core/cascade_router.js +131 -0
- package/dist/core/cascade_router.js.map +1 -0
- package/dist/core/cf_tunnel.d.ts +52 -0
- package/dist/core/cf_tunnel.d.ts.map +1 -0
- package/dist/core/cf_tunnel.js +134 -0
- package/dist/core/cf_tunnel.js.map +1 -0
- package/dist/core/gha_dispatcher.d.ts +48 -0
- package/dist/core/gha_dispatcher.d.ts.map +1 -0
- package/dist/core/gha_dispatcher.js +198 -0
- package/dist/core/gha_dispatcher.js.map +1 -0
- package/dist/core/logger.d.ts +89 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +245 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/mode.d.ts +26 -0
- package/dist/core/mode.d.ts.map +1 -0
- package/dist/core/mode.js +122 -0
- package/dist/core/mode.js.map +1 -0
- package/dist/core/pairing.d.ts +40 -0
- package/dist/core/pairing.d.ts.map +1 -0
- package/dist/core/pairing.js +145 -0
- package/dist/core/pairing.js.map +1 -0
- package/dist/core/pilot_setup.d.ts +29 -0
- package/dist/core/pilot_setup.d.ts.map +1 -0
- package/dist/core/pilot_setup.js +119 -0
- package/dist/core/pilot_setup.js.map +1 -0
- package/dist/core/polar.d.ts +81 -0
- package/dist/core/polar.d.ts.map +1 -0
- package/dist/core/polar.js +175 -0
- package/dist/core/polar.js.map +1 -0
- package/dist/core/project_picker.d.ts +56 -0
- package/dist/core/project_picker.d.ts.map +1 -0
- package/dist/core/project_picker.js +86 -0
- package/dist/core/project_picker.js.map +1 -0
- package/dist/core/projects.d.ts +58 -0
- package/dist/core/projects.d.ts.map +1 -0
- package/dist/core/projects.js +146 -0
- package/dist/core/projects.js.map +1 -0
- package/dist/core/projects_sync.d.ts +80 -0
- package/dist/core/projects_sync.d.ts.map +1 -0
- package/dist/core/projects_sync.js +278 -0
- package/dist/core/projects_sync.js.map +1 -0
- package/dist/core/remote_runner.d.ts +70 -0
- package/dist/core/remote_runner.d.ts.map +1 -0
- package/dist/core/remote_runner.js +133 -0
- package/dist/core/remote_runner.js.map +1 -0
- package/dist/core/repo_state.d.ts +24 -0
- package/dist/core/repo_state.d.ts.map +1 -0
- package/dist/core/repo_state.js +109 -0
- package/dist/core/repo_state.js.map +1 -0
- package/dist/core/target.d.ts +31 -0
- package/dist/core/target.d.ts.map +1 -0
- package/dist/core/target.js +121 -0
- package/dist/core/target.js.map +1 -0
- package/dist/deploy/aws.d.ts +43 -0
- package/dist/deploy/aws.d.ts.map +1 -0
- package/dist/deploy/aws.js +173 -0
- package/dist/deploy/aws.js.map +1 -0
- package/dist/figma/api.d.ts +35 -0
- package/dist/figma/api.d.ts.map +1 -0
- package/dist/figma/api.js +40 -0
- package/dist/figma/api.js.map +1 -0
- package/dist/figma/decorator.d.ts +74 -0
- package/dist/figma/decorator.d.ts.map +1 -0
- package/dist/figma/decorator.js +210 -0
- package/dist/figma/decorator.js.map +1 -0
- package/dist/figma/heuristics.d.ts +29 -0
- package/dist/figma/heuristics.d.ts.map +1 -0
- package/dist/figma/heuristics.js +110 -0
- package/dist/figma/heuristics.js.map +1 -0
- package/dist/figma/normalize.d.ts +33 -0
- package/dist/figma/normalize.d.ts.map +1 -0
- package/dist/figma/normalize.js +101 -0
- package/dist/figma/normalize.js.map +1 -0
- package/dist/figma/tokens.d.ts +23 -0
- package/dist/figma/tokens.d.ts.map +1 -0
- package/dist/figma/tokens.js +111 -0
- package/dist/figma/tokens.js.map +1 -0
- package/dist/figma/types.d.ts +118 -0
- package/dist/figma/types.d.ts.map +1 -0
- package/dist/figma/types.js +12 -0
- package/dist/figma/types.js.map +1 -0
- package/dist/i18n/index.d.ts +48 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +135 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/types.d.ts +52 -0
- package/dist/i18n/types.d.ts.map +1 -0
- package/dist/i18n/types.js +85 -0
- package/dist/i18n/types.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/lan/mdns_packet.d.ts +74 -0
- package/dist/lan/mdns_packet.d.ts.map +1 -0
- package/dist/lan/mdns_packet.js +247 -0
- package/dist/lan/mdns_packet.js.map +1 -0
- package/dist/lan/mdns_service.d.ts +102 -0
- package/dist/lan/mdns_service.d.ts.map +1 -0
- package/dist/lan/mdns_service.js +206 -0
- package/dist/lan/mdns_service.js.map +1 -0
- package/dist/license/activate.d.ts +33 -0
- package/dist/license/activate.d.ts.map +1 -0
- package/dist/license/activate.js +135 -0
- package/dist/license/activate.js.map +1 -0
- package/dist/license/fingerprint.d.ts +2 -0
- package/dist/license/fingerprint.d.ts.map +1 -0
- package/dist/license/fingerprint.js +29 -0
- package/dist/license/fingerprint.js.map +1 -0
- package/dist/license/hito4_client.d.ts +24 -0
- package/dist/license/hito4_client.d.ts.map +1 -0
- package/dist/license/hito4_client.js +103 -0
- package/dist/license/hito4_client.js.map +1 -0
- package/dist/license/index.d.ts +22 -0
- package/dist/license/index.d.ts.map +1 -0
- package/dist/license/index.js +125 -0
- package/dist/license/index.js.map +1 -0
- package/dist/license/types.d.ts +38 -0
- package/dist/license/types.d.ts.map +1 -0
- package/dist/license/types.js +9 -0
- package/dist/license/types.js.map +1 -0
- package/dist/migrate/ai-apply.d.ts +198 -0
- package/dist/migrate/ai-apply.d.ts.map +1 -0
- package/dist/migrate/ai-apply.js +833 -0
- package/dist/migrate/ai-apply.js.map +1 -0
- package/dist/migrate/ai-decorator.d.ts +87 -0
- package/dist/migrate/ai-decorator.d.ts.map +1 -0
- package/dist/migrate/ai-decorator.js +203 -0
- package/dist/migrate/ai-decorator.js.map +1 -0
- package/dist/migrate/apply.d.ts +28 -0
- package/dist/migrate/apply.d.ts.map +1 -0
- package/dist/migrate/apply.js +119 -0
- package/dist/migrate/apply.js.map +1 -0
- package/dist/migrate/audit.d.ts +9 -0
- package/dist/migrate/audit.d.ts.map +1 -0
- package/dist/migrate/audit.js +197 -0
- package/dist/migrate/audit.js.map +1 -0
- package/dist/migrate/diff.d.ts +28 -0
- package/dist/migrate/diff.d.ts.map +1 -0
- package/dist/migrate/diff.js +154 -0
- package/dist/migrate/diff.js.map +1 -0
- package/dist/migrate/html-orchestrator.d.ts +81 -0
- package/dist/migrate/html-orchestrator.d.ts.map +1 -0
- package/dist/migrate/html-orchestrator.js +233 -0
- package/dist/migrate/html-orchestrator.js.map +1 -0
- package/dist/migrate/html-walker.d.ts +93 -0
- package/dist/migrate/html-walker.d.ts.map +1 -0
- package/dist/migrate/html-walker.js +288 -0
- package/dist/migrate/html-walker.js.map +1 -0
- package/dist/migrate/js-template-walker.d.ts +118 -0
- package/dist/migrate/js-template-walker.d.ts.map +1 -0
- package/dist/migrate/js-template-walker.js +644 -0
- package/dist/migrate/js-template-walker.js.map +1 -0
- package/dist/migrate/manifest-validator.d.ts +30 -0
- package/dist/migrate/manifest-validator.d.ts.map +1 -0
- package/dist/migrate/manifest-validator.js +261 -0
- package/dist/migrate/manifest-validator.js.map +1 -0
- package/dist/migrate/overrides.d.ts +58 -0
- package/dist/migrate/overrides.d.ts.map +1 -0
- package/dist/migrate/overrides.js +193 -0
- package/dist/migrate/overrides.js.map +1 -0
- package/dist/migrate/plugin-scope.d.ts +42 -0
- package/dist/migrate/plugin-scope.d.ts.map +1 -0
- package/dist/migrate/plugin-scope.js +94 -0
- package/dist/migrate/plugin-scope.js.map +1 -0
- package/dist/migrate/types.d.ts +45 -0
- package/dist/migrate/types.d.ts.map +1 -0
- package/dist/migrate/types.js +9 -0
- package/dist/migrate/types.js.map +1 -0
- package/dist/migrate/verb-inference.d.ts +37 -0
- package/dist/migrate/verb-inference.d.ts.map +1 -0
- package/dist/migrate/verb-inference.js +274 -0
- package/dist/migrate/verb-inference.js.map +1 -0
- package/dist/nac3/attrs.d.ts +87 -0
- package/dist/nac3/attrs.d.ts.map +1 -0
- package/dist/nac3/attrs.js +134 -0
- package/dist/nac3/attrs.js.map +1 -0
- package/dist/nac3/scenario_dsl.d.ts +71 -0
- package/dist/nac3/scenario_dsl.d.ts.map +1 -0
- package/dist/nac3/scenario_dsl.js +191 -0
- package/dist/nac3/scenario_dsl.js.map +1 -0
- package/dist/nac3/tokens.d.ts +126 -0
- package/dist/nac3/tokens.d.ts.map +1 -0
- package/dist/nac3/tokens.js +138 -0
- package/dist/nac3/tokens.js.map +1 -0
- package/dist/reader/parsers/csv.d.ts +42 -0
- package/dist/reader/parsers/csv.d.ts.map +1 -0
- package/dist/reader/parsers/csv.js +221 -0
- package/dist/reader/parsers/csv.js.map +1 -0
- package/dist/reader/parsers/docx.d.ts +31 -0
- package/dist/reader/parsers/docx.d.ts.map +1 -0
- package/dist/reader/parsers/docx.js +51 -0
- package/dist/reader/parsers/docx.js.map +1 -0
- package/dist/reader/parsers/epub.d.ts +39 -0
- package/dist/reader/parsers/epub.d.ts.map +1 -0
- package/dist/reader/parsers/epub.js +265 -0
- package/dist/reader/parsers/epub.js.map +1 -0
- package/dist/reader/parsers/html.d.ts +40 -0
- package/dist/reader/parsers/html.d.ts.map +1 -0
- package/dist/reader/parsers/html.js +386 -0
- package/dist/reader/parsers/html.js.map +1 -0
- package/dist/reader/parsers/md.d.ts +30 -0
- package/dist/reader/parsers/md.d.ts.map +1 -0
- package/dist/reader/parsers/md.js +199 -0
- package/dist/reader/parsers/md.js.map +1 -0
- package/dist/reader/parsers/pdf.d.ts +39 -0
- package/dist/reader/parsers/pdf.d.ts.map +1 -0
- package/dist/reader/parsers/pdf.js +220 -0
- package/dist/reader/parsers/pdf.js.map +1 -0
- package/dist/reader/parsers/rtf.d.ts +37 -0
- package/dist/reader/parsers/rtf.d.ts.map +1 -0
- package/dist/reader/parsers/rtf.js +347 -0
- package/dist/reader/parsers/rtf.js.map +1 -0
- package/dist/reader/parsers/source.d.ts +32 -0
- package/dist/reader/parsers/source.d.ts.map +1 -0
- package/dist/reader/parsers/source.js +122 -0
- package/dist/reader/parsers/source.js.map +1 -0
- package/dist/reader/parsers/txt.d.ts +25 -0
- package/dist/reader/parsers/txt.d.ts.map +1 -0
- package/dist/reader/parsers/txt.js +56 -0
- package/dist/reader/parsers/txt.js.map +1 -0
- package/dist/reader/parsers/xlsx.d.ts +33 -0
- package/dist/reader/parsers/xlsx.d.ts.map +1 -0
- package/dist/reader/parsers/xlsx.js +143 -0
- package/dist/reader/parsers/xlsx.js.map +1 -0
- package/dist/reader/registry.d.ts +39 -0
- package/dist/reader/registry.d.ts.map +1 -0
- package/dist/reader/registry.js +172 -0
- package/dist/reader/registry.js.map +1 -0
- package/dist/reader/search.d.ts +27 -0
- package/dist/reader/search.d.ts.map +1 -0
- package/dist/reader/search.js +77 -0
- package/dist/reader/search.js.map +1 -0
- package/dist/reader/state.d.ts +56 -0
- package/dist/reader/state.d.ts.map +1 -0
- package/dist/reader/state.js +179 -0
- package/dist/reader/state.js.map +1 -0
- package/dist/reader/types.d.ts +119 -0
- package/dist/reader/types.d.ts.map +1 -0
- package/dist/reader/types.js +23 -0
- package/dist/reader/types.js.map +1 -0
- package/dist/ship/run.d.ts +26 -0
- package/dist/ship/run.d.ts.map +1 -0
- package/dist/ship/run.js +123 -0
- package/dist/ship/run.js.map +1 -0
- package/dist/template/index.d.ts +50 -0
- package/dist/template/index.d.ts.map +1 -0
- package/dist/template/index.js +140 -0
- package/dist/template/index.js.map +1 -0
- package/dist/ui/colors.d.ts +13 -0
- package/dist/ui/colors.d.ts.map +1 -0
- package/dist/ui/colors.js +26 -0
- package/dist/ui/colors.js.map +1 -0
- package/dist/validate/index.d.ts +19 -0
- package/dist/validate/index.d.ts.map +1 -0
- package/dist/validate/index.js +181 -0
- package/dist/validate/index.js.map +1 -0
- package/dist/vault/catalog.d.ts +55 -0
- package/dist/vault/catalog.d.ts.map +1 -0
- package/dist/vault/catalog.js +424 -0
- package/dist/vault/catalog.js.map +1 -0
- package/dist/vault/crypto.d.ts +82 -0
- package/dist/vault/crypto.d.ts.map +1 -0
- package/dist/vault/crypto.js +173 -0
- package/dist/vault/crypto.js.map +1 -0
- package/dist/vault/git_askpass.d.ts +26 -0
- package/dist/vault/git_askpass.d.ts.map +1 -0
- package/dist/vault/git_askpass.js +104 -0
- package/dist/vault/git_askpass.js.map +1 -0
- package/dist/vault/migrator.d.ts +57 -0
- package/dist/vault/migrator.d.ts.map +1 -0
- package/dist/vault/migrator.js +204 -0
- package/dist/vault/migrator.js.map +1 -0
- package/dist/vault/redactor.d.ts +73 -0
- package/dist/vault/redactor.d.ts.map +1 -0
- package/dist/vault/redactor.js +182 -0
- package/dist/vault/redactor.js.map +1 -0
- package/dist/vault/store.d.ts +132 -0
- package/dist/vault/store.d.ts.map +1 -0
- package/dist/vault/store.js +335 -0
- package/dist/vault/store.js.map +1 -0
- package/dist/version.d.ts +8 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +8 -0
- package/dist/version.js.map +1 -0
- package/dist/voice/chunker.d.ts +43 -0
- package/dist/voice/chunker.d.ts.map +1 -0
- package/dist/voice/chunker.js +133 -0
- package/dist/voice/chunker.js.map +1 -0
- package/dist/voice/config.d.ts +14 -0
- package/dist/voice/config.d.ts.map +1 -0
- package/dist/voice/config.js +51 -0
- package/dist/voice/config.js.map +1 -0
- package/dist/voice/intents.d.ts +71 -0
- package/dist/voice/intents.d.ts.map +1 -0
- package/dist/voice/intents.js +0 -0
- package/dist/voice/intents.js.map +1 -0
- package/dist/voice/providers/elevenlabs.d.ts +53 -0
- package/dist/voice/providers/elevenlabs.d.ts.map +1 -0
- package/dist/voice/providers/elevenlabs.js +159 -0
- package/dist/voice/providers/elevenlabs.js.map +1 -0
- package/dist/voice/providers/google.d.ts +56 -0
- package/dist/voice/providers/google.d.ts.map +1 -0
- package/dist/voice/providers/google.js +253 -0
- package/dist/voice/providers/google.js.map +1 -0
- package/dist/voice/providers/whisper.d.ts +44 -0
- package/dist/voice/providers/whisper.d.ts.map +1 -0
- package/dist/voice/providers/whisper.js +179 -0
- package/dist/voice/providers/whisper.js.map +1 -0
- package/dist/voice/registry.d.ts +35 -0
- package/dist/voice/registry.d.ts.map +1 -0
- package/dist/voice/registry.js +48 -0
- package/dist/voice/registry.js.map +1 -0
- package/dist/voice/router.d.ts +62 -0
- package/dist/voice/router.d.ts.map +1 -0
- package/dist/voice/router.js +175 -0
- package/dist/voice/router.js.map +1 -0
- package/dist/voice/types.d.ts +116 -0
- package/dist/voice/types.d.ts.map +1 -0
- package/dist/voice/types.js +22 -0
- package/dist/voice/types.js.map +1 -0
- package/dist/voice/voiceprint/enrollment.d.ts +36 -0
- package/dist/voice/voiceprint/enrollment.d.ts.map +1 -0
- package/dist/voice/voiceprint/enrollment.js +71 -0
- package/dist/voice/voiceprint/enrollment.js.map +1 -0
- package/dist/voice/voiceprint/identify.d.ts +16 -0
- package/dist/voice/voiceprint/identify.d.ts.map +1 -0
- package/dist/voice/voiceprint/identify.js +20 -0
- package/dist/voice/voiceprint/identify.js.map +1 -0
- package/dist/voice/voiceprint/liveness.d.ts +90 -0
- package/dist/voice/voiceprint/liveness.d.ts.map +1 -0
- package/dist/voice/voiceprint/liveness.js +251 -0
- package/dist/voice/voiceprint/liveness.js.map +1 -0
- package/dist/voice/voiceprint/match.d.ts +54 -0
- package/dist/voice/voiceprint/match.d.ts.map +1 -0
- package/dist/voice/voiceprint/match.js +88 -0
- package/dist/voice/voiceprint/match.js.map +1 -0
- package/dist/voice/voiceprint/providers/local-mfcc-stub.d.ts +44 -0
- package/dist/voice/voiceprint/providers/local-mfcc-stub.d.ts.map +1 -0
- package/dist/voice/voiceprint/providers/local-mfcc-stub.js +92 -0
- package/dist/voice/voiceprint/providers/local-mfcc-stub.js.map +1 -0
- package/dist/voice/voiceprint/store.d.ts +60 -0
- package/dist/voice/voiceprint/store.d.ts.map +1 -0
- package/dist/voice/voiceprint/store.js +155 -0
- package/dist/voice/voiceprint/store.js.map +1 -0
- package/dist/voice/voiceprint/trust.d.ts +90 -0
- package/dist/voice/voiceprint/trust.d.ts.map +1 -0
- package/dist/voice/voiceprint/trust.js +150 -0
- package/dist/voice/voiceprint/trust.js.map +1 -0
- package/dist/voice/voiceprint/types.d.ts +100 -0
- package/dist/voice/voiceprint/types.d.ts.map +1 -0
- package/dist/voice/voiceprint/types.js +23 -0
- package/dist/voice/voiceprint/types.js.map +1 -0
- package/dist/voice/wake.d.ts +64 -0
- package/dist/voice/wake.d.ts.map +1 -0
- package/dist/voice/wake.js +143 -0
- package/dist/voice/wake.js.map +1 -0
- package/docs/manuals/manual.ar.html +91 -0
- package/docs/manuals/manual.de.html +100 -0
- package/docs/manuals/manual.en.html +118 -0
- package/docs/manuals/manual.es.html +120 -0
- package/docs/manuals/manual.fr.html +102 -0
- package/docs/manuals/manual.hi.html +93 -0
- package/docs/manuals/manual.it.html +93 -0
- package/docs/manuals/manual.ja.html +97 -0
- package/docs/manuals/manual.pt.html +103 -0
- package/docs/manuals/manual.zh.html +89 -0
- package/package.json +94 -0
- package/src/i18n/catalogs/ar.json +86 -0
- package/src/i18n/catalogs/de.json +86 -0
- package/src/i18n/catalogs/en.json +86 -0
- package/src/i18n/catalogs/es.json +86 -0
- package/src/i18n/catalogs/fr.json +86 -0
- package/src/i18n/catalogs/hi.json +86 -0
- package/src/i18n/catalogs/it.json +86 -0
- package/src/i18n/catalogs/ja.json +86 -0
- package/src/i18n/catalogs/pt.json +86 -0
- package/src/i18n/catalogs/zh.json +86 -0
- package/templates/react-app/README.md +43 -0
- package/templates/react-app/index.html +12 -0
- package/templates/react-app/package.json +35 -0
- package/templates/react-app/src/App.tsx +106 -0
- package/templates/react-app/src/main.tsx +21 -0
- package/templates/react-app/src/nac/manifest.ts +46 -0
- package/templates/react-app/src/styles.css +68 -0
- package/templates/react-app/tsconfig.json +19 -0
- package/templates/react-app/vite.config.ts +12 -0
- package/templates/react-app/yujin.forge.json +15 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Yujin Forge -- project validator.
|
|
3
|
+
*
|
|
4
|
+
* Verifies that a directory looks like a Yujin Forge project. The
|
|
5
|
+
* check is static (no compile, no install). Useful day-1 as:
|
|
6
|
+
*
|
|
7
|
+
* - a pre-commit hook
|
|
8
|
+
* - a CI gate (yf validate --strict && yf test && yf ship)
|
|
9
|
+
* - a sanity probe after `yf new` / `yf migrate --apply`
|
|
10
|
+
*
|
|
11
|
+
* The full NAC-3 manifest validator (label_i18n completeness for
|
|
12
|
+
* all 10 locales, verb declarations, ack contract) lands once the
|
|
13
|
+
* @yujin/nac runtime is published; this stage focuses on the
|
|
14
|
+
* structural contract that doesn't depend on the runtime.
|
|
15
|
+
*/
|
|
16
|
+
import { promises as fs } from 'node:fs';
|
|
17
|
+
import path from 'node:path';
|
|
18
|
+
import { isValidSlug } from '../template/index.js';
|
|
19
|
+
const REQUIRED_FORGE_FIELDS = [
|
|
20
|
+
'project_slug',
|
|
21
|
+
'project_name',
|
|
22
|
+
'forge_version',
|
|
23
|
+
'nac_version',
|
|
24
|
+
];
|
|
25
|
+
export async function validateProject(opts) {
|
|
26
|
+
const findings = [];
|
|
27
|
+
await checkForgeJson(opts.projectRoot, findings);
|
|
28
|
+
await checkPackageJson(opts.projectRoot, findings);
|
|
29
|
+
await checkSrcDir(opts.projectRoot, findings);
|
|
30
|
+
const errorCount = findings.filter((f) => f.severity === 'error').length;
|
|
31
|
+
const warnCount = findings.filter((f) => f.severity === 'warn').length;
|
|
32
|
+
const ok = errorCount === 0 && (!opts.strict || warnCount === 0);
|
|
33
|
+
return {
|
|
34
|
+
project_root: opts.projectRoot,
|
|
35
|
+
findings,
|
|
36
|
+
ok,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
async function checkForgeJson(root, out) {
|
|
40
|
+
const p = path.join(root, 'yujin.forge.json');
|
|
41
|
+
let raw;
|
|
42
|
+
try {
|
|
43
|
+
raw = await fs.readFile(p, 'utf-8');
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
if (err.code === 'ENOENT') {
|
|
47
|
+
out.push({
|
|
48
|
+
severity: 'error',
|
|
49
|
+
code: 'forge_json_missing',
|
|
50
|
+
message: 'yujin.forge.json not found at ' + p,
|
|
51
|
+
});
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
throw err;
|
|
55
|
+
}
|
|
56
|
+
let parsed;
|
|
57
|
+
try {
|
|
58
|
+
parsed = JSON.parse(raw);
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
out.push({
|
|
62
|
+
severity: 'error',
|
|
63
|
+
code: 'forge_json_unparseable',
|
|
64
|
+
message: 'yujin.forge.json is not valid JSON: '
|
|
65
|
+
+ (err instanceof Error ? err.message : String(err)),
|
|
66
|
+
});
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
70
|
+
out.push({
|
|
71
|
+
severity: 'error',
|
|
72
|
+
code: 'forge_json_not_object',
|
|
73
|
+
message: 'yujin.forge.json must be a JSON object',
|
|
74
|
+
});
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const obj = parsed;
|
|
78
|
+
for (const field of REQUIRED_FORGE_FIELDS) {
|
|
79
|
+
if (!(field in obj)) {
|
|
80
|
+
out.push({
|
|
81
|
+
severity: 'error',
|
|
82
|
+
code: 'forge_json_missing_field',
|
|
83
|
+
message: "yujin.forge.json missing required field '" + field + "'",
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const slug = obj['project_slug'];
|
|
88
|
+
if (typeof slug === 'string' && !isValidSlug(slug)) {
|
|
89
|
+
out.push({
|
|
90
|
+
severity: 'error',
|
|
91
|
+
code: 'forge_json_invalid_slug',
|
|
92
|
+
message: "project_slug '" + slug + "' is not a valid slug (lowercase, dash, 3..40 chars, starts with a letter)",
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
const tel = obj['telemetry'];
|
|
96
|
+
if (tel !== undefined && (typeof tel !== 'object' || tel === null || Array.isArray(tel))) {
|
|
97
|
+
out.push({
|
|
98
|
+
severity: 'warn',
|
|
99
|
+
code: 'forge_json_telemetry_shape',
|
|
100
|
+
message: "yujin.forge.json 'telemetry' must be an object when present",
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async function checkPackageJson(root, out) {
|
|
105
|
+
const p = path.join(root, 'package.json');
|
|
106
|
+
let raw;
|
|
107
|
+
try {
|
|
108
|
+
raw = await fs.readFile(p, 'utf-8');
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
if (err.code === 'ENOENT') {
|
|
112
|
+
out.push({
|
|
113
|
+
severity: 'error',
|
|
114
|
+
code: 'package_json_missing',
|
|
115
|
+
message: 'package.json not found at ' + p,
|
|
116
|
+
});
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
throw err;
|
|
120
|
+
}
|
|
121
|
+
let pkg;
|
|
122
|
+
try {
|
|
123
|
+
pkg = JSON.parse(raw);
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
out.push({
|
|
127
|
+
severity: 'error',
|
|
128
|
+
code: 'package_json_unparseable',
|
|
129
|
+
message: 'package.json is not valid JSON',
|
|
130
|
+
});
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const deps = {
|
|
134
|
+
...(asDeps(pkg['dependencies'])),
|
|
135
|
+
...(asDeps(pkg['devDependencies'])),
|
|
136
|
+
...(asDeps(pkg['peerDependencies'])),
|
|
137
|
+
};
|
|
138
|
+
if (!('@yujin/nac' in deps) && !('@yujin/nac-commercial' in deps)) {
|
|
139
|
+
out.push({
|
|
140
|
+
severity: 'warn',
|
|
141
|
+
code: 'package_json_no_nac_dep',
|
|
142
|
+
message: "package.json does not depend on '@yujin/nac' or '@yujin/nac-commercial'",
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function asDeps(v) {
|
|
147
|
+
if (typeof v !== 'object' || v === null || Array.isArray(v))
|
|
148
|
+
return {};
|
|
149
|
+
const out = {};
|
|
150
|
+
for (const [k, val] of Object.entries(v)) {
|
|
151
|
+
if (typeof val === 'string')
|
|
152
|
+
out[k] = val;
|
|
153
|
+
}
|
|
154
|
+
return out;
|
|
155
|
+
}
|
|
156
|
+
async function checkSrcDir(root, out) {
|
|
157
|
+
const p = path.join(root, 'src');
|
|
158
|
+
try {
|
|
159
|
+
const stat = await fs.stat(p);
|
|
160
|
+
if (!stat.isDirectory()) {
|
|
161
|
+
out.push({
|
|
162
|
+
severity: 'error',
|
|
163
|
+
code: 'src_not_a_directory',
|
|
164
|
+
message: 'src/ exists but is not a directory',
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
if (err.code === 'ENOENT') {
|
|
170
|
+
out.push({
|
|
171
|
+
severity: 'error',
|
|
172
|
+
code: 'src_missing',
|
|
173
|
+
message: 'src/ directory not found at ' + p,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
throw err;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/validate/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vault slot catalog -- predefined slot names with their kind,
|
|
3
|
+
* description, and reachability test.
|
|
4
|
+
*
|
|
5
|
+
* Per SQ sec 0.11, Forge ships with a catalog of well-known
|
|
6
|
+
* credentials so the user does not have to remember the exact
|
|
7
|
+
* slot name + the kind classification. Slots that are NOT in
|
|
8
|
+
* the catalog are accepted as `kind: 'custom'`.
|
|
9
|
+
*
|
|
10
|
+
* The test function lets `yf vault test <name>` verify the
|
|
11
|
+
* credential is still valid against the external service.
|
|
12
|
+
* Network calls go out via Node's global fetch (Node 18+);
|
|
13
|
+
* timeout is enforced via AbortController so the doctor /
|
|
14
|
+
* panel does not hang on offline services.
|
|
15
|
+
*
|
|
16
|
+
* ASCII-only.
|
|
17
|
+
*/
|
|
18
|
+
export declare const SLOT_KINDS: readonly ["repo", "registry", "ai", "cloud", "app", "custom"];
|
|
19
|
+
export type SlotKind = (typeof SLOT_KINDS)[number];
|
|
20
|
+
export interface SlotCatalogEntry {
|
|
21
|
+
/** Canonical slot name. */
|
|
22
|
+
name: string;
|
|
23
|
+
/** Classification per SQ 0.11. */
|
|
24
|
+
kind: Exclude<SlotKind, 'custom'>;
|
|
25
|
+
/** Human-readable description shown in the UI. ASCII-only. */
|
|
26
|
+
description: string;
|
|
27
|
+
/** Where the user obtains this credential (URL). */
|
|
28
|
+
obtainUrl?: string;
|
|
29
|
+
/** Optional probe that hits the service and returns ok=true
|
|
30
|
+
* when the credential is valid + 200 OK. Always returns
|
|
31
|
+
* within `timeoutMs`. */
|
|
32
|
+
test?: (plaintext: string, opts: SlotTestOptions) => Promise<SlotTestResult>;
|
|
33
|
+
}
|
|
34
|
+
export interface SlotTestOptions {
|
|
35
|
+
timeoutMs: number;
|
|
36
|
+
}
|
|
37
|
+
export interface SlotTestResult {
|
|
38
|
+
ok: boolean;
|
|
39
|
+
/** HTTP status from the probe response (or 0 if network failure). */
|
|
40
|
+
status: number;
|
|
41
|
+
/** Service-side detail when ok=false (e.g. "bad_credentials"). */
|
|
42
|
+
detail?: string;
|
|
43
|
+
/** Latency of the probe in ms. */
|
|
44
|
+
latency_ms: number;
|
|
45
|
+
}
|
|
46
|
+
export declare const SLOT_CATALOG: SlotCatalogEntry[];
|
|
47
|
+
/** Look up a catalog entry by exact name. Returns undefined
|
|
48
|
+
* when the slot is custom (user-defined). */
|
|
49
|
+
export declare function lookupCatalog(name: string): SlotCatalogEntry | undefined;
|
|
50
|
+
/** Infer the kind for a slot name: catalog hit -> its kind,
|
|
51
|
+
* miss -> 'custom'. */
|
|
52
|
+
export declare function inferKind(name: string): SlotKind;
|
|
53
|
+
/** Indexed view of the catalog by kind. */
|
|
54
|
+
export declare function catalogByKind(): Record<SlotKind, SlotCatalogEntry[]>;
|
|
55
|
+
//# sourceMappingURL=catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/vault/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,eAAO,MAAM,UAAU,+DAAgE,CAAC;AACxF,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAC/B,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAClC,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;8BAE0B;IAC1B,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;CAC9E;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAC;CACpB;AA0RD,eAAO,MAAM,YAAY,EAAE,gBAAgB,EA2G1C,CAAC;AAEF;8CAC8C;AAC9C,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAExE;AAED;wBACwB;AACxB,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAGhD;AAED,2CAA2C;AAC3C,wBAAgB,aAAa,IAAI,MAAM,CAAC,QAAQ,EAAE,gBAAgB,EAAE,CAAC,CAMpE"}
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vault slot catalog -- predefined slot names with their kind,
|
|
3
|
+
* description, and reachability test.
|
|
4
|
+
*
|
|
5
|
+
* Per SQ sec 0.11, Forge ships with a catalog of well-known
|
|
6
|
+
* credentials so the user does not have to remember the exact
|
|
7
|
+
* slot name + the kind classification. Slots that are NOT in
|
|
8
|
+
* the catalog are accepted as `kind: 'custom'`.
|
|
9
|
+
*
|
|
10
|
+
* The test function lets `yf vault test <name>` verify the
|
|
11
|
+
* credential is still valid against the external service.
|
|
12
|
+
* Network calls go out via Node's global fetch (Node 18+);
|
|
13
|
+
* timeout is enforced via AbortController so the doctor /
|
|
14
|
+
* panel does not hang on offline services.
|
|
15
|
+
*
|
|
16
|
+
* ASCII-only.
|
|
17
|
+
*/
|
|
18
|
+
export const SLOT_KINDS = ['repo', 'registry', 'ai', 'cloud', 'app', 'custom'];
|
|
19
|
+
/* Helper to wrap fetch with a timeout. */
|
|
20
|
+
async function probeFetch(url, init, timeoutMs) {
|
|
21
|
+
const ctrl = new AbortController();
|
|
22
|
+
const timer = setTimeout(() => ctrl.abort(), timeoutMs);
|
|
23
|
+
const t0 = Date.now();
|
|
24
|
+
try {
|
|
25
|
+
const res = await fetch(url, { ...init, signal: ctrl.signal });
|
|
26
|
+
const text = await res.text();
|
|
27
|
+
return { status: res.status, bodyText: text, latency_ms: Date.now() - t0 };
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
31
|
+
return { status: 0, bodyText: '', latency_ms: Date.now() - t0, err: msg };
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
clearTimeout(timer);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/* ---------- repo ---------- */
|
|
38
|
+
const githubTest = async (token, opts) => {
|
|
39
|
+
const r = await probeFetch('https://api.github.com/user', {
|
|
40
|
+
headers: { authorization: 'token ' + token, accept: 'application/vnd.github+json',
|
|
41
|
+
'user-agent': 'yujin-forge' },
|
|
42
|
+
}, opts.timeoutMs);
|
|
43
|
+
if (r.err)
|
|
44
|
+
return { ok: false, status: 0, detail: r.err, latency_ms: r.latency_ms };
|
|
45
|
+
if (r.status === 200)
|
|
46
|
+
return { ok: true, status: 200, latency_ms: r.latency_ms };
|
|
47
|
+
return { ok: false, status: r.status, detail: extractError(r.bodyText), latency_ms: r.latency_ms };
|
|
48
|
+
};
|
|
49
|
+
const gitlabTest = async (token, opts) => {
|
|
50
|
+
const r = await probeFetch('https://gitlab.com/api/v4/user', {
|
|
51
|
+
headers: { 'private-token': token, 'user-agent': 'yujin-forge' },
|
|
52
|
+
}, opts.timeoutMs);
|
|
53
|
+
if (r.err)
|
|
54
|
+
return { ok: false, status: 0, detail: r.err, latency_ms: r.latency_ms };
|
|
55
|
+
return r.status === 200
|
|
56
|
+
? { ok: true, status: 200, latency_ms: r.latency_ms }
|
|
57
|
+
: { ok: false, status: r.status, detail: extractError(r.bodyText), latency_ms: r.latency_ms };
|
|
58
|
+
};
|
|
59
|
+
const bitbucketTest = async (token, opts) => {
|
|
60
|
+
/* Bitbucket App Password requires user:pass. We expect the
|
|
61
|
+
slot value to be either `user:password` or just the
|
|
62
|
+
password (in which case test result is unreliable). */
|
|
63
|
+
const auth = token.includes(':') ? token : 'x-token-auth:' + token;
|
|
64
|
+
const r = await probeFetch('https://api.bitbucket.org/2.0/user', {
|
|
65
|
+
headers: {
|
|
66
|
+
authorization: 'Basic ' + Buffer.from(auth).toString('base64'),
|
|
67
|
+
'user-agent': 'yujin-forge',
|
|
68
|
+
},
|
|
69
|
+
}, opts.timeoutMs);
|
|
70
|
+
if (r.err)
|
|
71
|
+
return { ok: false, status: 0, detail: r.err, latency_ms: r.latency_ms };
|
|
72
|
+
return r.status === 200
|
|
73
|
+
? { ok: true, status: 200, latency_ms: r.latency_ms }
|
|
74
|
+
: { ok: false, status: r.status, detail: extractError(r.bodyText), latency_ms: r.latency_ms };
|
|
75
|
+
};
|
|
76
|
+
/* ---------- registry ---------- */
|
|
77
|
+
const npmTest = async (token, opts) => {
|
|
78
|
+
const r = await probeFetch('https://registry.npmjs.org/-/whoami', {
|
|
79
|
+
headers: { authorization: 'Bearer ' + token, accept: 'application/json',
|
|
80
|
+
'user-agent': 'yujin-forge' },
|
|
81
|
+
}, opts.timeoutMs);
|
|
82
|
+
if (r.err)
|
|
83
|
+
return { ok: false, status: 0, detail: r.err, latency_ms: r.latency_ms };
|
|
84
|
+
return r.status === 200
|
|
85
|
+
? { ok: true, status: 200, latency_ms: r.latency_ms }
|
|
86
|
+
: { ok: false, status: r.status, detail: extractError(r.bodyText), latency_ms: r.latency_ms };
|
|
87
|
+
};
|
|
88
|
+
const pypiTest = async (token, opts) => {
|
|
89
|
+
/* PyPI does not expose a generic whoami; we probe the upload
|
|
90
|
+
endpoint with an OPTIONS request which validates auth
|
|
91
|
+
without uploading. */
|
|
92
|
+
const r = await probeFetch('https://upload.pypi.org/legacy/', {
|
|
93
|
+
method: 'OPTIONS',
|
|
94
|
+
headers: { authorization: 'Basic ' + Buffer.from('__token__:' + token).toString('base64'),
|
|
95
|
+
'user-agent': 'yujin-forge' },
|
|
96
|
+
}, opts.timeoutMs);
|
|
97
|
+
if (r.err)
|
|
98
|
+
return { ok: false, status: 0, detail: r.err, latency_ms: r.latency_ms };
|
|
99
|
+
return r.status === 200 || r.status === 204
|
|
100
|
+
? { ok: true, status: r.status, latency_ms: r.latency_ms }
|
|
101
|
+
: { ok: false, status: r.status, detail: extractError(r.bodyText), latency_ms: r.latency_ms };
|
|
102
|
+
};
|
|
103
|
+
const dockerTest = async (token, opts) => {
|
|
104
|
+
/* DockerHub Personal Access Token -- the JWT auth endpoint
|
|
105
|
+
accepts the PAT as password for the username:PAT pair. We
|
|
106
|
+
can't do a clean whoami without the username, so we check
|
|
107
|
+
the rate-limit endpoint which only requires a valid token. */
|
|
108
|
+
const r = await probeFetch('https://hub.docker.com/v2/user/', {
|
|
109
|
+
headers: { authorization: 'Bearer ' + token, 'user-agent': 'yujin-forge' },
|
|
110
|
+
}, opts.timeoutMs);
|
|
111
|
+
if (r.err)
|
|
112
|
+
return { ok: false, status: 0, detail: r.err, latency_ms: r.latency_ms };
|
|
113
|
+
return r.status === 200
|
|
114
|
+
? { ok: true, status: 200, latency_ms: r.latency_ms }
|
|
115
|
+
: { ok: false, status: r.status, detail: extractError(r.bodyText), latency_ms: r.latency_ms };
|
|
116
|
+
};
|
|
117
|
+
/* ---------- ai ---------- */
|
|
118
|
+
const anthropicTest = async (key, opts) => {
|
|
119
|
+
/* Minimal Anthropic ping: small messages request that the
|
|
120
|
+
API can reject with auth-error without billing tokens. */
|
|
121
|
+
const r = await probeFetch('https://api.anthropic.com/v1/messages', {
|
|
122
|
+
method: 'POST',
|
|
123
|
+
headers: {
|
|
124
|
+
'x-api-key': key, 'anthropic-version': '2023-06-01',
|
|
125
|
+
'content-type': 'application/json', 'user-agent': 'yujin-forge',
|
|
126
|
+
},
|
|
127
|
+
body: JSON.stringify({
|
|
128
|
+
model: 'claude-haiku-4-5-20251001',
|
|
129
|
+
max_tokens: 1,
|
|
130
|
+
messages: [{ role: 'user', content: 'ping' }],
|
|
131
|
+
}),
|
|
132
|
+
}, opts.timeoutMs);
|
|
133
|
+
if (r.err)
|
|
134
|
+
return { ok: false, status: 0, detail: r.err, latency_ms: r.latency_ms };
|
|
135
|
+
/* 200 OK = good. 401 = bad key. 400 etc = key is good but
|
|
136
|
+
payload tweaked -- still counts as authenticated. */
|
|
137
|
+
if (r.status === 200)
|
|
138
|
+
return { ok: true, status: 200, latency_ms: r.latency_ms };
|
|
139
|
+
if (r.status === 401 || r.status === 403) {
|
|
140
|
+
return { ok: false, status: r.status, detail: extractError(r.bodyText), latency_ms: r.latency_ms };
|
|
141
|
+
}
|
|
142
|
+
/* Anything else (400, 429, 5xx) means the key was accepted
|
|
143
|
+
by the auth layer but something else broke -- treat as
|
|
144
|
+
authenticated. */
|
|
145
|
+
return { ok: true, status: r.status, detail: 'auth ok; payload rejected', latency_ms: r.latency_ms };
|
|
146
|
+
};
|
|
147
|
+
const openaiTest = async (key, opts) => {
|
|
148
|
+
const r = await probeFetch('https://api.openai.com/v1/models', {
|
|
149
|
+
headers: { authorization: 'Bearer ' + key, 'user-agent': 'yujin-forge' },
|
|
150
|
+
}, opts.timeoutMs);
|
|
151
|
+
if (r.err)
|
|
152
|
+
return { ok: false, status: 0, detail: r.err, latency_ms: r.latency_ms };
|
|
153
|
+
return r.status === 200
|
|
154
|
+
? { ok: true, status: 200, latency_ms: r.latency_ms }
|
|
155
|
+
: { ok: false, status: r.status, detail: extractError(r.bodyText), latency_ms: r.latency_ms };
|
|
156
|
+
};
|
|
157
|
+
const elevenlabsTest = async (key, opts) => {
|
|
158
|
+
const r = await probeFetch('https://api.elevenlabs.io/v1/user', {
|
|
159
|
+
headers: { 'xi-api-key': key, 'user-agent': 'yujin-forge' },
|
|
160
|
+
}, opts.timeoutMs);
|
|
161
|
+
if (r.err)
|
|
162
|
+
return { ok: false, status: 0, detail: r.err, latency_ms: r.latency_ms };
|
|
163
|
+
return r.status === 200
|
|
164
|
+
? { ok: true, status: 200, latency_ms: r.latency_ms }
|
|
165
|
+
: { ok: false, status: r.status, detail: extractError(r.bodyText), latency_ms: r.latency_ms };
|
|
166
|
+
};
|
|
167
|
+
const googleVoiceTest = async (key, opts) => {
|
|
168
|
+
/* Google Cloud TTS lives behind a service account; the slot
|
|
169
|
+
stores the JSON SA file. We do a syntactic check (parses
|
|
170
|
+
as JSON with required fields). Network probe would need
|
|
171
|
+
token exchange which is heavier. */
|
|
172
|
+
let parsed = null;
|
|
173
|
+
try {
|
|
174
|
+
parsed = JSON.parse(key);
|
|
175
|
+
}
|
|
176
|
+
catch { /* not JSON */ }
|
|
177
|
+
if (!parsed || parsed.type !== 'service_account' || !parsed.client_email) {
|
|
178
|
+
return {
|
|
179
|
+
ok: false, status: 0,
|
|
180
|
+
detail: 'value is not a Google service-account JSON',
|
|
181
|
+
latency_ms: 0,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
return { ok: true, status: 200, latency_ms: 0, detail: 'syntactic check (no network probe)' };
|
|
185
|
+
};
|
|
186
|
+
/* ---------- cloud ---------- */
|
|
187
|
+
const awsTest = async (_value, _opts) => {
|
|
188
|
+
/* AWS sigv4 signing is heavy; we just emit a syntactic check
|
|
189
|
+
marker. Real auth happens when a tool uses the key. */
|
|
190
|
+
return { ok: true, status: 200, latency_ms: 0,
|
|
191
|
+
detail: 'syntactic check (no STS probe in this slice)' };
|
|
192
|
+
};
|
|
193
|
+
/* ---------- app ---------- */
|
|
194
|
+
const slackTest = async (token, opts) => {
|
|
195
|
+
const r = await probeFetch('https://slack.com/api/auth.test', {
|
|
196
|
+
method: 'POST',
|
|
197
|
+
headers: { authorization: 'Bearer ' + token, 'user-agent': 'yujin-forge' },
|
|
198
|
+
}, opts.timeoutMs);
|
|
199
|
+
if (r.err)
|
|
200
|
+
return { ok: false, status: 0, detail: r.err, latency_ms: r.latency_ms };
|
|
201
|
+
let body = {};
|
|
202
|
+
try {
|
|
203
|
+
body = JSON.parse(r.bodyText);
|
|
204
|
+
}
|
|
205
|
+
catch { /* leave as {} */ }
|
|
206
|
+
return body.ok
|
|
207
|
+
? { ok: true, status: r.status, latency_ms: r.latency_ms }
|
|
208
|
+
: { ok: false, status: r.status, detail: body.error || extractError(r.bodyText), latency_ms: r.latency_ms };
|
|
209
|
+
};
|
|
210
|
+
const discordTest = async (token, opts) => {
|
|
211
|
+
const r = await probeFetch('https://discord.com/api/v10/users/@me', {
|
|
212
|
+
headers: { authorization: 'Bot ' + token, 'user-agent': 'yujin-forge' },
|
|
213
|
+
}, opts.timeoutMs);
|
|
214
|
+
if (r.err)
|
|
215
|
+
return { ok: false, status: 0, detail: r.err, latency_ms: r.latency_ms };
|
|
216
|
+
return r.status === 200
|
|
217
|
+
? { ok: true, status: 200, latency_ms: r.latency_ms }
|
|
218
|
+
: { ok: false, status: r.status, detail: extractError(r.bodyText), latency_ms: r.latency_ms };
|
|
219
|
+
};
|
|
220
|
+
const stripeTest = async (key, opts) => {
|
|
221
|
+
const r = await probeFetch('https://api.stripe.com/v1/balance', {
|
|
222
|
+
headers: { authorization: 'Bearer ' + key, 'user-agent': 'yujin-forge' },
|
|
223
|
+
}, opts.timeoutMs);
|
|
224
|
+
if (r.err)
|
|
225
|
+
return { ok: false, status: 0, detail: r.err, latency_ms: r.latency_ms };
|
|
226
|
+
return r.status === 200
|
|
227
|
+
? { ok: true, status: 200, latency_ms: r.latency_ms }
|
|
228
|
+
: { ok: false, status: r.status, detail: extractError(r.bodyText), latency_ms: r.latency_ms };
|
|
229
|
+
};
|
|
230
|
+
const sendgridTest = async (key, opts) => {
|
|
231
|
+
const r = await probeFetch('https://api.sendgrid.com/v3/scopes', {
|
|
232
|
+
headers: { authorization: 'Bearer ' + key, 'user-agent': 'yujin-forge' },
|
|
233
|
+
}, opts.timeoutMs);
|
|
234
|
+
if (r.err)
|
|
235
|
+
return { ok: false, status: 0, detail: r.err, latency_ms: r.latency_ms };
|
|
236
|
+
return r.status === 200
|
|
237
|
+
? { ok: true, status: 200, latency_ms: r.latency_ms }
|
|
238
|
+
: { ok: false, status: r.status, detail: extractError(r.bodyText), latency_ms: r.latency_ms };
|
|
239
|
+
};
|
|
240
|
+
const linearTest = async (token, opts) => {
|
|
241
|
+
const r = await probeFetch('https://api.linear.app/graphql', {
|
|
242
|
+
method: 'POST',
|
|
243
|
+
headers: { authorization: token, 'content-type': 'application/json',
|
|
244
|
+
'user-agent': 'yujin-forge' },
|
|
245
|
+
body: JSON.stringify({ query: '{ viewer { id } }' }),
|
|
246
|
+
}, opts.timeoutMs);
|
|
247
|
+
if (r.err)
|
|
248
|
+
return { ok: false, status: 0, detail: r.err, latency_ms: r.latency_ms };
|
|
249
|
+
return r.status === 200
|
|
250
|
+
? { ok: true, status: 200, latency_ms: r.latency_ms }
|
|
251
|
+
: { ok: false, status: r.status, detail: extractError(r.bodyText), latency_ms: r.latency_ms };
|
|
252
|
+
};
|
|
253
|
+
const notionTest = async (token, opts) => {
|
|
254
|
+
const r = await probeFetch('https://api.notion.com/v1/users/me', {
|
|
255
|
+
headers: { authorization: 'Bearer ' + token, 'notion-version': '2022-06-28',
|
|
256
|
+
'user-agent': 'yujin-forge' },
|
|
257
|
+
}, opts.timeoutMs);
|
|
258
|
+
if (r.err)
|
|
259
|
+
return { ok: false, status: 0, detail: r.err, latency_ms: r.latency_ms };
|
|
260
|
+
return r.status === 200
|
|
261
|
+
? { ok: true, status: 200, latency_ms: r.latency_ms }
|
|
262
|
+
: { ok: false, status: r.status, detail: extractError(r.bodyText), latency_ms: r.latency_ms };
|
|
263
|
+
};
|
|
264
|
+
const figmaTest = async (token, opts) => {
|
|
265
|
+
const r = await probeFetch('https://api.figma.com/v1/me', {
|
|
266
|
+
headers: { 'x-figma-token': token, 'user-agent': 'yujin-forge' },
|
|
267
|
+
}, opts.timeoutMs);
|
|
268
|
+
if (r.err)
|
|
269
|
+
return { ok: false, status: 0, detail: r.err, latency_ms: r.latency_ms };
|
|
270
|
+
return r.status === 200
|
|
271
|
+
? { ok: true, status: 200, latency_ms: r.latency_ms }
|
|
272
|
+
: { ok: false, status: r.status, detail: extractError(r.bodyText), latency_ms: r.latency_ms };
|
|
273
|
+
};
|
|
274
|
+
const twilioTest = async (_token, _opts) => {
|
|
275
|
+
/* Twilio requires SID + auth_token as basic; we cannot probe
|
|
276
|
+
just one. Emit a syntactic check that the value looks like
|
|
277
|
+
an auth token (32 hex chars). */
|
|
278
|
+
const ok = /^[a-f0-9]{32,}$/.test(_token);
|
|
279
|
+
return { ok, status: ok ? 200 : 0,
|
|
280
|
+
detail: ok ? 'syntactic check (needs paired twilio_account_sid for real probe)'
|
|
281
|
+
: 'value does not look like a 32-hex auth token',
|
|
282
|
+
latency_ms: 0 };
|
|
283
|
+
};
|
|
284
|
+
function extractError(bodyText) {
|
|
285
|
+
if (!bodyText)
|
|
286
|
+
return '';
|
|
287
|
+
try {
|
|
288
|
+
const parsed = JSON.parse(bodyText);
|
|
289
|
+
if (parsed.message)
|
|
290
|
+
return String(parsed.message).slice(0, 120);
|
|
291
|
+
if (parsed.error)
|
|
292
|
+
return String(parsed.error).slice(0, 120);
|
|
293
|
+
if (parsed.detail)
|
|
294
|
+
return String(parsed.detail).slice(0, 120);
|
|
295
|
+
}
|
|
296
|
+
catch { /* fall through */ }
|
|
297
|
+
return bodyText.slice(0, 120);
|
|
298
|
+
}
|
|
299
|
+
/* The catalog itself. Order is preserved for UI listing. */
|
|
300
|
+
export const SLOT_CATALOG = [
|
|
301
|
+
/* repo */
|
|
302
|
+
{ name: 'github_token', kind: 'repo',
|
|
303
|
+
description: 'GitHub Personal Access Token (ghp_* / github_pat_*)',
|
|
304
|
+
obtainUrl: 'https://github.com/settings/tokens',
|
|
305
|
+
test: githubTest },
|
|
306
|
+
{ name: 'gitlab_token', kind: 'repo',
|
|
307
|
+
description: 'GitLab Personal Access Token (glpat-*)',
|
|
308
|
+
obtainUrl: 'https://gitlab.com/-/user_settings/personal_access_tokens',
|
|
309
|
+
test: gitlabTest },
|
|
310
|
+
{ name: 'bitbucket_token', kind: 'repo',
|
|
311
|
+
description: 'Bitbucket App Password (paired user:pwd or pwd only)',
|
|
312
|
+
obtainUrl: 'https://bitbucket.org/account/settings/app-passwords/',
|
|
313
|
+
test: bitbucketTest },
|
|
314
|
+
{ name: 'ssh_key', kind: 'repo',
|
|
315
|
+
description: 'SSH private key for repo push (paste full PEM body)' },
|
|
316
|
+
/* registry */
|
|
317
|
+
{ name: 'npm_token', kind: 'registry',
|
|
318
|
+
description: 'npmjs.com automation token (Publish + Read)',
|
|
319
|
+
obtainUrl: 'https://www.npmjs.com/settings/~/tokens',
|
|
320
|
+
test: npmTest },
|
|
321
|
+
{ name: 'pypi_token', kind: 'registry',
|
|
322
|
+
description: 'PyPI API token (starts with pypi-*)',
|
|
323
|
+
obtainUrl: 'https://pypi.org/manage/account/token/',
|
|
324
|
+
test: pypiTest },
|
|
325
|
+
{ name: 'maven_token', kind: 'registry',
|
|
326
|
+
description: 'Sonatype OSSRH token (user:password)' },
|
|
327
|
+
{ name: 'docker_token', kind: 'registry',
|
|
328
|
+
description: 'DockerHub Personal Access Token',
|
|
329
|
+
obtainUrl: 'https://hub.docker.com/settings/security',
|
|
330
|
+
test: dockerTest },
|
|
331
|
+
{ name: 'homebrew_token', kind: 'registry',
|
|
332
|
+
description: 'GitHub token with repo scope for brew tap publishing' },
|
|
333
|
+
/* ai */
|
|
334
|
+
{ name: 'anthropic', kind: 'ai',
|
|
335
|
+
description: 'Anthropic API key (sk-ant-*)',
|
|
336
|
+
obtainUrl: 'https://console.anthropic.com/settings/keys',
|
|
337
|
+
test: anthropicTest },
|
|
338
|
+
{ name: 'openai', kind: 'ai',
|
|
339
|
+
description: 'OpenAI API key (sk-* or sk-proj-*)',
|
|
340
|
+
obtainUrl: 'https://platform.openai.com/api-keys',
|
|
341
|
+
test: openaiTest },
|
|
342
|
+
{ name: 'elevenlabs', kind: 'ai',
|
|
343
|
+
description: 'ElevenLabs API key',
|
|
344
|
+
obtainUrl: 'https://elevenlabs.io/app/settings/api-keys',
|
|
345
|
+
test: elevenlabsTest },
|
|
346
|
+
{ name: 'google_voice', kind: 'ai',
|
|
347
|
+
description: 'Google Cloud Service Account JSON for Speech-to-Text + Text-to-Speech',
|
|
348
|
+
obtainUrl: 'https://console.cloud.google.com/iam-admin/serviceaccounts',
|
|
349
|
+
test: googleVoiceTest },
|
|
350
|
+
/* cloud */
|
|
351
|
+
{ name: 'aws_access_key_id', kind: 'cloud',
|
|
352
|
+
description: 'AWS Access Key ID (AKIA*)',
|
|
353
|
+
obtainUrl: 'https://console.aws.amazon.com/iam/home#/security_credentials',
|
|
354
|
+
test: awsTest },
|
|
355
|
+
{ name: 'aws_secret_access_key', kind: 'cloud',
|
|
356
|
+
description: 'AWS Secret Access Key (paired with aws_access_key_id)',
|
|
357
|
+
test: awsTest },
|
|
358
|
+
{ name: 'gcp_service_account', kind: 'cloud',
|
|
359
|
+
description: 'GCP Service Account JSON',
|
|
360
|
+
obtainUrl: 'https://console.cloud.google.com/iam-admin/serviceaccounts',
|
|
361
|
+
test: googleVoiceTest /* same JSON syntactic check */ },
|
|
362
|
+
{ name: 'azure_service_principal', kind: 'cloud',
|
|
363
|
+
description: 'Azure SP credentials (JSON with clientId, clientSecret, tenantId)' },
|
|
364
|
+
/* app */
|
|
365
|
+
{ name: 'slack_bot_token', kind: 'app',
|
|
366
|
+
description: 'Slack bot token (xoxb-*)',
|
|
367
|
+
obtainUrl: 'https://api.slack.com/apps',
|
|
368
|
+
test: slackTest },
|
|
369
|
+
{ name: 'discord_bot_token', kind: 'app',
|
|
370
|
+
description: 'Discord bot token (from a Discord application)',
|
|
371
|
+
obtainUrl: 'https://discord.com/developers/applications',
|
|
372
|
+
test: discordTest },
|
|
373
|
+
{ name: 'twilio_account_sid', kind: 'app',
|
|
374
|
+
description: 'Twilio Account SID (AC*)',
|
|
375
|
+
obtainUrl: 'https://console.twilio.com/' },
|
|
376
|
+
{ name: 'twilio_auth_token', kind: 'app',
|
|
377
|
+
description: 'Twilio Auth Token (32 hex chars)',
|
|
378
|
+
obtainUrl: 'https://console.twilio.com/',
|
|
379
|
+
test: twilioTest },
|
|
380
|
+
{ name: 'stripe_secret_key', kind: 'app',
|
|
381
|
+
description: 'Stripe Secret Key (sk_live_* or sk_test_*)',
|
|
382
|
+
obtainUrl: 'https://dashboard.stripe.com/apikeys',
|
|
383
|
+
test: stripeTest },
|
|
384
|
+
{ name: 'sendgrid_api_key', kind: 'app',
|
|
385
|
+
description: 'SendGrid API Key (SG.*)',
|
|
386
|
+
obtainUrl: 'https://app.sendgrid.com/settings/api_keys',
|
|
387
|
+
test: sendgridTest },
|
|
388
|
+
{ name: 'mailgun_api_key', kind: 'app',
|
|
389
|
+
description: 'Mailgun API Key',
|
|
390
|
+
obtainUrl: 'https://app.mailgun.com/app/account/security/api_keys' },
|
|
391
|
+
{ name: 'linear_token', kind: 'app',
|
|
392
|
+
description: 'Linear API key',
|
|
393
|
+
obtainUrl: 'https://linear.app/settings/api',
|
|
394
|
+
test: linearTest },
|
|
395
|
+
{ name: 'notion_token', kind: 'app',
|
|
396
|
+
description: 'Notion integration token (secret_*)',
|
|
397
|
+
obtainUrl: 'https://www.notion.so/profile/integrations',
|
|
398
|
+
test: notionTest },
|
|
399
|
+
{ name: 'figma_token', kind: 'app',
|
|
400
|
+
description: 'Figma Personal Access Token',
|
|
401
|
+
obtainUrl: 'https://www.figma.com/settings',
|
|
402
|
+
test: figmaTest },
|
|
403
|
+
];
|
|
404
|
+
/** Look up a catalog entry by exact name. Returns undefined
|
|
405
|
+
* when the slot is custom (user-defined). */
|
|
406
|
+
export function lookupCatalog(name) {
|
|
407
|
+
return SLOT_CATALOG.find((e) => e.name === name);
|
|
408
|
+
}
|
|
409
|
+
/** Infer the kind for a slot name: catalog hit -> its kind,
|
|
410
|
+
* miss -> 'custom'. */
|
|
411
|
+
export function inferKind(name) {
|
|
412
|
+
const entry = lookupCatalog(name);
|
|
413
|
+
return entry ? entry.kind : 'custom';
|
|
414
|
+
}
|
|
415
|
+
/** Indexed view of the catalog by kind. */
|
|
416
|
+
export function catalogByKind() {
|
|
417
|
+
const out = {
|
|
418
|
+
repo: [], registry: [], ai: [], cloud: [], app: [], custom: [],
|
|
419
|
+
};
|
|
420
|
+
for (const e of SLOT_CATALOG)
|
|
421
|
+
out[e.kind].push(e);
|
|
422
|
+
return out;
|
|
423
|
+
}
|
|
424
|
+
//# sourceMappingURL=catalog.js.map
|