@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,69 @@
|
|
|
1
|
+
import { readVoiceConfig, writeVoiceConfig, matchConfiguredWakeWord } from '../voice/config.js';
|
|
2
|
+
import { DEFAULT_WAKE_ALIASES, mergeAliases } from '../voice/wake.js';
|
|
3
|
+
function splitCsv(s) {
|
|
4
|
+
return s.split(',').map((x) => x.trim()).filter((x) => x.length > 0);
|
|
5
|
+
}
|
|
6
|
+
export function registerVoiceCommand(program) {
|
|
7
|
+
const voice = program.command('voice').description('Voice + wake-word configuration.');
|
|
8
|
+
const config = voice
|
|
9
|
+
.command('config')
|
|
10
|
+
.description('Read or update the wake-word config (aliases, distance).')
|
|
11
|
+
.option('--show', 'Print the active config.')
|
|
12
|
+
.option('--aliases <list>', 'Comma-separated user extra aliases (replaces).')
|
|
13
|
+
.option('--add <list>', 'Comma-separated aliases to append.')
|
|
14
|
+
.option('--max-distance <n>', 'Levenshtein cap (0..2).')
|
|
15
|
+
.option('--reset', 'Reset extras + max-distance to defaults.')
|
|
16
|
+
.action(async (opts) => {
|
|
17
|
+
let cfg = await readVoiceConfig();
|
|
18
|
+
if (opts.reset) {
|
|
19
|
+
cfg = { version: 1, wake_aliases_extra: [], wake_max_distance: 2 };
|
|
20
|
+
await writeVoiceConfig(cfg);
|
|
21
|
+
console.log('voice config reset to defaults.');
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
let mutated = false;
|
|
25
|
+
if (opts.aliases !== undefined) {
|
|
26
|
+
cfg.wake_aliases_extra = splitCsv(opts.aliases);
|
|
27
|
+
mutated = true;
|
|
28
|
+
}
|
|
29
|
+
if (opts.add !== undefined) {
|
|
30
|
+
const extras = splitCsv(opts.add);
|
|
31
|
+
const set = new Set([...cfg.wake_aliases_extra, ...extras]);
|
|
32
|
+
cfg.wake_aliases_extra = [...set];
|
|
33
|
+
mutated = true;
|
|
34
|
+
}
|
|
35
|
+
if (opts.maxDistance !== undefined) {
|
|
36
|
+
const n = Number.parseInt(opts.maxDistance, 10);
|
|
37
|
+
if (!Number.isFinite(n) || n < 0 || n > 4) {
|
|
38
|
+
throw new Error('--max-distance must be an integer in [0,4]');
|
|
39
|
+
}
|
|
40
|
+
cfg.wake_max_distance = n;
|
|
41
|
+
mutated = true;
|
|
42
|
+
}
|
|
43
|
+
if (mutated)
|
|
44
|
+
await writeVoiceConfig(cfg);
|
|
45
|
+
if (opts.show || !mutated) {
|
|
46
|
+
const merged = mergeAliases(cfg.wake_aliases_extra);
|
|
47
|
+
console.log(JSON.stringify({
|
|
48
|
+
builtin_aliases: DEFAULT_WAKE_ALIASES,
|
|
49
|
+
user_extra: cfg.wake_aliases_extra,
|
|
50
|
+
merged,
|
|
51
|
+
max_distance: cfg.wake_max_distance,
|
|
52
|
+
}, null, 2));
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
console.log('voice config updated.');
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
voice
|
|
59
|
+
.command('test <phrase>')
|
|
60
|
+
.description('Test the wake-word matcher against a phrase.')
|
|
61
|
+
.action(async (phrase) => {
|
|
62
|
+
const r = await matchConfiguredWakeWord(phrase);
|
|
63
|
+
console.log(JSON.stringify(r, null, 2));
|
|
64
|
+
if (!r.hit)
|
|
65
|
+
process.exitCode = 1;
|
|
66
|
+
});
|
|
67
|
+
void config;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=voice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voice.js","sourceRoot":"","sources":["../../src/commands/voice.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cascade router (PLAN soft #4 + soft #10).
|
|
3
|
+
*
|
|
4
|
+
* Pablo 2026-05-26: "si laptop online procesamiento preferido
|
|
5
|
+
* en laptop, si laptop offline encola para cuando vuelve online.
|
|
6
|
+
* Automatico a GitHub Actions" -- this module decides WHICH
|
|
7
|
+
* target the next task runs on.
|
|
8
|
+
*
|
|
9
|
+
* Three targets, ranked in preference order:
|
|
10
|
+
* 1. Local laptop reachable on the LAN (mDNS + HTTP probe).
|
|
11
|
+
* 2. Cloudflare Tunnel exposing the laptop (HTTPS probe).
|
|
12
|
+
* 3. GitHub Actions fallback (dispatch a workflow run).
|
|
13
|
+
*
|
|
14
|
+
* Three compute classes drive how strict we are:
|
|
15
|
+
* class_1_local_only -- must hit laptop or CF tunnel; never Actions.
|
|
16
|
+
* Examples: open user docs, read local FS.
|
|
17
|
+
* class_2_local_preferred -- laptop -> CF -> Actions, in that order.
|
|
18
|
+
* Examples: generic agentic tasks.
|
|
19
|
+
* class_3_cloud_ok -- any reachable target wins. We still try
|
|
20
|
+
* local first when it's near, but Actions
|
|
21
|
+
* is fine if it's already warm.
|
|
22
|
+
*
|
|
23
|
+
* The router does NOT execute tasks itself -- it returns a
|
|
24
|
+
* RouteDecision the caller can act on (call the laptop HTTP
|
|
25
|
+
* brain, the CF URL, or dispatch a GHA workflow). This keeps
|
|
26
|
+
* the routing pure + testable.
|
|
27
|
+
*
|
|
28
|
+
* ASCII-only.
|
|
29
|
+
*/
|
|
30
|
+
export type ComputeClass = 'class_1_local_only' | 'class_2_local_preferred' | 'class_3_cloud_ok';
|
|
31
|
+
export type Target = 'laptop_lan' | 'cf_tunnel' | 'github_actions';
|
|
32
|
+
export interface RouteDecision {
|
|
33
|
+
/** Chosen target. null when no target is reachable AND the
|
|
34
|
+
* compute class refuses to fall through to Actions. */
|
|
35
|
+
target: Target | null;
|
|
36
|
+
/** Endpoint URL the caller should hit (or the GHA workflow
|
|
37
|
+
* ref for class actions). */
|
|
38
|
+
endpoint: string | null;
|
|
39
|
+
/** Human-readable explanation; surfaced to the user in chat
|
|
40
|
+
* or status output. */
|
|
41
|
+
reason: string;
|
|
42
|
+
/** Targets we tried and skipped (with the why) so the user
|
|
43
|
+
* can debug "why didn't my laptop pick this up?". */
|
|
44
|
+
attempts: Array<{
|
|
45
|
+
target: Target;
|
|
46
|
+
ok: boolean;
|
|
47
|
+
reason: string;
|
|
48
|
+
}>;
|
|
49
|
+
}
|
|
50
|
+
export interface ProbeResult {
|
|
51
|
+
ok: boolean;
|
|
52
|
+
latencyMs?: number;
|
|
53
|
+
reason?: string;
|
|
54
|
+
}
|
|
55
|
+
export interface CascadeProbes {
|
|
56
|
+
/** Check the laptop on the LAN -- usually an HTTP GET to
|
|
57
|
+
* http://<discovered-host>:<port>/healthz. */
|
|
58
|
+
probeLaptopLan?: () => Promise<ProbeResult>;
|
|
59
|
+
/** Check the laptop via CF tunnel -- HTTPS GET to
|
|
60
|
+
* https://<slug>.mcp.rpaforce.com/healthz. */
|
|
61
|
+
probeCfTunnel?: () => Promise<ProbeResult>;
|
|
62
|
+
/** Check GitHub Actions reachability -- usually a GET on the
|
|
63
|
+
* user's repo (200 means GHA can dispatch). */
|
|
64
|
+
probeGithubActions?: () => Promise<ProbeResult>;
|
|
65
|
+
}
|
|
66
|
+
export interface CascadeEndpoints {
|
|
67
|
+
laptop_lan?: string;
|
|
68
|
+
cf_tunnel?: string;
|
|
69
|
+
github_actions?: string;
|
|
70
|
+
}
|
|
71
|
+
export interface CascadeOptions {
|
|
72
|
+
/** Maximum wall-clock per probe before we treat it as a miss.
|
|
73
|
+
* Default 2000 ms. */
|
|
74
|
+
probeTimeoutMs?: number;
|
|
75
|
+
}
|
|
76
|
+
/** Decide which target to dispatch a task to.
|
|
77
|
+
*
|
|
78
|
+
* Order: laptop_lan -> cf_tunnel -> github_actions. The
|
|
79
|
+
* computeClass gates whether the last step is allowed.
|
|
80
|
+
*
|
|
81
|
+
* Note: probes run sequentially so a reachable nearer target
|
|
82
|
+
* short-circuits without paying for cloud probes. */
|
|
83
|
+
export declare function decideRoute(computeClass: ComputeClass, endpoints: CascadeEndpoints, probes: CascadeProbes, opts?: CascadeOptions): Promise<RouteDecision>;
|
|
84
|
+
/** HTTP-based probe factory. Returns a probe that does
|
|
85
|
+
* `fetch(url, { method:'GET' })` + reports the latency. */
|
|
86
|
+
export declare function makeHttpProbe(url: string, fetchImpl?: typeof fetch): () => Promise<ProbeResult>;
|
|
87
|
+
/** Convenience: given an HTTP endpoint, run a healthcheck
|
|
88
|
+
* against `<endpoint>/healthz`. Used by both LAN + CF probes. */
|
|
89
|
+
export declare function makeHealthzProbe(baseUrl: string, fetchImpl?: typeof fetch): () => Promise<ProbeResult>;
|
|
90
|
+
//# sourceMappingURL=cascade_router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cascade_router.d.ts","sourceRoot":"","sources":["../../src/core/cascade_router.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,MAAM,MAAM,YAAY,GAAG,oBAAoB,GAAG,yBAAyB,GAAG,kBAAkB,CAAC;AAEjG,MAAM,MAAM,MAAM,GAAG,YAAY,GAAG,WAAW,GAAG,gBAAgB,CAAC;AAEnE,MAAM,WAAW,aAAa;IAC5B;4DACwD;IACxD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB;kCAC8B;IAC9B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;4BACwB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf;0DACsD;IACtD,QAAQ,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClE;AAED,MAAM,WAAW,WAAW;IAAG,EAAE,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE;AAEjF,MAAM,WAAW,aAAa;IAC5B;mDAC+C;IAC/C,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;IAC5C;mDAC+C;IAC/C,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;IAC3C;oDACgD;IAChD,kBAAkB,CAAC,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B;2BACuB;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AA8BD;;;;;;sDAMsD;AACtD,wBAAsB,WAAW,CAC/B,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,gBAAgB,EAC3B,MAAM,EAAE,aAAa,EACrB,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,aAAa,CAAC,CAoDxB;AAED;4DAC4D;AAC5D,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,SAAS,GAAE,OAAO,KAA2D,GAC5E,MAAM,OAAO,CAAC,WAAW,CAAC,CAY5B;AAED;kEACkE;AAClE,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,OAAO,KAAK,GACvB,MAAM,OAAO,CAAC,WAAW,CAAC,CAG5B"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cascade router (PLAN soft #4 + soft #10).
|
|
3
|
+
*
|
|
4
|
+
* Pablo 2026-05-26: "si laptop online procesamiento preferido
|
|
5
|
+
* en laptop, si laptop offline encola para cuando vuelve online.
|
|
6
|
+
* Automatico a GitHub Actions" -- this module decides WHICH
|
|
7
|
+
* target the next task runs on.
|
|
8
|
+
*
|
|
9
|
+
* Three targets, ranked in preference order:
|
|
10
|
+
* 1. Local laptop reachable on the LAN (mDNS + HTTP probe).
|
|
11
|
+
* 2. Cloudflare Tunnel exposing the laptop (HTTPS probe).
|
|
12
|
+
* 3. GitHub Actions fallback (dispatch a workflow run).
|
|
13
|
+
*
|
|
14
|
+
* Three compute classes drive how strict we are:
|
|
15
|
+
* class_1_local_only -- must hit laptop or CF tunnel; never Actions.
|
|
16
|
+
* Examples: open user docs, read local FS.
|
|
17
|
+
* class_2_local_preferred -- laptop -> CF -> Actions, in that order.
|
|
18
|
+
* Examples: generic agentic tasks.
|
|
19
|
+
* class_3_cloud_ok -- any reachable target wins. We still try
|
|
20
|
+
* local first when it's near, but Actions
|
|
21
|
+
* is fine if it's already warm.
|
|
22
|
+
*
|
|
23
|
+
* The router does NOT execute tasks itself -- it returns a
|
|
24
|
+
* RouteDecision the caller can act on (call the laptop HTTP
|
|
25
|
+
* brain, the CF URL, or dispatch a GHA workflow). This keeps
|
|
26
|
+
* the routing pure + testable.
|
|
27
|
+
*
|
|
28
|
+
* ASCII-only.
|
|
29
|
+
*/
|
|
30
|
+
/** Race a promise against a timeout. */
|
|
31
|
+
async function withTimeout(p, ms, label) {
|
|
32
|
+
return new Promise((resolve, reject) => {
|
|
33
|
+
const t = setTimeout(() => reject(new Error('timeout: ' + label)), ms);
|
|
34
|
+
p.then((v) => { clearTimeout(t); resolve(v); }, (e) => { clearTimeout(t); reject(e); });
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
async function safeProbe(label, fn, endpoint, timeoutMs) {
|
|
38
|
+
if (!fn)
|
|
39
|
+
return { ok: false, reason: 'no probe registered for ' + label };
|
|
40
|
+
if (!endpoint)
|
|
41
|
+
return { ok: false, reason: 'no endpoint configured for ' + label };
|
|
42
|
+
try {
|
|
43
|
+
const r = await withTimeout(fn(), timeoutMs, label);
|
|
44
|
+
if (r.ok)
|
|
45
|
+
return { ok: true, reason: 'ok' + (r.latencyMs !== undefined ? ' (' + r.latencyMs + 'ms)' : '') };
|
|
46
|
+
return { ok: false, reason: r.reason ?? 'probe returned ok=false' };
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
return { ok: false, reason: err instanceof Error ? err.message : String(err) };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/** Decide which target to dispatch a task to.
|
|
53
|
+
*
|
|
54
|
+
* Order: laptop_lan -> cf_tunnel -> github_actions. The
|
|
55
|
+
* computeClass gates whether the last step is allowed.
|
|
56
|
+
*
|
|
57
|
+
* Note: probes run sequentially so a reachable nearer target
|
|
58
|
+
* short-circuits without paying for cloud probes. */
|
|
59
|
+
export async function decideRoute(computeClass, endpoints, probes, opts = {}) {
|
|
60
|
+
const timeoutMs = opts.probeTimeoutMs ?? 2000;
|
|
61
|
+
const attempts = [];
|
|
62
|
+
/* Step 1: laptop_lan. */
|
|
63
|
+
const lan = await safeProbe('laptop_lan', probes.probeLaptopLan, endpoints.laptop_lan, timeoutMs);
|
|
64
|
+
attempts.push({ target: 'laptop_lan', ok: lan.ok, reason: lan.reason });
|
|
65
|
+
if (lan.ok) {
|
|
66
|
+
return {
|
|
67
|
+
target: 'laptop_lan',
|
|
68
|
+
endpoint: endpoints.laptop_lan ?? null,
|
|
69
|
+
reason: 'laptop reachable on the LAN',
|
|
70
|
+
attempts,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/* Step 2: cf_tunnel. */
|
|
74
|
+
const cf = await safeProbe('cf_tunnel', probes.probeCfTunnel, endpoints.cf_tunnel, timeoutMs);
|
|
75
|
+
attempts.push({ target: 'cf_tunnel', ok: cf.ok, reason: cf.reason });
|
|
76
|
+
if (cf.ok) {
|
|
77
|
+
return {
|
|
78
|
+
target: 'cf_tunnel',
|
|
79
|
+
endpoint: endpoints.cf_tunnel ?? null,
|
|
80
|
+
reason: 'laptop reachable via Cloudflare Tunnel',
|
|
81
|
+
attempts,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/* Step 3: github_actions -- gated by compute class. */
|
|
85
|
+
if (computeClass === 'class_1_local_only') {
|
|
86
|
+
return {
|
|
87
|
+
target: null, endpoint: null,
|
|
88
|
+
reason: 'class_1_local_only forbids Actions fallback and both local targets are unreachable',
|
|
89
|
+
attempts,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
const gha = await safeProbe('github_actions', probes.probeGithubActions, endpoints.github_actions, timeoutMs);
|
|
93
|
+
attempts.push({ target: 'github_actions', ok: gha.ok, reason: gha.reason });
|
|
94
|
+
if (gha.ok) {
|
|
95
|
+
return {
|
|
96
|
+
target: 'github_actions',
|
|
97
|
+
endpoint: endpoints.github_actions ?? null,
|
|
98
|
+
reason: 'falling back to GitHub Actions dispatcher',
|
|
99
|
+
attempts,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
target: null, endpoint: null,
|
|
104
|
+
reason: 'no target is reachable',
|
|
105
|
+
attempts,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/** HTTP-based probe factory. Returns a probe that does
|
|
109
|
+
* `fetch(url, { method:'GET' })` + reports the latency. */
|
|
110
|
+
export function makeHttpProbe(url, fetchImpl = ((u, init) => globalThis.fetch(u, init))) {
|
|
111
|
+
return async () => {
|
|
112
|
+
const t0 = Date.now();
|
|
113
|
+
try {
|
|
114
|
+
const r = await fetchImpl(url, { method: 'GET' });
|
|
115
|
+
const latencyMs = Date.now() - t0;
|
|
116
|
+
if (r.ok)
|
|
117
|
+
return { ok: true, latencyMs };
|
|
118
|
+
return { ok: false, reason: 'HTTP ' + r.status, latencyMs };
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
return { ok: false, reason: err instanceof Error ? err.message : String(err) };
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/** Convenience: given an HTTP endpoint, run a healthcheck
|
|
126
|
+
* against `<endpoint>/healthz`. Used by both LAN + CF probes. */
|
|
127
|
+
export function makeHealthzProbe(baseUrl, fetchImpl) {
|
|
128
|
+
const url = baseUrl.replace(/\/+$/, '') + '/healthz';
|
|
129
|
+
return makeHttpProbe(url, fetchImpl);
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=cascade_router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cascade_router.js","sourceRoot":"","sources":["../../src/core/cascade_router.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloudflare Tunnel orchestration (PLAN #2 connectivity).
|
|
3
|
+
*
|
|
4
|
+
* Yujin owns the `*.forge.yujin.app` subdomain via a CF
|
|
5
|
+
* account; each paid user gets a stable `<slug>.forge.yujin.app`
|
|
6
|
+
* URL that points to their laptop tunnel.
|
|
7
|
+
*
|
|
8
|
+
* This module:
|
|
9
|
+
* - Resolves the cloudflared binary (download if missing).
|
|
10
|
+
* - Starts/stops a tunnel session.
|
|
11
|
+
* - Reads the tunnel URL (named + token from Yujin's CF
|
|
12
|
+
* account, or `try.cloudflare.com` fallback for free
|
|
13
|
+
* trial users).
|
|
14
|
+
* - Persists current tunnel URL in registry per project.
|
|
15
|
+
*
|
|
16
|
+
* Note: real wiring to Yujin's CF API requires a server-
|
|
17
|
+
* side helper that mints tokens per user (HITO 4 era). This
|
|
18
|
+
* module ships the local side: it can run a try.cloudflare
|
|
19
|
+
* ephemeral tunnel out-of-the-box, and accepts a token when
|
|
20
|
+
* provided (from vault slot `cloudflare_tunnel_token`).
|
|
21
|
+
*
|
|
22
|
+
* ASCII-only.
|
|
23
|
+
*/
|
|
24
|
+
import { type ChildProcess } from 'node:child_process';
|
|
25
|
+
export interface TunnelHandle {
|
|
26
|
+
/** Public URL the laptop is reachable at. */
|
|
27
|
+
publicUrl: string;
|
|
28
|
+
/** Underlying cloudflared process. */
|
|
29
|
+
process: ChildProcess;
|
|
30
|
+
/** Stop the tunnel + clean up. */
|
|
31
|
+
stop: () => Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
export interface StartTunnelOptions {
|
|
34
|
+
/** Local port the panel runs on. */
|
|
35
|
+
port: number;
|
|
36
|
+
/** Force the ephemeral try.cloudflare flow (skip token). */
|
|
37
|
+
ephemeral?: boolean;
|
|
38
|
+
/** Override the cloudflared binary location. */
|
|
39
|
+
bin?: string;
|
|
40
|
+
}
|
|
41
|
+
/** Try to resolve cloudflared in PATH. Returns null if not
|
|
42
|
+
* installed. The doctor command surfaces this so the user
|
|
43
|
+
* knows to install before relying on tunnel features. */
|
|
44
|
+
export declare function resolveCloudflared(): Promise<string | null>;
|
|
45
|
+
/** Read the tunnel token from vault, if configured. The
|
|
46
|
+
* expected slot name is `cloudflare_tunnel_token`. Returns
|
|
47
|
+
* null when missing -- caller falls back to ephemeral. */
|
|
48
|
+
export declare function readTunnelToken(): Promise<string | null>;
|
|
49
|
+
/** Start a cloudflared tunnel for `port`. Returns a handle
|
|
50
|
+
* with the public URL once cloudflared announces it. */
|
|
51
|
+
export declare function startTunnel(opts: StartTunnelOptions): Promise<TunnelHandle>;
|
|
52
|
+
//# sourceMappingURL=cf_tunnel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cf_tunnel.d.ts","sourceRoot":"","sources":["../../src/core/cf_tunnel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAO9D,MAAM,WAAW,YAAY;IAC3B,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,OAAO,EAAE,YAAY,CAAC;IACtB,kCAAkC;IAClC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gDAAgD;IAChD,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAQD;;0DAE0D;AAC1D,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoBjE;AAED;;2DAE2D;AAC3D,wBAAsB,eAAe,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQ9D;AAED;yDACyD;AACzD,wBAAsB,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CA4DjF"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloudflare Tunnel orchestration (PLAN #2 connectivity).
|
|
3
|
+
*
|
|
4
|
+
* Yujin owns the `*.forge.yujin.app` subdomain via a CF
|
|
5
|
+
* account; each paid user gets a stable `<slug>.forge.yujin.app`
|
|
6
|
+
* URL that points to their laptop tunnel.
|
|
7
|
+
*
|
|
8
|
+
* This module:
|
|
9
|
+
* - Resolves the cloudflared binary (download if missing).
|
|
10
|
+
* - Starts/stops a tunnel session.
|
|
11
|
+
* - Reads the tunnel URL (named + token from Yujin's CF
|
|
12
|
+
* account, or `try.cloudflare.com` fallback for free
|
|
13
|
+
* trial users).
|
|
14
|
+
* - Persists current tunnel URL in registry per project.
|
|
15
|
+
*
|
|
16
|
+
* Note: real wiring to Yujin's CF API requires a server-
|
|
17
|
+
* side helper that mints tokens per user (HITO 4 era). This
|
|
18
|
+
* module ships the local side: it can run a try.cloudflare
|
|
19
|
+
* ephemeral tunnel out-of-the-box, and accepts a token when
|
|
20
|
+
* provided (from vault slot `cloudflare_tunnel_token`).
|
|
21
|
+
*
|
|
22
|
+
* ASCII-only.
|
|
23
|
+
*/
|
|
24
|
+
import { spawn } from 'node:child_process';
|
|
25
|
+
import { promises as fs } from 'node:fs';
|
|
26
|
+
import path from 'node:path';
|
|
27
|
+
import os from 'node:os';
|
|
28
|
+
import { Vault } from '../vault/store.js';
|
|
29
|
+
import { configDir } from '../license/index.js';
|
|
30
|
+
const CLOUDFLARED_BIN_NAMES = {
|
|
31
|
+
win32: 'cloudflared.exe',
|
|
32
|
+
darwin: 'cloudflared',
|
|
33
|
+
linux: 'cloudflared',
|
|
34
|
+
};
|
|
35
|
+
/** Try to resolve cloudflared in PATH. Returns null if not
|
|
36
|
+
* installed. The doctor command surfaces this so the user
|
|
37
|
+
* knows to install before relying on tunnel features. */
|
|
38
|
+
export async function resolveCloudflared() {
|
|
39
|
+
const name = CLOUDFLARED_BIN_NAMES[process.platform]
|
|
40
|
+
?? 'cloudflared';
|
|
41
|
+
/* Check PATH. */
|
|
42
|
+
const envPath = process.env.PATH ?? '';
|
|
43
|
+
const separator = process.platform === 'win32' ? ';' : ':';
|
|
44
|
+
for (const dir of envPath.split(separator)) {
|
|
45
|
+
const candidate = path.join(dir, name);
|
|
46
|
+
try {
|
|
47
|
+
await fs.access(candidate);
|
|
48
|
+
return candidate;
|
|
49
|
+
}
|
|
50
|
+
catch { /* keep looking */ }
|
|
51
|
+
}
|
|
52
|
+
/* Check ~/.yujin-forge/bin where we drop the download. */
|
|
53
|
+
const local = path.join(os.homedir(), '.yujin-forge', 'bin', name);
|
|
54
|
+
try {
|
|
55
|
+
await fs.access(local);
|
|
56
|
+
return local;
|
|
57
|
+
}
|
|
58
|
+
catch { /* not present */ }
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
/** Read the tunnel token from vault, if configured. The
|
|
62
|
+
* expected slot name is `cloudflare_tunnel_token`. Returns
|
|
63
|
+
* null when missing -- caller falls back to ephemeral. */
|
|
64
|
+
export async function readTunnelToken() {
|
|
65
|
+
try {
|
|
66
|
+
const vault = await Vault.open({ configDir: configDir() });
|
|
67
|
+
if (vault.has('cloudflare_tunnel_token')) {
|
|
68
|
+
return vault.get('cloudflare_tunnel_token');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch { /* vault not initialised */ }
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
/** Start a cloudflared tunnel for `port`. Returns a handle
|
|
75
|
+
* with the public URL once cloudflared announces it. */
|
|
76
|
+
export async function startTunnel(opts) {
|
|
77
|
+
const bin = opts.bin ?? await resolveCloudflared();
|
|
78
|
+
if (!bin) {
|
|
79
|
+
throw new Error('cloudflared not found. Install from '
|
|
80
|
+
+ 'https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/ '
|
|
81
|
+
+ 'or set `bin` explicitly.');
|
|
82
|
+
}
|
|
83
|
+
const token = !opts.ephemeral ? await readTunnelToken() : null;
|
|
84
|
+
let args;
|
|
85
|
+
if (token) {
|
|
86
|
+
/* Named tunnel via Yujin's CF account. */
|
|
87
|
+
args = ['tunnel', 'run', '--token', token, '--url', 'http://127.0.0.1:' + opts.port];
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
/* Ephemeral try.cloudflare flow -- gets a random
|
|
91
|
+
trycloudflare.com URL. */
|
|
92
|
+
args = ['tunnel', '--url', 'http://127.0.0.1:' + opts.port,
|
|
93
|
+
'--no-autoupdate'];
|
|
94
|
+
}
|
|
95
|
+
const proc = spawn(bin, args, {
|
|
96
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
97
|
+
env: { ...process.env },
|
|
98
|
+
});
|
|
99
|
+
/* Capture stdout/stderr until we see the public URL line.
|
|
100
|
+
try.cloudflare prints "https://<slug>.trycloudflare.com"
|
|
101
|
+
in stderr; named tunnels print the configured URL. */
|
|
102
|
+
const publicUrl = await new Promise((resolve, reject) => {
|
|
103
|
+
let buf = '';
|
|
104
|
+
const onData = (b) => {
|
|
105
|
+
buf += b.toString('utf-8');
|
|
106
|
+
const m = buf.match(/https:\/\/[a-z0-9-]+\.(?:trycloudflare\.com|forge\.yujin\.app|cfargotunnel\.com)/);
|
|
107
|
+
if (m) {
|
|
108
|
+
proc.stdout?.off('data', onData);
|
|
109
|
+
proc.stderr?.off('data', onData);
|
|
110
|
+
resolve(m[0]);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
proc.stdout?.on('data', onData);
|
|
114
|
+
proc.stderr?.on('data', onData);
|
|
115
|
+
proc.on('error', reject);
|
|
116
|
+
/* Timeout: 30s for the tunnel to announce its URL. */
|
|
117
|
+
setTimeout(() => reject(new Error('cloudflared did not announce a URL within 30s. Output: ' + buf.slice(-500))), 30000);
|
|
118
|
+
});
|
|
119
|
+
const stop = () => new Promise((resolve) => {
|
|
120
|
+
if (proc.exitCode !== null) {
|
|
121
|
+
resolve();
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
proc.once('exit', () => resolve());
|
|
125
|
+
proc.kill('SIGTERM');
|
|
126
|
+
setTimeout(() => {
|
|
127
|
+
if (proc.exitCode === null)
|
|
128
|
+
proc.kill('SIGKILL');
|
|
129
|
+
resolve();
|
|
130
|
+
}, 5000);
|
|
131
|
+
});
|
|
132
|
+
return { publicUrl, process: proc, stop };
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=cf_tunnel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cf_tunnel.js","sourceRoot":"","sources":["../../src/core/cf_tunnel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Actions fallback dispatcher (PLAN connectivity).
|
|
3
|
+
*
|
|
4
|
+
* Per Pablo's decision (#4): when laptop is offline, mobile
|
|
5
|
+
* (or web) clients dispatch `yf <command>` to the user's
|
|
6
|
+
* GitHub repo via a yf-remote.yml workflow. Outputs land in
|
|
7
|
+
* a branch `_yujin/runs/<run_id>.json` that mobile polls.
|
|
8
|
+
*
|
|
9
|
+
* The workflow file is auto-committed when `yf projects add`
|
|
10
|
+
* registers a repo for the first time (per Pablo's "OK
|
|
11
|
+
* autonomia" on confirmation #2).
|
|
12
|
+
*
|
|
13
|
+
* This module gives:
|
|
14
|
+
* - `yfRemoteWorkflowYaml()` -> the canonical workflow.
|
|
15
|
+
* - `dispatchWorkflow(repo, command, args, token)` -> POST
|
|
16
|
+
* to the GH API.
|
|
17
|
+
* - `pollRunStatus(repo, runId, token)` -> SSE-like poller.
|
|
18
|
+
*
|
|
19
|
+
* ASCII-only.
|
|
20
|
+
*/
|
|
21
|
+
export interface DispatchResult {
|
|
22
|
+
ok: boolean;
|
|
23
|
+
run_id?: string;
|
|
24
|
+
workflow_run_id?: number;
|
|
25
|
+
error?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface RunStatus {
|
|
28
|
+
status: 'queued' | 'in_progress' | 'success' | 'failure' | 'cancelled' | 'timed_out';
|
|
29
|
+
url: string;
|
|
30
|
+
duration_seconds?: number;
|
|
31
|
+
}
|
|
32
|
+
/** The canonical workflow yaml that Forge commits to user
|
|
33
|
+
* repos on first registration. Idempotent on re-write. */
|
|
34
|
+
export declare function yfRemoteWorkflowYaml(): string;
|
|
35
|
+
/** Generate a short, mostly-readable run_id. */
|
|
36
|
+
export declare function generateRunId(): string;
|
|
37
|
+
/** Dispatch yf-remote on a GitHub repo. `repo` is the
|
|
38
|
+
* "owner/name" string. Returns run_id + the workflow_run_id
|
|
39
|
+
* when GH assigns one. */
|
|
40
|
+
export declare function dispatchWorkflow(repo: string, command: string, args: string, token: string): Promise<DispatchResult>;
|
|
41
|
+
/** Poll the _yujin/runs branch for the result JSON. Returns
|
|
42
|
+
* null while pending, or the parsed JSON when ready. */
|
|
43
|
+
export declare function fetchRunResult(repo: string, runId: string, token: string): Promise<RunStatus & {
|
|
44
|
+
stdout?: string;
|
|
45
|
+
stderr?: string;
|
|
46
|
+
exit?: number;
|
|
47
|
+
} | null>;
|
|
48
|
+
//# sourceMappingURL=gha_dispatcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gha_dispatcher.d.ts","sourceRoot":"","sources":["../../src/core/gha_dispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,QAAQ,GAAG,aAAa,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC;IACrF,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;2DAC2D;AAC3D,wBAAgB,oBAAoB,IAAI,MAAM,CAqF7C;AAED,gDAAgD;AAChD,wBAAgB,aAAa,IAAI,MAAM,CAItC;AAED;;2BAE2B;AAC3B,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,cAAc,CAAC,CA8BzB;AAED;yDACyD;AACzD,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,SAAS,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CA2CjF"}
|