@engenty/wizards-runtime 0.0.0-stage → 0.7.6
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 +110 -0
- package/README.md +214 -2
- package/apps/runtime/dist/agents/architect.js +444 -0
- package/apps/runtime/dist/agents/studio-assistant.js +883 -0
- package/apps/runtime/dist/agents/subscription.js +207 -0
- package/apps/runtime/dist/agents/thought.js +21 -0
- package/apps/runtime/dist/agents/website.js +480 -0
- package/apps/runtime/dist/app.js +359 -0
- package/apps/runtime/dist/apple/wizards-apple +0 -0
- package/apps/runtime/dist/assistant/browser.js +26 -0
- package/apps/runtime/dist/assistant/docs.js +158 -0
- package/apps/runtime/dist/assistant/knows.js +353 -0
- package/apps/runtime/dist/assistant/primer.js +26 -0
- package/apps/runtime/dist/assistant/runs.js +24 -0
- package/apps/runtime/dist/auth/account.js +175 -0
- package/apps/runtime/dist/auth/device.js +112 -0
- package/apps/runtime/dist/auth/index.js +358 -0
- package/apps/runtime/dist/auth/keys.js +55 -0
- package/apps/runtime/dist/auth/local-ticket.js +26 -0
- package/apps/runtime/dist/authoring/example.js +74 -0
- package/apps/runtime/dist/authoring/guide.js +433 -0
- package/apps/runtime/dist/authoring/ops.js +117 -0
- package/apps/runtime/dist/browser/fast/action-space.js +160 -0
- package/apps/runtime/dist/browser/fast/classifier.js +91 -0
- package/apps/runtime/dist/browser/fast/decide.js +171 -0
- package/apps/runtime/dist/browser/fast/driver.js +141 -0
- package/apps/runtime/dist/browser/fast/instructions.js +33 -0
- package/apps/runtime/dist/browser/fast/run.js +249 -0
- package/apps/runtime/dist/browser/fast/span-picker.js +153 -0
- package/apps/runtime/dist/browser/fast/text-helper.js +178 -0
- package/apps/runtime/dist/browser/snapshot.js +335 -0
- package/apps/runtime/dist/cli/account.js +385 -0
- package/apps/runtime/dist/cli/autostart.js +182 -0
- package/apps/runtime/dist/cli/autoupdate.js +221 -0
- package/apps/runtime/dist/cli/clients.js +44 -0
- package/apps/runtime/dist/cli/connect.js +540 -0
- package/apps/runtime/dist/cli/environment.js +95 -0
- package/apps/runtime/dist/cli/exec.js +45 -0
- package/apps/runtime/dist/cli/features.js +50 -0
- package/apps/runtime/dist/cli/home.js +88 -0
- package/apps/runtime/dist/cli/install-env.js +33 -0
- package/apps/runtime/dist/cli/machine.js +107 -0
- package/apps/runtime/dist/cli/main.js +231 -0
- package/apps/runtime/dist/cli/mcp.js +136 -0
- package/apps/runtime/dist/cli/menu.js +202 -0
- package/apps/runtime/dist/cli/processes.js +72 -0
- package/apps/runtime/dist/cli/report.js +66 -0
- package/apps/runtime/dist/cli/sandbox.js +77 -0
- package/apps/runtime/dist/cli/setup.js +335 -0
- package/apps/runtime/dist/cli/start.js +276 -0
- package/apps/runtime/dist/cli/status.js +212 -0
- package/apps/runtime/dist/cli/ui.js +59 -0
- package/apps/runtime/dist/cli/uninstall-main.js +20 -0
- package/apps/runtime/dist/cli/uninstall.js +231 -0
- package/apps/runtime/dist/cli/update.js +86 -0
- package/apps/runtime/dist/cli/validate.js +75 -0
- package/apps/runtime/dist/cli/versions.js +123 -0
- package/apps/runtime/dist/connectors/builtin.js +86 -0
- package/apps/runtime/dist/connectors/external.js +409 -0
- package/apps/runtime/dist/connectors/gmail.js +107 -0
- package/apps/runtime/dist/connectors/imap.js +261 -0
- package/apps/runtime/dist/connectors/index.js +325 -0
- package/apps/runtime/dist/connectors/mail.js +72 -0
- package/apps/runtime/dist/connectors/outlook.js +90 -0
- package/apps/runtime/dist/connectors/plugin-connections.js +343 -0
- package/apps/runtime/dist/connectors/via-account.js +65 -0
- package/apps/runtime/dist/credits/credits.js +100 -0
- package/apps/runtime/dist/credits/estimate.js +152 -0
- package/apps/runtime/dist/db/adopt.js +149 -0
- package/apps/runtime/dist/db/client.js +173 -0
- package/apps/runtime/dist/db/control-schema.js +133 -0
- package/apps/runtime/dist/db/migrations/control/0000_last_absorbing_man.sql +47 -0
- package/apps/runtime/dist/db/migrations/control/0001_gorgeous_nicolaos.sql +41 -0
- package/apps/runtime/dist/db/migrations/control/0002_secret_penance.sql +1 -0
- package/apps/runtime/dist/db/migrations/control/0003_nasty_mordo.sql +3 -0
- package/apps/runtime/dist/db/migrations/control/0004_breezy_eddie_brock.sql +6 -0
- package/apps/runtime/dist/db/migrations/control/0005_chilly_oracle.sql +1 -0
- package/apps/runtime/dist/db/migrations/control/0006_sleepy_mojo.sql +1 -0
- package/apps/runtime/dist/db/migrations/control/0007_common_the_hand.sql +15 -0
- package/apps/runtime/dist/db/migrations/control/0008_runner.sql +8 -0
- package/apps/runtime/dist/db/migrations/control/0009_plugin_claim.sql +9 -0
- package/apps/runtime/dist/db/migrations/control/0010_tan_snowbird.sql +6 -0
- package/apps/runtime/dist/db/migrations/control/meta/0000_snapshot.json +311 -0
- package/apps/runtime/dist/db/migrations/control/meta/0001_snapshot.json +599 -0
- package/apps/runtime/dist/db/migrations/control/meta/0002_snapshot.json +607 -0
- package/apps/runtime/dist/db/migrations/control/meta/0003_snapshot.json +311 -0
- package/apps/runtime/dist/db/migrations/control/meta/0004_snapshot.json +350 -0
- package/apps/runtime/dist/db/migrations/control/meta/0005_snapshot.json +358 -0
- package/apps/runtime/dist/db/migrations/control/meta/0006_snapshot.json +365 -0
- package/apps/runtime/dist/db/migrations/control/meta/0007_snapshot.json +460 -0
- package/apps/runtime/dist/db/migrations/control/meta/0008_snapshot.json +505 -0
- package/apps/runtime/dist/db/migrations/control/meta/0009_snapshot.json +561 -0
- package/apps/runtime/dist/db/migrations/control/meta/0010_snapshot.json +600 -0
- package/apps/runtime/dist/db/migrations/control/meta/_journal.json +83 -0
- package/apps/runtime/dist/db/migrations/tenant/0000_eminent_freak.sql +188 -0
- package/apps/runtime/dist/db/migrations/tenant/0001_salty_master_chief.sql +1 -0
- package/apps/runtime/dist/db/migrations/tenant/0002_cloudy_firebird.sql +1 -0
- package/apps/runtime/dist/db/migrations/tenant/0003_brown_warbound.sql +52 -0
- package/apps/runtime/dist/db/migrations/tenant/0004_romantic_nocturne.sql +6 -0
- package/apps/runtime/dist/db/migrations/tenant/0005_reflective_forgotten_one.sql +2 -0
- package/apps/runtime/dist/db/migrations/tenant/0006_hard_war_machine.sql +30 -0
- package/apps/runtime/dist/db/migrations/tenant/0007_space_data.sql +43 -0
- package/apps/runtime/dist/db/migrations/tenant/0008_run_event_note.sql +1 -0
- package/apps/runtime/dist/db/migrations/tenant/0009_knowledge.sql +104 -0
- package/apps/runtime/dist/db/migrations/tenant/0010_plugin_connection.sql +15 -0
- package/apps/runtime/dist/db/migrations/tenant/0011_runners.sql +2 -0
- package/apps/runtime/dist/db/migrations/tenant/0012_assistant_chat.sql +40 -0
- package/apps/runtime/dist/db/migrations/tenant/0013_run_origin.sql +1 -0
- package/apps/runtime/dist/db/migrations/tenant/0014_run_answer.sql +2 -0
- package/apps/runtime/dist/db/migrations/tenant/0015_device_calls.sql +13 -0
- package/apps/runtime/dist/db/migrations/tenant/0016_even_trish_tilby.sql +12 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0000_snapshot.json +1323 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0001_snapshot.json +1330 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0002_snapshot.json +1337 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0003_snapshot.json +1605 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0004_snapshot.json +1645 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0005_snapshot.json +1659 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0006_snapshot.json +1696 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0007_snapshot.json +2012 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0008_snapshot.json +2019 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0009_snapshot.json +2837 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0010_snapshot.json +2942 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0011_snapshot.json +2956 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0012_snapshot.json +3132 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0013_snapshot.json +3139 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0014_snapshot.json +3154 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0015_snapshot.json +3243 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0016_snapshot.json +3326 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/_journal.json +125 -0
- package/apps/runtime/dist/db/schema.js +602 -0
- package/apps/runtime/dist/debug.js +197 -0
- package/apps/runtime/dist/docs/dev/index.md +41 -0
- package/apps/runtime/dist/docs/dev/meta.json +7 -0
- package/apps/runtime/dist/docs/dev/plugins/connections.md +74 -0
- package/apps/runtime/dist/docs/dev/plugins/events.md +89 -0
- package/apps/runtime/dist/docs/dev/plugins/examples.md +101 -0
- package/apps/runtime/dist/docs/dev/plugins/index.md +78 -0
- package/apps/runtime/dist/docs/dev/plugins/layout.md +90 -0
- package/apps/runtime/dist/docs/dev/plugins/meta.json +28 -0
- package/apps/runtime/dist/docs/dev/plugins/quick-start.md +94 -0
- package/apps/runtime/dist/docs/dev/plugins/reference.md +348 -0
- package/apps/runtime/dist/docs/dev/plugins/reloading.md +76 -0
- package/apps/runtime/dist/docs/dev/plugins/routes.md +185 -0
- package/apps/runtime/dist/docs/dev/plugins/runners.md +230 -0
- package/apps/runtime/dist/docs/dev/plugins/server.md +281 -0
- package/apps/runtime/dist/docs/dev/plugins/shipping.md +79 -0
- package/apps/runtime/dist/docs/dev/plugins/space.md +297 -0
- package/apps/runtime/dist/docs/dev/plugins/starters.md +70 -0
- package/apps/runtime/dist/docs/dev/plugins/studio.md +363 -0
- package/apps/runtime/dist/docs/dev/plugins/styling.md +129 -0
- package/apps/runtime/dist/docs/dev/plugins/tables.md +104 -0
- package/apps/runtime/dist/docs/dev/plugins/tools.md +139 -0
- package/apps/runtime/dist/docs/dev/wizard-format.md +125 -0
- package/apps/runtime/dist/docs/meta.json +3 -0
- package/apps/runtime/dist/docs/user/ai-apps.md +112 -0
- package/apps/runtime/dist/docs/user/assistant.md +77 -0
- package/apps/runtime/dist/docs/user/build-a-wizard.md +116 -0
- package/apps/runtime/dist/docs/user/command-line.md +86 -0
- package/apps/runtime/dist/docs/user/connectors.md +90 -0
- package/apps/runtime/dist/docs/user/create-account.md +52 -0
- package/apps/runtime/dist/docs/user/data.md +66 -0
- package/apps/runtime/dist/docs/user/first-start.md +60 -0
- package/apps/runtime/dist/docs/user/index.md +49 -0
- package/apps/runtime/dist/docs/user/install.md +123 -0
- package/apps/runtime/dist/docs/user/local-only.md +42 -0
- package/apps/runtime/dist/docs/user/meta.json +32 -0
- package/apps/runtime/dist/docs/user/models.md +156 -0
- package/apps/runtime/dist/docs/user/plugins.md +71 -0
- package/apps/runtime/dist/docs/user/run.md +98 -0
- package/apps/runtime/dist/docs/user/server.md +52 -0
- package/apps/runtime/dist/docs/user/space.md +126 -0
- package/apps/runtime/dist/docs/user/steps.md +220 -0
- package/apps/runtime/dist/docs/user/test-and-share.md +224 -0
- package/apps/runtime/dist/docs/user/troubleshooting.md +67 -0
- package/apps/runtime/dist/docs/user/wordpress.md +121 -0
- package/apps/runtime/dist/documents/parse.js +246 -0
- package/apps/runtime/dist/engenty/connections-external/build-connector.js +193 -0
- package/apps/runtime/dist/engenty/connections-external/errors.js +11 -0
- package/apps/runtime/dist/engenty/connections-external/import-service.js +270 -0
- package/apps/runtime/dist/engenty/connections-external/importer/classify.js +34 -0
- package/apps/runtime/dist/engenty/connections-external/importer/map-auth.js +185 -0
- package/apps/runtime/dist/engenty/connections-external/importer/normalize-mcp.js +63 -0
- package/apps/runtime/dist/engenty/connections-external/importer/normalize-openapi.js +130 -0
- package/apps/runtime/dist/engenty/connections-external/invoke/http-invoker.js +143 -0
- package/apps/runtime/dist/engenty/connections-external/invoke/mcp-client.js +143 -0
- package/apps/runtime/dist/engenty/connections-external/net/guarded-fetch.js +119 -0
- package/apps/runtime/dist/engenty/connections-external/oauth-dcr.js +88 -0
- package/apps/runtime/dist/engenty/connections-external/registry-client.js +336 -0
- package/apps/runtime/dist/engenty/connections-external/registry-source.js +82 -0
- package/apps/runtime/dist/engenty/connections-external/types.js +7 -0
- package/apps/runtime/dist/engenty/connections-github/connector.js +209 -0
- package/apps/runtime/dist/engenty/connections-google/connectors/calendar.js +381 -0
- package/apps/runtime/dist/engenty/connections-google/connectors/contacts.js +94 -0
- package/apps/runtime/dist/engenty/connections-google/connectors/drive.js +290 -0
- package/apps/runtime/dist/engenty/connections-google/connectors/gmail.js +567 -0
- package/apps/runtime/dist/engenty/connections-google/definitions.js +11 -0
- package/apps/runtime/dist/engenty/connections-google/shared.js +73 -0
- package/apps/runtime/dist/engenty/connections-hubspot/connector.js +140 -0
- package/apps/runtime/dist/engenty/connections-microsoft/action.js +17 -0
- package/apps/runtime/dist/engenty/connections-microsoft/graph.js +114 -0
- package/apps/runtime/dist/engenty/connections-microsoft/onedrive.js +286 -0
- package/apps/runtime/dist/engenty/connections-microsoft/outlook.js +492 -0
- package/apps/runtime/dist/engenty/connections-s3/s3.js +328 -0
- package/apps/runtime/dist/engenty/connections-sdk/files-capability.js +86 -0
- package/apps/runtime/dist/engenty/connections-sdk/oauth2.js +150 -0
- package/apps/runtime/dist/engenty/connections-sdk/registry.js +89 -0
- package/apps/runtime/dist/engenty/connections-sdk/storage-capability.js +84 -0
- package/apps/runtime/dist/engenty/connections-sdk/types.js +30 -0
- package/apps/runtime/dist/engenty/connections-slack/connector.js +360 -0
- package/apps/runtime/dist/engenty/csv-import/csv-matrix.js +178 -0
- package/apps/runtime/dist/engenty/csv-import/import-sources.js +87 -0
- package/apps/runtime/dist/engenty/csv-import/parse-csv.js +129 -0
- package/apps/runtime/dist/engenty/csv-import/serialize-csv.js +20 -0
- package/apps/runtime/dist/engenty/csv-import/types.js +1 -0
- package/apps/runtime/dist/engenty/csv-import/xlsx-workbook.js +159 -0
- package/apps/runtime/dist/engenty/doc-converter/interface.js +9 -0
- package/apps/runtime/dist/engenty/doc-converter/page-break.js +92 -0
- package/apps/runtime/dist/engenty/doc-converter/providers/local/index.js +72 -0
- package/apps/runtime/dist/engenty/document-scanner/schemas/classifier.js +30 -0
- package/apps/runtime/dist/engenty/document-scanner/schemas/index.js +4 -0
- package/apps/runtime/dist/engenty/document-scanner/schemas/invoice.js +73 -0
- package/apps/runtime/dist/engenty/document-scanner/schemas/receipt.js +63 -0
- package/apps/runtime/dist/engenty/document-scanner/schemas/shared.js +40 -0
- package/apps/runtime/dist/engenty/search-index/chunks.js +164 -0
- package/apps/runtime/dist/engenty/search-index/contracts.js +9 -0
- package/apps/runtime/dist/engenty/shims/connections-sdk.js +39 -0
- package/apps/runtime/dist/engenty/shims/plugin-sdk.js +1 -0
- package/apps/runtime/dist/engenty/shims/web-ingest.js +19 -0
- package/apps/runtime/dist/engenty/web-ingest/ssrf.js +277 -0
- package/apps/runtime/dist/engine/asks.js +82 -0
- package/apps/runtime/dist/engine/decide.js +82 -0
- package/apps/runtime/dist/engine/device.js +194 -0
- package/apps/runtime/dist/engine/events.js +128 -0
- package/apps/runtime/dist/engine/input.js +208 -0
- package/apps/runtime/dist/engine/owner.js +32 -0
- package/apps/runtime/dist/engine/prepare.js +90 -0
- package/apps/runtime/dist/engine/push.js +58 -0
- package/apps/runtime/dist/engine/requirements.js +355 -0
- package/apps/runtime/dist/engine/resources.js +198 -0
- package/apps/runtime/dist/engine/runner.js +970 -0
- package/apps/runtime/dist/engine/steps.js +1000 -0
- package/apps/runtime/dist/engine/surface.js +91 -0
- package/apps/runtime/dist/engine/template.js +240 -0
- package/apps/runtime/dist/engine/types.js +4 -0
- package/apps/runtime/dist/env.js +279 -0
- package/apps/runtime/dist/features.js +123 -0
- package/apps/runtime/dist/files/blobs.js +22 -0
- package/apps/runtime/dist/files/objects.js +86 -0
- package/apps/runtime/dist/files/storage.js +120 -0
- package/apps/runtime/dist/files/web-images.js +101 -0
- package/apps/runtime/dist/film/project.js +257 -0
- package/apps/runtime/dist/film/skills.js +91 -0
- package/apps/runtime/dist/film/sounds.js +122 -0
- package/apps/runtime/dist/film/step.js +289 -0
- package/apps/runtime/dist/film/tools.js +99 -0
- package/apps/runtime/dist/geocode.js +58 -0
- package/apps/runtime/dist/harness/antigravity.js +129 -0
- package/apps/runtime/dist/harness/apple.js +270 -0
- package/apps/runtime/dist/harness/claude.js +147 -0
- package/apps/runtime/dist/harness/codex.js +229 -0
- package/apps/runtime/dist/harness/cursor.js +93 -0
- package/apps/runtime/dist/harness/env.js +124 -0
- package/apps/runtime/dist/harness/index.js +95 -0
- package/apps/runtime/dist/harness/model.js +279 -0
- package/apps/runtime/dist/harness/prompt.js +121 -0
- package/apps/runtime/dist/harness/terminal.js +194 -0
- package/apps/runtime/dist/harness/types.js +7 -0
- package/apps/runtime/dist/index.js +113 -0
- package/apps/runtime/dist/limits.js +81 -0
- package/apps/runtime/dist/link-preview.js +60 -0
- package/apps/runtime/dist/log.js +106 -0
- package/apps/runtime/dist/manage.js +249 -0
- package/apps/runtime/dist/mcp/auth.js +161 -0
- package/apps/runtime/dist/mcp/bridge.js +59 -0
- package/apps/runtime/dist/mcp/flow-app.js +97 -0
- package/apps/runtime/dist/mcp/handler.js +54 -0
- package/apps/runtime/dist/mcp/scopes.js +14 -0
- package/apps/runtime/dist/mcp/seen.js +65 -0
- package/apps/runtime/dist/mcp/tools.js +572 -0
- package/apps/runtime/dist/media/conversation.js +167 -0
- package/apps/runtime/dist/media/ffmpeg.js +121 -0
- package/apps/runtime/dist/media/generate.js +120 -0
- package/apps/runtime/dist/media/marking.js +121 -0
- package/apps/runtime/dist/media/transcribe.js +198 -0
- package/apps/runtime/dist/model-errors.js +42 -0
- package/apps/runtime/dist/models.js +1164 -0
- package/apps/runtime/dist/plugin.js +61 -0
- package/apps/runtime/dist/plugins/channels.js +78 -0
- package/apps/runtime/dist/plugins/claims.js +56 -0
- package/apps/runtime/dist/plugins/discovery.js +155 -0
- package/apps/runtime/dist/plugins/events.js +63 -0
- package/apps/runtime/dist/plugins/jobs.js +64 -0
- package/apps/runtime/dist/plugins/loader.js +508 -0
- package/apps/runtime/dist/plugins/migrations.js +69 -0
- package/apps/runtime/dist/plugins/pro-keys.js +34 -0
- package/apps/runtime/dist/plugins/pro-state.js +83 -0
- package/apps/runtime/dist/plugins/pro.js +310 -0
- package/apps/runtime/dist/plugins/public.js +44 -0
- package/apps/runtime/dist/plugins/registry.js +122 -0
- package/apps/runtime/dist/plugins/runs.js +210 -0
- package/apps/runtime/dist/render/browser-path.js +54 -0
- package/apps/runtime/dist/render/chromium.js +98 -0
- package/apps/runtime/dist/render/convert.js +158 -0
- package/apps/runtime/dist/render/downloads.js +299 -0
- package/apps/runtime/dist/render/guard.js +25 -0
- package/apps/runtime/dist/render/shaped.js +137 -0
- package/apps/runtime/dist/routes/api.js +440 -0
- package/apps/runtime/dist/routes/debug.js +42 -0
- package/apps/runtime/dist/routes/delivery.js +90 -0
- package/apps/runtime/dist/routes/internal.js +81 -0
- package/apps/runtime/dist/routes/lang.js +25 -0
- package/apps/runtime/dist/routes/marketplace.js +43 -0
- package/apps/runtime/dist/routes/plugin-public.js +113 -0
- package/apps/runtime/dist/routes/plugins.js +212 -0
- package/apps/runtime/dist/routes/runs.js +1422 -0
- package/apps/runtime/dist/routes/studio.js +1629 -0
- package/apps/runtime/dist/routes/wizard-stream.js +30 -0
- package/apps/runtime/dist/running.js +39 -0
- package/apps/runtime/dist/sandbox/agentos-package.js +73 -0
- package/apps/runtime/dist/sandbox/agentos.js +162 -0
- package/apps/runtime/dist/sandbox/docker.js +45 -0
- package/apps/runtime/dist/sandbox/index.js +52 -0
- package/apps/runtime/dist/sandbox/install.js +122 -0
- package/apps/runtime/dist/sandbox/mastra.js +71 -0
- package/apps/runtime/dist/sandbox/types.js +1 -0
- package/apps/runtime/dist/secrets/crypto.js +28 -0
- package/apps/runtime/dist/secrets/signing.js +52 -0
- package/apps/runtime/dist/secrets/vault.js +59 -0
- package/apps/runtime/dist/services/access.js +88 -0
- package/apps/runtime/dist/services/api.js +248 -0
- package/apps/runtime/dist/services/architect.js +95 -0
- package/apps/runtime/dist/services/assistant-chats.js +311 -0
- package/apps/runtime/dist/services/brand.js +85 -0
- package/apps/runtime/dist/services/cloud.js +456 -0
- package/apps/runtime/dist/services/draft-events.js +27 -0
- package/apps/runtime/dist/services/engenty-shapes.js +71 -0
- package/apps/runtime/dist/services/errors.js +29 -0
- package/apps/runtime/dist/services/files.js +178 -0
- package/apps/runtime/dist/services/knowledge-model.js +559 -0
- package/apps/runtime/dist/services/knowledge.js +721 -0
- package/apps/runtime/dist/services/links.js +16 -0
- package/apps/runtime/dist/services/marketplace.js +492 -0
- package/apps/runtime/dist/services/onboarding.js +152 -0
- package/apps/runtime/dist/services/package-file.js +82 -0
- package/apps/runtime/dist/services/package.js +170 -0
- package/apps/runtime/dist/services/profile.js +51 -0
- package/apps/runtime/dist/services/project-files.js +439 -0
- package/apps/runtime/dist/services/project-index.js +707 -0
- package/apps/runtime/dist/services/projects.js +387 -0
- package/apps/runtime/dist/services/relevance.js +58 -0
- package/apps/runtime/dist/services/runners.js +178 -0
- package/apps/runtime/dist/services/runs.js +524 -0
- package/apps/runtime/dist/services/shares.js +130 -0
- package/apps/runtime/dist/services/site.js +270 -0
- package/apps/runtime/dist/services/space-categories.js +861 -0
- package/apps/runtime/dist/services/space-data.js +792 -0
- package/apps/runtime/dist/services/space-origin.js +207 -0
- package/apps/runtime/dist/services/spaces.js +657 -0
- package/apps/runtime/dist/services/translations.js +306 -0
- package/apps/runtime/dist/services/widgets.js +34 -0
- package/apps/runtime/dist/services/wizard-icon.js +157 -0
- package/apps/runtime/dist/services/wizards.js +420 -0
- package/apps/runtime/dist/settings.js +16 -0
- package/apps/runtime/dist/store/errors.js +4 -0
- package/apps/runtime/dist/store/index.js +299 -0
- package/apps/runtime/dist/store/shared-lists.js +123 -0
- package/apps/runtime/dist/tenants/control.js +238 -0
- package/apps/runtime/dist/tenants/tenant.js +26 -0
- package/apps/runtime/dist/texts.js +207 -0
- package/apps/runtime/dist/tools/browser.js +703 -0
- package/apps/runtime/dist/tools/connector.js +204 -0
- package/apps/runtime/dist/tools/index.js +291 -0
- package/apps/runtime/dist/tools/mail.js +104 -0
- package/apps/runtime/dist/tools/net-guard.js +170 -0
- package/apps/runtime/dist/tools/pages.js +81 -0
- package/apps/runtime/dist/tools/plugin.js +180 -0
- package/apps/runtime/dist/tools/project.js +154 -0
- package/apps/runtime/dist/tools/shared.js +69 -0
- package/apps/runtime/dist/tools/store.js +238 -0
- package/apps/runtime/dist/update.js +113 -0
- package/apps/runtime/dist/widgets/bundle.js +99 -0
- package/apps/runtime/dist/widgets/render.js +329 -0
- package/apps/runtime/dist/widgets/runtime.js +108 -0
- package/apps/runtime/dist/widgets/script.js +30 -0
- package/apps/runtime/dist/widgets/step.js +223 -0
- package/apps/web/dist/ai-labels/ai-black.svg +20 -0
- package/apps/web/dist/ai-labels/ai-generated-black.svg +31 -0
- package/apps/web/dist/ai-labels/ai-generated-white.svg +32 -0
- package/apps/web/dist/ai-labels/ai-modified-black.svg +30 -0
- package/apps/web/dist/ai-labels/ai-modified-white.svg +31 -0
- package/apps/web/dist/ai-labels/ai-white.svg +21 -0
- package/apps/web/dist/assets/AboutDialog-DYgXPagX.js +1 -0
- package/apps/web/dist/assets/ChangelogDialog-BXqBW8j3.js +1 -0
- package/apps/web/dist/assets/ChatView-CK2--tsE.js +10 -0
- package/apps/web/dist/assets/EditorPage-jvcwyXbU.js +3 -0
- package/apps/web/dist/assets/FlowPreview-CusP7ci9.js +1 -0
- package/apps/web/dist/assets/Harness-BrP-ENHg.css +1 -0
- package/apps/web/dist/assets/Harness-CV9uYzbv.js +16 -0
- package/apps/web/dist/assets/NewWizardChannels-BakW5q6s.js +1 -0
- package/apps/web/dist/assets/NewWizardPage-BoA-LJuW.js +7 -0
- package/apps/web/dist/assets/OnboardingPage-DaD1XnOe.js +1 -0
- package/apps/web/dist/assets/ProjectPage-BFgk1DEv.js +1 -0
- package/apps/web/dist/assets/PublicRunner-C9MwEvxy.js +1 -0
- package/apps/web/dist/assets/ReadOnly-DC2Kp7l8.js +1 -0
- package/apps/web/dist/assets/RunDrawer-CY6NZSrI.js +4 -0
- package/apps/web/dist/assets/RunnerView-BT26XgcY.js +1 -0
- package/apps/web/dist/assets/SettingsPage-AFt9IDLt.js +1 -0
- package/apps/web/dist/assets/SetupPage-DtFYAbwJ.js +1 -0
- package/apps/web/dist/assets/SharePage-t2xwNS61.js +1 -0
- package/apps/web/dist/assets/changelog-CATQFxCQ.js +1 -0
- package/apps/web/dist/assets/engenty-eXZ-EAwd.js +1 -0
- package/apps/web/dist/assets/esm-DXeMu8Lb.js +7 -0
- package/apps/web/dist/assets/fluffy-engenty-ClRou7yu.js +456 -0
- package/apps/web/dist/assets/index-AfUa8xKD.css +1 -0
- package/apps/web/dist/assets/index-Drw7FMTQ.js +14 -0
- package/apps/web/dist/assets/jsx-runtime-BNakU3Ej.js +1 -0
- package/apps/web/dist/assets/lock-R_CfU0Xo.js +1 -0
- package/apps/web/dist/assets/oss-credits-cZ9NUaLZ.js +1 -0
- package/apps/web/dist/assets/pdfmake-Cx9scTbD.js +228 -0
- package/apps/web/dist/assets/phone-CgrIS4_-.js +1 -0
- package/apps/web/dist/assets/preload-helper-CNEI7N0N.js +1 -0
- package/apps/web/dist/assets/qr-scanner-worker.min-CJaXo3yu.js +98 -0
- package/apps/web/dist/assets/qr-scanner.min-C_UI0gH-.js +1 -0
- package/apps/web/dist/assets/rolldown-runtime-hePW80VL.js +1 -0
- package/apps/web/dist/assets/settings-menu-2IMOOlLl.js +1 -0
- package/apps/web/dist/assets/ui-dzGvc3xk.js +137 -0
- package/apps/web/dist/assets/upload-BSuTilFF.js +1 -0
- package/apps/web/dist/assets/vfs_fonts-DllDSYt1.js +1 -0
- package/apps/web/dist/embed.js +266 -0
- package/apps/web/dist/favicon.svg +1 -0
- package/apps/web/dist/icons/apple-touch-icon.png +0 -0
- package/apps/web/dist/icons/icon-192.png +0 -0
- package/apps/web/dist/icons/icon-512.png +0 -0
- package/apps/web/dist/icons/icon-maskable-512.png +0 -0
- package/apps/web/dist/index.html +48 -0
- package/apps/web/dist/install.sh +577 -0
- package/apps/web/dist/manifest.webmanifest +21 -0
- package/apps/web/dist/mcp/flow.html +980 -0
- package/apps/web/dist/sw.js +15 -0
- package/bin/wizards.mjs +288 -0
- package/modules/README.md +15 -0
- package/node_modules/@engenty/wizards/dist/plugin/index.d.ts +1150 -0
- package/node_modules/@engenty/wizards/dist/plugin/index.js +4 -0
- package/node_modules/@engenty/wizards/dist/plugin/studio.d.ts +322 -0
- package/node_modules/@engenty/wizards/dist/plugin/studio.js +4 -0
- package/node_modules/@engenty/wizards/dist/plugin/thread.d.ts +174 -0
- package/node_modules/@engenty/wizards/dist/plugin/thread.js +821 -0
- package/node_modules/@engenty/wizards/package.json +11 -0
- package/node_modules/@engenty-wizards/shared/dist/assistant.d.ts +174 -0
- package/node_modules/@engenty-wizards/shared/dist/assistant.js +65 -0
- package/node_modules/@engenty-wizards/shared/dist/changes.d.ts +22 -0
- package/node_modules/@engenty-wizards/shared/dist/changes.js +61 -0
- package/node_modules/@engenty-wizards/shared/dist/connectors.d.ts +77 -0
- package/node_modules/@engenty-wizards/shared/dist/connectors.js +2 -0
- package/node_modules/@engenty-wizards/shared/dist/decision.d.ts +76 -0
- package/node_modules/@engenty-wizards/shared/dist/decision.js +147 -0
- package/node_modules/@engenty-wizards/shared/dist/definition.d.ts +2922 -0
- package/node_modules/@engenty-wizards/shared/dist/definition.js +1920 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-format.d.ts +5 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-format.js +132 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-value.d.ts +11 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-value.js +209 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns.d.ts +532 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns.js +217 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/index.d.ts +3 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/index.js +3 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-lexical.d.ts +14 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-lexical.js +166 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-rank.d.ts +33 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-rank.js +99 -0
- package/node_modules/@engenty-wizards/shared/dist/feature-flags.d.ts +78 -0
- package/node_modules/@engenty-wizards/shared/dist/feature-flags.js +70 -0
- package/node_modules/@engenty-wizards/shared/dist/features.d.ts +41 -0
- package/node_modules/@engenty-wizards/shared/dist/features.js +89 -0
- package/node_modules/@engenty-wizards/shared/dist/fit.d.ts +71 -0
- package/node_modules/@engenty-wizards/shared/dist/fit.js +382 -0
- package/node_modules/@engenty-wizards/shared/dist/json-schema.d.ts +14 -0
- package/node_modules/@engenty-wizards/shared/dist/json-schema.js +66 -0
- package/node_modules/@engenty-wizards/shared/dist/knowledge.d.ts +199 -0
- package/node_modules/@engenty-wizards/shared/dist/knowledge.js +68 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace-entry.d.ts +35 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace-entry.js +107 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace-search.d.ts +20 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace-search.js +136 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace.d.ts +227 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace.js +354 -0
- package/node_modules/@engenty-wizards/shared/dist/merge.d.ts +7 -0
- package/node_modules/@engenty-wizards/shared/dist/merge.js +40 -0
- package/node_modules/@engenty-wizards/shared/dist/numbers.d.ts +24 -0
- package/node_modules/@engenty-wizards/shared/dist/numbers.js +54 -0
- package/node_modules/@engenty-wizards/shared/dist/projects.d.ts +224 -0
- package/node_modules/@engenty-wizards/shared/dist/projects.js +319 -0
- package/node_modules/@engenty-wizards/shared/dist/providers.d.ts +101 -0
- package/node_modules/@engenty-wizards/shared/dist/providers.js +390 -0
- package/node_modules/@engenty-wizards/shared/dist/run.d.ts +680 -0
- package/node_modules/@engenty-wizards/shared/dist/run.js +620 -0
- package/node_modules/@engenty-wizards/shared/dist/runner-texts.d.ts +546 -0
- package/node_modules/@engenty-wizards/shared/dist/runner-texts.js +523 -0
- package/node_modules/@engenty-wizards/shared/dist/runners.d.ts +93 -0
- package/node_modules/@engenty-wizards/shared/dist/runners.js +146 -0
- package/node_modules/@engenty-wizards/shared/dist/shape.d.ts +102 -0
- package/node_modules/@engenty-wizards/shared/dist/shape.js +318 -0
- package/node_modules/@engenty-wizards/shared/dist/space-data.d.ts +89 -0
- package/node_modules/@engenty-wizards/shared/dist/space-data.js +47 -0
- package/node_modules/@engenty-wizards/shared/dist/store.d.ts +117 -0
- package/node_modules/@engenty-wizards/shared/dist/store.js +81 -0
- package/node_modules/@engenty-wizards/shared/dist/surface.d.ts +115 -0
- package/node_modules/@engenty-wizards/shared/dist/surface.js +442 -0
- package/node_modules/@engenty-wizards/shared/dist/texts.d.ts +45 -0
- package/node_modules/@engenty-wizards/shared/dist/texts.js +54 -0
- package/node_modules/@engenty-wizards/shared/dist/translation.d.ts +23 -0
- package/node_modules/@engenty-wizards/shared/dist/translation.js +154 -0
- package/node_modules/@engenty-wizards/shared/dist/wizard-package.d.ts +48 -0
- package/node_modules/@engenty-wizards/shared/dist/wizard-package.js +49 -0
- package/node_modules/@engenty-wizards/shared/dist/workspace.d.ts +16 -0
- package/node_modules/@engenty-wizards/shared/dist/workspace.js +51 -0
- package/node_modules/@engenty-wizards/shared/package.json +10 -0
- package/package.json +77 -4
- package/plugin/.claude-plugin/plugin.json +9 -0
- package/plugin/.mcp.json +8 -0
- package/plugin/commands/wizard.md +8 -0
- package/plugin/skills/build-wizard/SKILL.md +27 -0
- package/plugin/skills/use-wizard/SKILL.md +18 -0
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
2
|
+
import { PACKAGE_MIME } from "@engenty-wizards/shared/wizard-package";
|
|
3
|
+
import { Hono } from "hono";
|
|
4
|
+
import { bodyLimit } from "hono/body-limit";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { balanceCredits } from "../credits/credits.js";
|
|
7
|
+
import { withTenant } from "../db/client.js";
|
|
8
|
+
import { env } from "../env.js";
|
|
9
|
+
import { allowed } from "../limits.js";
|
|
10
|
+
import { managed, tenantInfo } from "../manage.js";
|
|
11
|
+
import { authenticate, principalOf } from "../mcp/auth.js";
|
|
12
|
+
import { loadedPlugin, pluginIdsOf } from "../plugins/registry.js";
|
|
13
|
+
import { asRole, mayBuild, mayCreate } from "../services/access.js";
|
|
14
|
+
import { apiRun, apiRuns, apiSpaceDetails, apiSpaces, apiWizards } from "../services/api.js";
|
|
15
|
+
import { ServiceError } from "../services/errors.js";
|
|
16
|
+
import { deleteFile, draftFiles, writeFile } from "../services/files.js";
|
|
17
|
+
import { asLang, searchMarketplace } from "../services/marketplace.js";
|
|
18
|
+
import { exportWizard } from "../services/package.js";
|
|
19
|
+
import { siteJob, siteSchema, startSiteJob } from "../services/site.js";
|
|
20
|
+
import { checkOnServer, checkSchema, listSyncedSpaces, patchSyncedWizard, removeSyncedSpace, removeSyncedWizard, rotateSyncedLink, syncDataSchema, syncSettingsSchema, syncSpaceData, syncWizard, syncWizardSchema, } from "../services/spaces.js";
|
|
21
|
+
import { createWizard, ownedWizard, publishWizard, writeDraft } from "../services/wizards.js";
|
|
22
|
+
import { codeOf, tenantStatus } from "../tenants/control.js";
|
|
23
|
+
import { notFoundAnswer, say } from "./lang.js";
|
|
24
|
+
import { dispatchAs } from "./plugins.js";
|
|
25
|
+
const importSchema = z.object({
|
|
26
|
+
/** An earlier import's wizard: it is updated instead of a new one being made. */
|
|
27
|
+
wizardId: z.string().optional(),
|
|
28
|
+
projectId: z.string().optional(),
|
|
29
|
+
definition: z.unknown(),
|
|
30
|
+
files: z
|
|
31
|
+
.array(z.object({ path: z.string(), mime: z.string().optional(), data: z.string() }))
|
|
32
|
+
.max(200)
|
|
33
|
+
.default([]),
|
|
34
|
+
publish: z.boolean().default(false),
|
|
35
|
+
});
|
|
36
|
+
/** Runs a call in the caller's tenant, as the caller's role. */
|
|
37
|
+
const inTenantAs = (who, fn) => withTenant(who.tenantId, () => asRole(who.role, fn));
|
|
38
|
+
const HOUR = 60 * 60 * 1000;
|
|
39
|
+
/** Where the account of a managed runtime is looked after: plan, credits, keys. */
|
|
40
|
+
const accountUrl = () => env.manage.url || null;
|
|
41
|
+
/** Plugins of the plans above Free that a client offers when the tenant lacks them. */
|
|
42
|
+
const PRO_PLUGINS = ["contacts", "appointments"];
|
|
43
|
+
/** A wizard with its workspace: 25 MB of files as base64, and the definition. */
|
|
44
|
+
const WIZARD_BYTES = 48 * 1024 * 1024;
|
|
45
|
+
const tooLarge = bodyLimit({
|
|
46
|
+
maxSize: WIZARD_BYTES,
|
|
47
|
+
onError: (c) => c.json({ error: "The request is too large.", code: "too_large" }, 413),
|
|
48
|
+
});
|
|
49
|
+
/**
|
|
50
|
+
* The caller of an API call, signed in like an MCP client (access token or API key), with the
|
|
51
|
+
* scopes the call needs; or the answer that turns it away.
|
|
52
|
+
*/
|
|
53
|
+
async function caller(c, scopes) {
|
|
54
|
+
const authInfo = await authenticate(c.req.raw);
|
|
55
|
+
if (authInfo instanceof Response) {
|
|
56
|
+
return authInfo;
|
|
57
|
+
}
|
|
58
|
+
const who = principalOf(authInfo);
|
|
59
|
+
if (scopes.some((scope) => !who.scopes.includes(scope))) {
|
|
60
|
+
return c.json({ error: "This token isn’t allowed to do that.", code: "insufficient_scope" }, 403);
|
|
61
|
+
}
|
|
62
|
+
if ((await tenantStatus(who.tenantId)) === "suspended") {
|
|
63
|
+
return c.json({
|
|
64
|
+
error: say(c, "accountSuspended"),
|
|
65
|
+
code: "tenant_suspended",
|
|
66
|
+
}, 403);
|
|
67
|
+
}
|
|
68
|
+
return who;
|
|
69
|
+
}
|
|
70
|
+
/** A local install sends when it publishes: more than this an hour is not an install at work. */
|
|
71
|
+
function withinSyncLimit(c, who) {
|
|
72
|
+
return allowed(`sync:${who.tenantId}`, 240, HOUR)
|
|
73
|
+
? null
|
|
74
|
+
: c.json({
|
|
75
|
+
error: say(c, "tooManyTransfersTry"),
|
|
76
|
+
code: "rate_limited",
|
|
77
|
+
}, 429);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* A plugin's routes for a client with a key or token (the WordPress plugin's Kontakte, Termine):
|
|
81
|
+
* the plugin's own `registerHttpRoute`s, as the key's person. Reading needs `wizards:read`,
|
|
82
|
+
* anything else `wizards:write`. A plugin the tenant's plan lacks answers `403 { code: "plugin" }`.
|
|
83
|
+
*/
|
|
84
|
+
async function pluginCall(c) {
|
|
85
|
+
const who = await caller(c, [c.req.method === "GET" ? "wizards:read" : "wizards:write"]);
|
|
86
|
+
if (who instanceof Response) {
|
|
87
|
+
return who;
|
|
88
|
+
}
|
|
89
|
+
const id = c.req.param("id") ?? "";
|
|
90
|
+
if (!(await pluginIdsOf(who.tenantId)).has(id)) {
|
|
91
|
+
return loadedPlugin(id) || PRO_PLUGINS.includes(id)
|
|
92
|
+
? c.json({
|
|
93
|
+
error: say(c, "pluginNotPartPlan"),
|
|
94
|
+
code: "plugin",
|
|
95
|
+
plugin: id,
|
|
96
|
+
}, 403)
|
|
97
|
+
: c.json(notFoundAnswer(c), 404);
|
|
98
|
+
}
|
|
99
|
+
return inTenantAs(who, () => dispatchAs(c, {
|
|
100
|
+
id: who.userId,
|
|
101
|
+
tenantId: who.tenantId,
|
|
102
|
+
role: who.role,
|
|
103
|
+
name: who.name ?? "",
|
|
104
|
+
email: who.email ?? "",
|
|
105
|
+
}));
|
|
106
|
+
}
|
|
107
|
+
const runsQuery = z.object({
|
|
108
|
+
space: z.string().optional(),
|
|
109
|
+
wizard: z.string().optional(),
|
|
110
|
+
status: z.enum(["done", "open", "all"]).optional(),
|
|
111
|
+
q: z.string().max(200).optional(),
|
|
112
|
+
days: z.coerce.number().int().min(1).max(3650).optional(),
|
|
113
|
+
page: z.coerce.number().int().min(1).max(10_000).optional(),
|
|
114
|
+
});
|
|
115
|
+
/**
|
|
116
|
+
* The runtime's API for other programs. `/spaces/…` is how a local install's project comes
|
|
117
|
+
* here: the wizards it publishes, under the ids they have there (docs/manage-contract.md).
|
|
118
|
+
* `POST /wizards/import` takes a whole wizard as a new one of a tenant that builds here.
|
|
119
|
+
*/
|
|
120
|
+
export const apiRoutes = new Hono()
|
|
121
|
+
// Who the key or token acts for, and what the account has: plan, plugins, spaces, credits.
|
|
122
|
+
.get("/me", async (c) => {
|
|
123
|
+
const who = await caller(c, []);
|
|
124
|
+
if (who instanceof Response) {
|
|
125
|
+
return who;
|
|
126
|
+
}
|
|
127
|
+
const info = managed ? await tenantInfo(who.tenantId).catch(() => null) : null;
|
|
128
|
+
return inTenantAs(who, async () => {
|
|
129
|
+
const plugins = [...(await pluginIdsOf(who.tenantId))].sort();
|
|
130
|
+
const account = accountUrl();
|
|
131
|
+
return c.json({
|
|
132
|
+
user: { id: who.userId, name: who.name ?? "", email: who.email ?? "", role: who.role },
|
|
133
|
+
tenant: {
|
|
134
|
+
id: who.tenantId,
|
|
135
|
+
name: info?.name ?? "",
|
|
136
|
+
plan: info?.plan ?? null,
|
|
137
|
+
credits: await balanceCredits(),
|
|
138
|
+
},
|
|
139
|
+
/** Makes and changes wizards and spaces here; Free builds in the local app. */
|
|
140
|
+
build: await mayBuild(),
|
|
141
|
+
create: await mayCreate(),
|
|
142
|
+
plugins,
|
|
143
|
+
/** What a plan above this one would add. */
|
|
144
|
+
missing: PRO_PLUGINS.filter((id) => !plugins.includes(id)),
|
|
145
|
+
spaces: await apiSpaces(who.userId),
|
|
146
|
+
scopes: who.scopes,
|
|
147
|
+
client: who.client,
|
|
148
|
+
urls: {
|
|
149
|
+
app: env.appUrl,
|
|
150
|
+
embed: `${env.publicUrl}/embed.js`,
|
|
151
|
+
studio: `${env.appUrl}/studio`,
|
|
152
|
+
newWizard: `${env.appUrl}/studio/new`,
|
|
153
|
+
space: `${env.appUrl}/studio/space`,
|
|
154
|
+
account: account,
|
|
155
|
+
billing: account ? `${account}/billing` : null,
|
|
156
|
+
upgrade: account ? `${account}/billing?upgrade=pro` : null,
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
})
|
|
161
|
+
// The wizards of the caller's spaces: published ones with their link and ID, drafts without.
|
|
162
|
+
.get("/wizards", async (c) => {
|
|
163
|
+
const who = await caller(c, ["wizards:read"]);
|
|
164
|
+
if (who instanceof Response) {
|
|
165
|
+
return who;
|
|
166
|
+
}
|
|
167
|
+
return inTenantAs(who, async () => c.json({ wizards: await apiWizards(who.userId, c.req.query("space")) }));
|
|
168
|
+
})
|
|
169
|
+
// The published wizard as a `.wizard` package: what a WordPress site runs on its own; with
|
|
170
|
+
// `knowledge=1` the project's pages come along as files (up to the snapshot's cap).
|
|
171
|
+
.get("/wizards/:id/package", async (c) => {
|
|
172
|
+
const who = await caller(c, ["wizards:read"]);
|
|
173
|
+
if (who instanceof Response) {
|
|
174
|
+
return who;
|
|
175
|
+
}
|
|
176
|
+
return inTenantAs(who, async () => {
|
|
177
|
+
const found = await exportWizard(who.userId, c.req.param("id"), {
|
|
178
|
+
published: true,
|
|
179
|
+
knowledge: c.req.query("knowledge") === "1",
|
|
180
|
+
});
|
|
181
|
+
if (!found) {
|
|
182
|
+
return c.json({
|
|
183
|
+
error: say(c, "wizardNotPublishedYet"),
|
|
184
|
+
code: "not_found",
|
|
185
|
+
}, 404);
|
|
186
|
+
}
|
|
187
|
+
return new Response(new Uint8Array(found.zip), {
|
|
188
|
+
headers: {
|
|
189
|
+
"content-type": PACKAGE_MIME,
|
|
190
|
+
"content-disposition": `attachment; filename="${found.name}"`,
|
|
191
|
+
"cache-control": "no-store",
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
})
|
|
196
|
+
// A new wizard from a template, published at once: what a website starts with.
|
|
197
|
+
.post("/wizards", async (c) => {
|
|
198
|
+
const who = await caller(c, ["wizards:write", "wizards:publish"]);
|
|
199
|
+
if (who instanceof Response) {
|
|
200
|
+
return who;
|
|
201
|
+
}
|
|
202
|
+
const body = z
|
|
203
|
+
.object({
|
|
204
|
+
starterId: z.string().min(1).max(200),
|
|
205
|
+
spaceId: z.string().optional(),
|
|
206
|
+
lang: z.string().max(10).optional(),
|
|
207
|
+
publish: z.boolean().default(true),
|
|
208
|
+
})
|
|
209
|
+
.parse(await c.req.json());
|
|
210
|
+
return inTenantAs(who, async () => {
|
|
211
|
+
const writer = { source: "mcp", client: who.client };
|
|
212
|
+
const created = await createWizard(who.userId, { projectId: body.spaceId, starterId: body.starterId, lang: body.lang }, writer);
|
|
213
|
+
let published = false;
|
|
214
|
+
if (body.publish && !created.issues.length) {
|
|
215
|
+
published = await publishWizard(who.userId, created.id).then(() => true, () => false);
|
|
216
|
+
}
|
|
217
|
+
const wizard = (await apiWizards(who.userId)).find((w) => w.id === created.id);
|
|
218
|
+
return c.json({ wizard, published, issues: created.issues });
|
|
219
|
+
});
|
|
220
|
+
})
|
|
221
|
+
// What a new wizard can start from: the plugins' starters first, then the marketplace's.
|
|
222
|
+
.get("/templates", async (c) => {
|
|
223
|
+
const who = await caller(c, ["wizards:read"]);
|
|
224
|
+
if (who instanceof Response) {
|
|
225
|
+
return who;
|
|
226
|
+
}
|
|
227
|
+
const q = c.req.query("q")?.trim() ?? "";
|
|
228
|
+
return inTenantAs(who, async () => {
|
|
229
|
+
const { entries } = await searchMarketplace({
|
|
230
|
+
q,
|
|
231
|
+
lang: asLang(c.req.query("lang")),
|
|
232
|
+
limit: 40,
|
|
233
|
+
});
|
|
234
|
+
return c.json({
|
|
235
|
+
templates: entries
|
|
236
|
+
.filter((e) => e.usable && (q || e.starter))
|
|
237
|
+
.map((e) => ({
|
|
238
|
+
id: e.id,
|
|
239
|
+
title: e.title,
|
|
240
|
+
pitch: e.pitch,
|
|
241
|
+
avatar: e.avatar,
|
|
242
|
+
language: e.language,
|
|
243
|
+
useCases: e.useCases,
|
|
244
|
+
formats: e.formats,
|
|
245
|
+
plan: e.plan ?? "free",
|
|
246
|
+
plugin: e.plugin ?? null,
|
|
247
|
+
/** Plugins the tenant lacks: a wizard made from it would not run. */
|
|
248
|
+
needs: e.needs ?? [],
|
|
249
|
+
credits: e.credits,
|
|
250
|
+
})),
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
})
|
|
254
|
+
// What visitors left: the live runs of the caller's wizards, by pages of 50.
|
|
255
|
+
.get("/runs", async (c) => {
|
|
256
|
+
const who = await caller(c, ["runs:read"]);
|
|
257
|
+
if (who instanceof Response) {
|
|
258
|
+
return who;
|
|
259
|
+
}
|
|
260
|
+
const query = runsQuery.parse(c.req.query());
|
|
261
|
+
return inTenantAs(who, async () => c.json(await apiRuns(who.userId, {
|
|
262
|
+
spaceId: query.space,
|
|
263
|
+
wizardId: query.wizard,
|
|
264
|
+
status: query.status,
|
|
265
|
+
q: query.q,
|
|
266
|
+
days: query.days,
|
|
267
|
+
page: query.page,
|
|
268
|
+
})));
|
|
269
|
+
})
|
|
270
|
+
.get("/runs/:id", async (c) => {
|
|
271
|
+
const who = await caller(c, ["runs:read"]);
|
|
272
|
+
if (who instanceof Response) {
|
|
273
|
+
return who;
|
|
274
|
+
}
|
|
275
|
+
return inTenantAs(who, async () => c.json(await apiRun(who.userId, c.req.param("id"))));
|
|
276
|
+
})
|
|
277
|
+
// The space's own details: title, about, colours, facts, logo, how much Knowledge it holds.
|
|
278
|
+
.get("/space", async (c) => {
|
|
279
|
+
const who = await caller(c, ["wizards:read"]);
|
|
280
|
+
if (who instanceof Response) {
|
|
281
|
+
return who;
|
|
282
|
+
}
|
|
283
|
+
return inTenantAs(who, async () => c.json(await apiSpaceDetails(who.userId, c.req.query("space"))));
|
|
284
|
+
})
|
|
285
|
+
// A website reads itself into the space (services/site.ts); answers with the job to ask after.
|
|
286
|
+
.post("/space/site", tooLarge, async (c) => {
|
|
287
|
+
const who = await caller(c, ["wizards:write"]);
|
|
288
|
+
if (who instanceof Response) {
|
|
289
|
+
return who;
|
|
290
|
+
}
|
|
291
|
+
if (!allowed(`site:${who.tenantId}`, 20, HOUR)) {
|
|
292
|
+
return c.json({
|
|
293
|
+
error: say(c, "tooManyTimesRow"),
|
|
294
|
+
code: "rate_limited",
|
|
295
|
+
}, 429);
|
|
296
|
+
}
|
|
297
|
+
const body = siteSchema.parse(await c.req.json());
|
|
298
|
+
return inTenantAs(who, async () => c.json(await startSiteJob(who, body)));
|
|
299
|
+
})
|
|
300
|
+
.get("/space/site/:job", async (c) => {
|
|
301
|
+
const who = await caller(c, ["wizards:read"]);
|
|
302
|
+
if (who instanceof Response) {
|
|
303
|
+
return who;
|
|
304
|
+
}
|
|
305
|
+
return inTenantAs(who, () => c.json(siteJob(c.req.param("job"))));
|
|
306
|
+
})
|
|
307
|
+
.all("/plugins/:id", pluginCall)
|
|
308
|
+
.all("/plugins/:id/*", pluginCall)
|
|
309
|
+
.get("/spaces", async (c) => {
|
|
310
|
+
const who = await caller(c, ["wizards:read"]);
|
|
311
|
+
if (who instanceof Response) {
|
|
312
|
+
return who;
|
|
313
|
+
}
|
|
314
|
+
return inTenantAs(who, async () => c.json({ spaces: await listSyncedSpaces() }));
|
|
315
|
+
})
|
|
316
|
+
.post("/spaces/check", async (c) => {
|
|
317
|
+
const who = await caller(c, ["wizards:read"]);
|
|
318
|
+
if (who instanceof Response) {
|
|
319
|
+
return who;
|
|
320
|
+
}
|
|
321
|
+
const body = checkSchema.parse(await c.req.json());
|
|
322
|
+
return inTenantAs(who, async () => c.json({ problems: await checkOnServer(body) }));
|
|
323
|
+
})
|
|
324
|
+
.put("/spaces/:spaceId/wizards/:wizardId", tooLarge, async (c) => {
|
|
325
|
+
const who = await caller(c, ["wizards:write", "wizards:publish"]);
|
|
326
|
+
if (who instanceof Response) {
|
|
327
|
+
return who;
|
|
328
|
+
}
|
|
329
|
+
const limited = withinSyncLimit(c, who);
|
|
330
|
+
if (limited) {
|
|
331
|
+
return limited;
|
|
332
|
+
}
|
|
333
|
+
const body = syncWizardSchema.parse(await c.req.json());
|
|
334
|
+
return inTenantAs(who, async () => c.json(await syncWizard(c.req.param("spaceId"), c.req.param("wizardId"), body)));
|
|
335
|
+
})
|
|
336
|
+
// The space's own tables and pages, sent with a wizard when they changed.
|
|
337
|
+
.put("/spaces/:spaceId/data", tooLarge, async (c) => {
|
|
338
|
+
const who = await caller(c, ["wizards:write"]);
|
|
339
|
+
if (who instanceof Response) {
|
|
340
|
+
return who;
|
|
341
|
+
}
|
|
342
|
+
const limited = withinSyncLimit(c, who);
|
|
343
|
+
if (limited) {
|
|
344
|
+
return limited;
|
|
345
|
+
}
|
|
346
|
+
const body = syncDataSchema.parse(await c.req.json());
|
|
347
|
+
return inTenantAs(who, async () => c.json(await syncSpaceData(c.req.param("spaceId"), body)));
|
|
348
|
+
})
|
|
349
|
+
.patch("/spaces/:spaceId/wizards/:wizardId", async (c) => {
|
|
350
|
+
const who = await caller(c, ["wizards:publish"]);
|
|
351
|
+
if (who instanceof Response) {
|
|
352
|
+
return who;
|
|
353
|
+
}
|
|
354
|
+
const limited = withinSyncLimit(c, who);
|
|
355
|
+
if (limited) {
|
|
356
|
+
return limited;
|
|
357
|
+
}
|
|
358
|
+
const body = syncSettingsSchema.parse(await c.req.json());
|
|
359
|
+
return inTenantAs(who, async () => c.json(await patchSyncedWizard(c.req.param("spaceId"), c.req.param("wizardId"), body)));
|
|
360
|
+
})
|
|
361
|
+
.post("/spaces/:spaceId/wizards/:wizardId/rotate-link", async (c) => {
|
|
362
|
+
const who = await caller(c, ["wizards:publish"]);
|
|
363
|
+
if (who instanceof Response) {
|
|
364
|
+
return who;
|
|
365
|
+
}
|
|
366
|
+
const limited = withinSyncLimit(c, who);
|
|
367
|
+
if (limited) {
|
|
368
|
+
return limited;
|
|
369
|
+
}
|
|
370
|
+
return inTenantAs(who, async () => c.json(await rotateSyncedLink(who.userId, c.req.param("spaceId"), c.req.param("wizardId"))));
|
|
371
|
+
})
|
|
372
|
+
.delete("/spaces/:spaceId/wizards/:wizardId", async (c) => {
|
|
373
|
+
const who = await caller(c, ["wizards:write"]);
|
|
374
|
+
if (who instanceof Response) {
|
|
375
|
+
return who;
|
|
376
|
+
}
|
|
377
|
+
return inTenantAs(who, async () => c.json(await removeSyncedWizard(who.userId, c.req.param("spaceId"), c.req.param("wizardId"))));
|
|
378
|
+
})
|
|
379
|
+
.delete("/spaces/:spaceId", async (c) => {
|
|
380
|
+
const who = await caller(c, ["wizards:write"]);
|
|
381
|
+
if (who instanceof Response) {
|
|
382
|
+
return who;
|
|
383
|
+
}
|
|
384
|
+
return inTenantAs(who, async () => c.json(await removeSyncedSpace(c.req.param("spaceId"))));
|
|
385
|
+
})
|
|
386
|
+
.post("/wizards/import", tooLarge, async (c) => {
|
|
387
|
+
const authInfo = await authenticate(c.req.raw);
|
|
388
|
+
if (authInfo instanceof Response) {
|
|
389
|
+
return authInfo;
|
|
390
|
+
}
|
|
391
|
+
const who = principalOf(authInfo);
|
|
392
|
+
const body = importSchema.parse(await c.req.json());
|
|
393
|
+
if (!who.scopes.includes("wizards:write") ||
|
|
394
|
+
(body.publish && !who.scopes.includes("wizards:publish"))) {
|
|
395
|
+
return c.json({ error: "This token isn’t allowed to do that.", code: "insufficient_scope" }, 403);
|
|
396
|
+
}
|
|
397
|
+
if ((await tenantStatus(who.tenantId)) === "suspended") {
|
|
398
|
+
return c.json({
|
|
399
|
+
error: say(c, "accountSuspended"),
|
|
400
|
+
code: "tenant_suspended",
|
|
401
|
+
}, 403);
|
|
402
|
+
}
|
|
403
|
+
return inTenantAs(who, async () => {
|
|
404
|
+
const writer = { source: "mcp", client: who.client };
|
|
405
|
+
let wizardId = body.wizardId;
|
|
406
|
+
if (wizardId) {
|
|
407
|
+
const existing = await ownedWizard(who.userId, wizardId).catch(() => null);
|
|
408
|
+
wizardId = existing?.id;
|
|
409
|
+
}
|
|
410
|
+
if (!wizardId) {
|
|
411
|
+
// The workspace must be there before the definition is checked against it.
|
|
412
|
+
const created = await createWizard(who.userId, { projectId: body.projectId }, writer);
|
|
413
|
+
wizardId = created.id;
|
|
414
|
+
}
|
|
415
|
+
const incoming = new Set(body.files.map((f) => f.path));
|
|
416
|
+
for (const old of await draftFiles(wizardId)) {
|
|
417
|
+
if (!incoming.has(old.path)) {
|
|
418
|
+
await deleteFile(who.userId, wizardId, old.path);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
for (const file of body.files) {
|
|
422
|
+
await writeFile(who.userId, wizardId, file.path, Buffer.from(file.data, "base64"), file.mime);
|
|
423
|
+
}
|
|
424
|
+
const current = await ownedWizard(who.userId, wizardId);
|
|
425
|
+
const written = await writeDraft(who.userId, wizardId, { definition: body.definition, baseRevision: current.revision }, writer);
|
|
426
|
+
if (!body.publish) {
|
|
427
|
+
return c.json({ wizardId, revision: written.revision, issues: written.issues });
|
|
428
|
+
}
|
|
429
|
+
if (written.issues.length) {
|
|
430
|
+
throw new ServiceError("has_issues", note("wizardStillErrors"), {
|
|
431
|
+
issues: written.issues,
|
|
432
|
+
wizardId,
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
const published = await publishWizard(who.userId, wizardId);
|
|
436
|
+
// The ID the mobile app takes.
|
|
437
|
+
const code = await codeOf(current.shareToken);
|
|
438
|
+
return c.json({ wizardId, revision: written.revision, issues: [], ...published, code });
|
|
439
|
+
});
|
|
440
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { LOCAL_MCP_HEADER, localTicketExpiry } from "../auth/local-ticket.js";
|
|
4
|
+
import { logs, ReportError, sendReport, status } from "../debug.js";
|
|
5
|
+
import { env } from "../env.js";
|
|
6
|
+
import { tailQuery } from "../log.js";
|
|
7
|
+
import { managed } from "../manage.js";
|
|
8
|
+
/**
|
|
9
|
+
* A runtime that runs alone answers its own command line here (`wizards logs`, `wizards
|
|
10
|
+
* report`): each request signed with the data folder's secret, as `wizards mcp` signs its own.
|
|
11
|
+
* Nothing of this is reached from another machine; the account hears from an install only when
|
|
12
|
+
* the person sends a report.
|
|
13
|
+
*/
|
|
14
|
+
export const localDebugRoutes = new Hono()
|
|
15
|
+
.use(async (c, next) => {
|
|
16
|
+
const ticket = c.req.header(LOCAL_MCP_HEADER) ?? "";
|
|
17
|
+
if (managed || !localTicketExpiry(env.authSecret, ticket, Date.now(), "local-debug")) {
|
|
18
|
+
return c.json({ error: "This ticket isn’t valid.", code: "unauthorized" }, 401);
|
|
19
|
+
}
|
|
20
|
+
await next();
|
|
21
|
+
})
|
|
22
|
+
.get("/status", async (c) => c.json(await status()))
|
|
23
|
+
.get("/logs", (c) => c.json(logs(tailQuery((key) => c.req.query(key)))))
|
|
24
|
+
.post("/report", async (c) => {
|
|
25
|
+
try {
|
|
26
|
+
return c.json(await sendReport());
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
if (err instanceof ReportError) {
|
|
30
|
+
return c.json({ error: err.message, code: err.code }, err.code === "no_account" ? 409 : 502);
|
|
31
|
+
}
|
|
32
|
+
throw err;
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
/** What a page reports about itself: an error it met, with where it stood. */
|
|
36
|
+
export const browserReport = z.object({
|
|
37
|
+
level: z.enum(["error", "warn"]).default("error"),
|
|
38
|
+
message: z.string().min(1).max(2000),
|
|
39
|
+
stack: z.string().max(4000).optional(),
|
|
40
|
+
url: z.string().max(500).optional(),
|
|
41
|
+
agent: z.string().max(300).optional(),
|
|
42
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { basePath } from "../env.js";
|
|
2
|
+
/** Uploads stay small; a clip from the phone's camera is the one thing that needs more room. */
|
|
3
|
+
export function uploadLimit(mime) {
|
|
4
|
+
return mime.startsWith("video/") ? 40_000_000 : 15_000_000;
|
|
5
|
+
}
|
|
6
|
+
/** `type/subtype` and nothing else: no commas, spaces or quotes a browser could read another type from. */
|
|
7
|
+
const MIME = /^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/;
|
|
8
|
+
/** The bare type of a declared one ("audio/webm;codecs=opus" → "audio/webm"), or null if it is not one. */
|
|
9
|
+
export function bareMime(declared) {
|
|
10
|
+
const mime = declared.split(";")[0].trim().toLowerCase();
|
|
11
|
+
return MIME.test(mime) ? mime : null;
|
|
12
|
+
}
|
|
13
|
+
/** What a person hands a wizard besides photos, recordings and clips: documents and tables. */
|
|
14
|
+
const DOCUMENT_TYPES = new Set([
|
|
15
|
+
"application/pdf",
|
|
16
|
+
"application/msword",
|
|
17
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
18
|
+
"application/vnd.ms-excel",
|
|
19
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
20
|
+
"application/vnd.ms-powerpoint",
|
|
21
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
22
|
+
"application/vnd.oasis.opendocument.text",
|
|
23
|
+
"application/vnd.oasis.opendocument.spreadsheet",
|
|
24
|
+
"application/vnd.oasis.opendocument.presentation",
|
|
25
|
+
"application/rtf",
|
|
26
|
+
"application/json",
|
|
27
|
+
"application/zip",
|
|
28
|
+
"message/rfc822",
|
|
29
|
+
"text/plain",
|
|
30
|
+
"text/csv",
|
|
31
|
+
"text/tab-separated-values",
|
|
32
|
+
"text/markdown",
|
|
33
|
+
"text/calendar",
|
|
34
|
+
"text/vcard",
|
|
35
|
+
]);
|
|
36
|
+
/**
|
|
37
|
+
* The type an upload is kept as: the browser's word for it, when it is a picture, a recording, a
|
|
38
|
+
* clip or a document. Anything else (an HTML page, a script) is kept as plain bytes; reading it
|
|
39
|
+
* goes by its name (documents/parse.ts).
|
|
40
|
+
*/
|
|
41
|
+
export function uploadMime(declared) {
|
|
42
|
+
const mime = bareMime(declared);
|
|
43
|
+
return mime && (/^(image|audio|video)\//.test(mime) || DOCUMENT_TYPES.has(mime))
|
|
44
|
+
? mime
|
|
45
|
+
: "application/octet-stream";
|
|
46
|
+
}
|
|
47
|
+
/** What a browser shows in place without running anything of the file's: photos, sound, film, PDFs. */
|
|
48
|
+
export function inlineSafe(mime) {
|
|
49
|
+
return ((/^(image|audio|video)\//.test(mime) && !mime.startsWith("image/svg")) ||
|
|
50
|
+
mime === "application/pdf");
|
|
51
|
+
}
|
|
52
|
+
/** `version`: the published one, so a new engenty or name reaches icons a phone has kept. */
|
|
53
|
+
export function wizardManifest(token, title, description, version = 0) {
|
|
54
|
+
const start = `${basePath}/w/${token}`;
|
|
55
|
+
const icon = (file) => `${basePath}/api/public/wizards/${token}/icons/${file}?v=${version}`;
|
|
56
|
+
return {
|
|
57
|
+
id: start,
|
|
58
|
+
name: title,
|
|
59
|
+
short_name: title.length > 14 ? `${title.slice(0, 13).trimEnd()}…` : title,
|
|
60
|
+
description,
|
|
61
|
+
start_url: start,
|
|
62
|
+
scope: `${basePath}/`,
|
|
63
|
+
display: "standalone",
|
|
64
|
+
background_color: "#faf8f5",
|
|
65
|
+
theme_color: "#faf8f5",
|
|
66
|
+
icons: [
|
|
67
|
+
{ src: icon("icon-192.png"), sizes: "192x192", type: "image/png", purpose: "any" },
|
|
68
|
+
{ src: icon("icon-512.png"), sizes: "512x512", type: "image/png", purpose: "any" },
|
|
69
|
+
{
|
|
70
|
+
src: icon("icon-maskable-512.png"),
|
|
71
|
+
sizes: "512x512",
|
|
72
|
+
type: "image/png",
|
|
73
|
+
purpose: "maskable",
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* One byte range of a file, as phones ask for audio and video: Safari plays a clip only from a
|
|
80
|
+
* server that answers ranges. `null` = no (usable) range asked, send it whole.
|
|
81
|
+
*/
|
|
82
|
+
export function byteRange(header, size) {
|
|
83
|
+
const m = header?.match(/^bytes=(\d*)-(\d*)$/);
|
|
84
|
+
if (!m || (!m[1] && !m[2]) || size === 0) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
const start = m[1] ? Number(m[1]) : Math.max(0, size - Number(m[2]));
|
|
88
|
+
const end = m[1] && m[2] ? Math.min(Number(m[2]), size - 1) : size - 1;
|
|
89
|
+
return start > end || start >= size ? "unsatisfiable" : { start, end };
|
|
90
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { timingSafeEqual } from "node:crypto";
|
|
2
|
+
import { rm } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { Hono } from "hono";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { closeTenantDb, tenantDb } from "../db/client.js";
|
|
7
|
+
import { logs, runDetail, status, tenantModels } from "../debug.js";
|
|
8
|
+
import { env } from "../env.js";
|
|
9
|
+
import { declaredFeatures } from "../features.js";
|
|
10
|
+
import { removeTenantObjects } from "../files/objects.js";
|
|
11
|
+
import { tailQuery } from "../log.js";
|
|
12
|
+
import { forgetTenant, managed } from "../manage.js";
|
|
13
|
+
import { loadedPlugins } from "../plugins/registry.js";
|
|
14
|
+
import { forgetTenantRows, setTenantStatus } from "../tenants/control.js";
|
|
15
|
+
function fromManage(header) {
|
|
16
|
+
const given = Buffer.from(header?.replace(/^Bearer\s+/i, "") ?? "");
|
|
17
|
+
const expected = Buffer.from(env.manage.serviceKey);
|
|
18
|
+
return (managed &&
|
|
19
|
+
expected.length > 0 &&
|
|
20
|
+
given.length === expected.length &&
|
|
21
|
+
timingSafeEqual(given, expected));
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* What the Manage-App tells this runtime about a tenant: suspend, resume, delete. Deleting
|
|
25
|
+
* removes the tenant's files and everything the control database knows; the tenant's database
|
|
26
|
+
* itself is deleted by whoever created it (the Manage-App, or here when it is a file).
|
|
27
|
+
*/
|
|
28
|
+
export const internalRoutes = new Hono()
|
|
29
|
+
.use(async (c, next) => {
|
|
30
|
+
if (!fromManage(c.req.header("authorization"))) {
|
|
31
|
+
return c.json({ error: "unauthorized" }, 401);
|
|
32
|
+
}
|
|
33
|
+
await next();
|
|
34
|
+
})
|
|
35
|
+
// --- a look from afar (docs/plans/remote-debug.md): read-only, never a key -------------
|
|
36
|
+
.get("/debug/status", async (c) => c.json(await status()))
|
|
37
|
+
.get("/debug/logs", (c) => c.json(logs(tailQuery((key) => c.req.query(key)))))
|
|
38
|
+
.get("/debug/runs/:id", async (c) => {
|
|
39
|
+
const found = await runDetail(c.req.param("id"));
|
|
40
|
+
return found ? c.json(found) : c.json({ error: "not found" }, 404);
|
|
41
|
+
})
|
|
42
|
+
.get("/debug/tenants/:id/models", async (c) => {
|
|
43
|
+
const found = await tenantModels(c.req.param("id"));
|
|
44
|
+
return found ? c.json(found) : c.json({ error: "not found" }, 404);
|
|
45
|
+
})
|
|
46
|
+
// The plugins this runtime carries: the Manage-App offers them when a plan's modules are picked.
|
|
47
|
+
.get("/plugins", (c) => {
|
|
48
|
+
return c.json({
|
|
49
|
+
plugins: loadedPlugins().map((p) => ({
|
|
50
|
+
id: p.source.id,
|
|
51
|
+
name: p.source.manifest.name ?? p.source.id,
|
|
52
|
+
description: p.source.manifest.description ?? "",
|
|
53
|
+
version: p.source.manifest.version ?? null,
|
|
54
|
+
})),
|
|
55
|
+
/** Every feature switch this runtime knows: the core's and its plugins' (under their ids). */
|
|
56
|
+
features: declaredFeatures(),
|
|
57
|
+
});
|
|
58
|
+
})
|
|
59
|
+
.post("/tenants/:id", async (c) => {
|
|
60
|
+
const id = c.req.param("id");
|
|
61
|
+
if (!/^[A-Za-z0-9_-]{1,64}$/.test(id)) {
|
|
62
|
+
return c.json({ error: "bad tenant id" }, 400);
|
|
63
|
+
}
|
|
64
|
+
const { action } = z
|
|
65
|
+
.object({ action: z.enum(["suspend", "resume", "delete"]) })
|
|
66
|
+
.parse(await c.req.json());
|
|
67
|
+
forgetTenant(id);
|
|
68
|
+
if (action === "delete") {
|
|
69
|
+
closeTenantDb(id);
|
|
70
|
+
await removeTenantObjects(id);
|
|
71
|
+
await forgetTenantRows(id);
|
|
72
|
+
for (const suffix of ["", "-wal", "-shm"]) {
|
|
73
|
+
await rm(join(env.dataDir, "tenants", `${id}.db${suffix}`), { force: true });
|
|
74
|
+
}
|
|
75
|
+
return c.json({ ok: true });
|
|
76
|
+
}
|
|
77
|
+
// The tenant row exists once its database was opened here.
|
|
78
|
+
await tenantDb(id);
|
|
79
|
+
await setTenantStatus(id, action === "suspend" ? "suspended" : "active");
|
|
80
|
+
return c.json({ ok: true });
|
|
81
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { localLang } from "@engenty-wizards/shared/definition";
|
|
2
|
+
import { serverText } from "../texts.js";
|
|
3
|
+
/**
|
|
4
|
+
* The language a visitor's request asks for, as the studio starts in it (`localLang`): the
|
|
5
|
+
* first of the browser's languages engenty speaks other than English, else English. The
|
|
6
|
+
* browser's `Accept-Language` names them in its order; the server has no time zone to go by.
|
|
7
|
+
*/
|
|
8
|
+
export function requestLang(c) {
|
|
9
|
+
const asked = (c.req.header("accept-language") ?? "")
|
|
10
|
+
.split(",")
|
|
11
|
+
.map((part) => part.split(";")[0]?.trim() ?? "")
|
|
12
|
+
.filter(Boolean);
|
|
13
|
+
return localLang(asked) ?? "en";
|
|
14
|
+
}
|
|
15
|
+
/** A line of the server's table the person reads, in the language their request asks for. */
|
|
16
|
+
export function say(c, key, params) {
|
|
17
|
+
return serverText(requestLang(c), key, params);
|
|
18
|
+
}
|
|
19
|
+
/** A 404 the person may read: a sentence in their language, the machine code beside it. */
|
|
20
|
+
export function notFoundAnswer(c) {
|
|
21
|
+
return {
|
|
22
|
+
error: say(c, "notFound"),
|
|
23
|
+
code: "not_found",
|
|
24
|
+
};
|
|
25
|
+
}
|