@webship.co/workspace 1.0.0-beta1 → 1.0.0-beta2
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 +339 -0
- package/README.md +28 -364
- package/core/bin/workspace.js +135 -0
- package/core/config/settings.labels.yml +514 -0
- package/core/config/settings.template.yml +292 -0
- package/core/config/style.yml +53 -0
- package/core/config/theme.default.yml +161 -0
- package/core/config/theme.dispatch.yml +166 -0
- package/core/config/theme.drupal.yml +175 -0
- package/core/config/theme.ember.yml +160 -0
- package/core/config/theme.github.yml +172 -0
- package/core/config/theme.gitlab.yml +168 -0
- package/core/config/theme.press.yml +161 -0
- package/core/config/theme.slate.yml +160 -0
- package/core/config/theme.upsun.yml +174 -0
- package/core/docs/architecture.svg +65 -0
- package/core/docs/getting-started.md +51 -0
- package/core/docs/plugins.md +27 -0
- package/core/docs/releases.md +23 -0
- package/core/docs/testing.md +15 -0
- package/core/docs/workspaces.md +25 -0
- package/core/scripts/args/arg-ai-items.sh +65 -0
- package/core/scripts/args/arg-autostart.sh +31 -0
- package/core/scripts/args/arg-avatar-agent.sh +28 -0
- package/core/scripts/args/arg-avatar-catalog.sh +12 -0
- package/core/scripts/args/arg-avatar-character.sh +68 -0
- package/core/scripts/args/arg-avatar-voice.sh +24 -0
- package/core/scripts/args/arg-avatar.sh +22 -0
- package/core/scripts/args/arg-checks.sh +36 -0
- package/core/scripts/args/arg-clone.sh +42 -0
- package/core/scripts/args/arg-commands.sh +51 -0
- package/core/scripts/args/arg-cucumber.sh +34 -0
- package/core/scripts/args/arg-distribution.sh +30 -0
- package/core/scripts/args/arg-drupal.sh +39 -0
- package/core/scripts/args/arg-drupal_cms.sh +18 -0
- package/core/scripts/args/arg-gitlab-ci-local.sh +25 -0
- package/core/scripts/args/arg-graphify.sh +36 -0
- package/core/scripts/args/arg-graphs.sh +12 -0
- package/core/scripts/args/arg-hostnames.sh +23 -0
- package/core/scripts/args/arg-milvus-backup.sh +8 -0
- package/core/scripts/args/arg-milvus-mcp.sh +12 -0
- package/core/scripts/args/arg-milvus.sh +32 -0
- package/core/scripts/args/arg-obsidian.sh +17 -0
- package/core/scripts/args/arg-odoo.sh +18 -0
- package/core/scripts/args/arg-penpot-backup.sh +8 -0
- package/core/scripts/args/arg-penpot-mcp.sh +15 -0
- package/core/scripts/args/arg-penpot-token.sh +17 -0
- package/core/scripts/args/arg-penpot.sh +44 -0
- package/core/scripts/args/arg-rag.sh +21 -0
- package/core/scripts/args/arg-ragify.sh +35 -0
- package/core/scripts/args/arg-reclaim.sh +18 -0
- package/core/scripts/args/arg-release.sh +21 -0
- package/core/scripts/args/arg-screen.sh +28 -0
- package/core/scripts/args/arg-site-template.sh +13 -0
- package/core/scripts/args/arg-spdd.sh +16 -0
- package/core/scripts/args/arg-specs.sh +22 -0
- package/core/scripts/args/arg-storage.sh +36 -0
- package/core/scripts/args/arg-testing.sh +36 -0
- package/core/scripts/args/arg-webship.sh +34 -0
- package/core/scripts/args/arg-webships-project.sh +22 -0
- package/core/scripts/args/arg-webships-site-template.sh +17 -0
- package/core/scripts/args/arg-webships.sh +34 -0
- package/core/scripts/args/arg-website-site-template.sh +17 -0
- package/core/scripts/args/arg-website.sh +25 -0
- package/core/scripts/args/arg-wordpress.sh +18 -0
- package/core/scripts/autostart-run.sh +162 -0
- package/core/scripts/autostart-stop.sh +30 -0
- package/core/scripts/autostart-watch.sh +43 -0
- package/core/scripts/autostart.sh +26 -0
- package/core/scripts/bootstrap-functions.sh +117 -0
- package/core/scripts/bootstrap-libraries.sh +10 -0
- package/core/scripts/bootstrap.sh +71 -0
- package/core/scripts/ddev-shim/ddev +122 -0
- package/core/scripts/docker-gid.sh +119 -0
- package/core/scripts/functions/arg-site-template.sh +28 -0
- package/core/scripts/functions/fun-ai-items-lock.sh +175 -0
- package/core/scripts/functions/fun-ai-items-sources.sh +298 -0
- package/core/scripts/functions/fun-ai-items.sh +621 -0
- package/core/scripts/functions/fun-ai-providers.sh +72 -0
- package/core/scripts/functions/fun-autostart.sh +429 -0
- package/core/scripts/functions/fun-avatar.sh +441 -0
- package/core/scripts/functions/fun-backup-item.sh +50 -0
- package/core/scripts/functions/fun-build-distribution.sh +226 -0
- package/core/scripts/functions/fun-build-site-template.sh +104 -0
- package/core/scripts/functions/fun-build-webships.sh +161 -0
- package/core/scripts/functions/fun-build-website.sh +199 -0
- package/core/scripts/functions/fun-checks.sh +243 -0
- package/core/scripts/functions/fun-clone-project.sh +289 -0
- package/core/scripts/functions/fun-commands.sh +521 -0
- package/core/scripts/functions/fun-database.sh +63 -0
- package/core/scripts/functions/fun-ddev-hostnames.sh +213 -0
- package/core/scripts/functions/fun-ddev-nodejs.sh +15 -0
- package/core/scripts/functions/fun-ddev-telemetry.sh +15 -0
- package/core/scripts/functions/fun-default-settings.sh +28 -0
- package/core/scripts/functions/fun-distribution-cucumber.sh +45 -0
- package/core/scripts/functions/fun-distribution-drupal.sh +25 -0
- package/core/scripts/functions/fun-distribution-drupal_cms.sh +35 -0
- package/core/scripts/functions/fun-distribution-webship.sh +28 -0
- package/core/scripts/functions/fun-distribution-webships.sh +33 -0
- package/core/scripts/functions/fun-distribution-website.sh +19 -0
- package/core/scripts/functions/fun-drush.sh +48 -0
- package/core/scripts/functions/fun-elevenlabs.sh +179 -0
- package/core/scripts/functions/fun-files.sh +19 -0
- package/core/scripts/functions/fun-git-worktrees.sh +142 -0
- package/core/scripts/functions/fun-gitlab-ci.sh +156 -0
- package/core/scripts/functions/fun-hostnames-cli.sh +88 -0
- package/core/scripts/functions/fun-milvus.sh +584 -0
- package/core/scripts/functions/fun-odoo.sh +121 -0
- package/core/scripts/functions/fun-penpot.sh +724 -0
- package/core/scripts/functions/fun-project-name.sh +20 -0
- package/core/scripts/functions/fun-rag.sh +253 -0
- package/core/scripts/functions/fun-ragify.sh +165 -0
- package/core/scripts/functions/fun-reclaim.sh +297 -0
- package/core/scripts/functions/fun-release.sh +159 -0
- package/core/scripts/functions/fun-remove-project.sh +319 -0
- package/core/scripts/functions/fun-screen.sh +96 -0
- package/core/scripts/functions/fun-spdd.sh +676 -0
- package/core/scripts/functions/fun-specs-share.sh +237 -0
- package/core/scripts/functions/fun-storage.sh +347 -0
- package/core/scripts/functions/fun-testing.sh +329 -0
- package/core/scripts/functions/fun-users.sh +87 -0
- package/core/scripts/functions/fun-version.sh +72 -0
- package/core/scripts/functions/fun-video-edit.sh +48 -0
- package/core/scripts/functions/fun-voice.sh +45 -0
- package/core/scripts/functions/fun-wordpress.sh +59 -0
- package/core/scripts/host-mounts.sh +161 -0
- package/core/scripts/install.sh +602 -0
- package/core/scripts/libs/__pycache__/video_edit.cpython-312.pyc +0 -0
- package/core/scripts/libs/argparse.sh +93 -0
- package/core/scripts/libs/bash-yaml.sh +52 -0
- package/core/scripts/libs/checks_plan.js +312 -0
- package/core/scripts/libs/elevenlabs.py +627 -0
- package/core/scripts/libs/progress-bar.sh +19 -0
- package/core/scripts/libs/rag_index.py +446 -0
- package/core/scripts/libs/video_edit.py +636 -0
- package/core/scripts/libs/voice.py +430 -0
- package/core/scripts/plugins/jira/host-install.sh +119 -0
- package/core/scripts/plugins/jira/host-mounts.txt +2 -0
- package/core/scripts/plugins/upsun/args/arg-upsun.sh +51 -0
- package/core/scripts/plugins/upsun/functions/fun-upsun.sh +304 -0
- package/core/scripts/plugins/upsun/host-install.sh +99 -0
- package/core/scripts/plugins/upsun/host-mounts.txt +1 -0
- package/core/scripts/plugins/upsun/upsun-ai.sh +133 -0
- package/core/scripts/plugins.sh +152 -0
- package/core/scripts/release.sh +69 -0
- package/core/scripts/storage.sh +39 -0
- package/core/scripts/sync-tooling.sh +246 -0
- package/core/scripts/tests/cmd-smoke-test.sh +109 -0
- package/core/scripts/trust-https.sh +257 -0
- package/core/workspace-app/.ddev/commands/web/test-dashboard +49 -0
- package/core/workspace-app/.ddev/config.yaml +400 -0
- package/core/workspace-app/.ddev/docker-compose.dood.yaml +45 -0
- package/core/workspace-app/.ddev/docker-compose.plugin-jira-twg.yaml +26 -0
- package/core/workspace-app/.ddev/docker-compose.plugin-upsun-upsun-cli.yaml +8 -0
- package/core/workspace-app/.ddev/docker-compose.screens.yaml +15 -0
- package/core/workspace-app/.ddev/nginx_full/nginx-site.conf +114 -0
- package/core/workspace-app/.ddev/web-build/Dockerfile.workspace-app +203 -0
- package/core/workspace-app/.ddev/web-build/ddev-shim-ddev +122 -0
- package/core/workspace-app/README.md +380 -0
- package/{actions → core/workspace-app/actions}/ddev.js +0 -1
- package/{actions → core/workspace-app/actions}/rag.js +0 -1
- package/{actions → core/workspace-app/actions}/testing.js +0 -1
- package/{assistant.js → core/workspace-app/assistant.js} +1 -10
- package/{git-info.js → core/workspace-app/git-info.js} +17 -1
- package/core/workspace-app/package.json +29 -0
- package/core/workspace-app/plugin-catalog.js +50 -0
- package/{plugins-page.js → core/workspace-app/plugins-page.js} +28 -2
- package/{server.js → core/workspace-app/server.js} +18 -0
- package/core/workspace-app/tests/features/actions-rail.feature +44 -0
- package/core/workspace-app/tests/features/ai-items.feature +23 -0
- package/core/workspace-app/tests/features/assistant-speech.feature +63 -0
- package/core/workspace-app/tests/features/checks.feature +39 -0
- package/core/workspace-app/tests/features/clone-project.feature +30 -0
- package/core/workspace-app/tests/features/command-authoring.feature +58 -0
- package/core/workspace-app/tests/features/dashboard.feature +57 -0
- package/core/workspace-app/tests/features/menus.feature +29 -0
- package/core/workspace-app/tests/features/plugins/jira/jira.feature +47 -0
- package/core/workspace-app/tests/features/plugins.feature +20 -0
- package/core/workspace-app/tests/features/project-actions.feature +40 -0
- package/core/workspace-app/tests/features/screens.feature +29 -0
- package/core/workspace-app/tests/features/settings.feature +46 -0
- package/core/workspace-app/tests/features/test-reports.feature +32 -0
- package/core/workspace-app/tests/features/theme.feature +40 -0
- package/core/workspace-app/tests/step-definitions/actions-post.steps.js +25 -0
- package/core/workspace-app/tests/step-definitions/assistant-speech.steps.js +152 -0
- package/core/workspace-app/tests/step-definitions/preconditions.steps.js +100 -0
- package/core/workspace-app/tests/unit/_isolated-config.js +31 -0
- package/core/workspace-app/tests/unit/accessibility.test.js +124 -0
- package/core/workspace-app/tests/unit/actions-rail-ux.test.js +56 -0
- package/core/workspace-app/tests/unit/actions-rail.test.js +51 -0
- package/core/workspace-app/tests/unit/ai-inventory.test.js +64 -0
- package/core/workspace-app/tests/unit/app-docs.test.js +64 -0
- package/core/workspace-app/tests/unit/assistant-avatar.test.js +110 -0
- package/core/workspace-app/tests/unit/assistant-cast.test.js +105 -0
- package/core/workspace-app/tests/unit/assistant-send-animation.test.js +15 -0
- package/core/workspace-app/tests/unit/assistant-suggestions.test.js +112 -0
- package/core/workspace-app/tests/unit/assistant-switches.test.js +53 -0
- package/core/workspace-app/tests/unit/assistant-views.test.js +146 -0
- package/core/workspace-app/tests/unit/assistant-working-indicator.test.js +49 -0
- package/core/workspace-app/tests/unit/assistant.test.js +61 -0
- package/core/workspace-app/tests/unit/audio-player.test.js +147 -0
- package/core/workspace-app/tests/unit/audio-voice.test.js +634 -0
- package/core/workspace-app/tests/unit/auth-google.test.js +180 -0
- package/core/workspace-app/tests/unit/autostart-watch.test.js +76 -0
- package/core/workspace-app/tests/unit/browsers.test.js +76 -0
- package/core/workspace-app/tests/unit/build-distribution.test.js +125 -0
- package/core/workspace-app/tests/unit/build-order.test.js +153 -0
- package/core/workspace-app/tests/unit/builder-args.test.js +113 -0
- package/core/workspace-app/tests/unit/builders.test.js +158 -0
- package/core/workspace-app/tests/unit/card-state-toggle.test.js +29 -0
- package/core/workspace-app/tests/unit/changelog.test.js +177 -0
- package/core/workspace-app/tests/unit/chat-thread.test.js +92 -0
- package/core/workspace-app/tests/unit/checks-plan.test.js +205 -0
- package/core/workspace-app/tests/unit/claude-args.test.js +182 -0
- package/core/workspace-app/tests/unit/claude-code-here.test.js +15 -0
- package/core/workspace-app/tests/unit/claude-resume.test.js +147 -0
- package/core/workspace-app/tests/unit/claude-screen-options.test.js +84 -0
- package/core/workspace-app/tests/unit/claude-session.test.js +41 -0
- package/core/workspace-app/tests/unit/command-flags.test.js +45 -0
- package/core/workspace-app/tests/unit/command-palette.test.js +105 -0
- package/core/workspace-app/tests/unit/commands-center.test.js +338 -0
- package/core/workspace-app/tests/unit/composer-menu.test.js +187 -0
- package/core/workspace-app/tests/unit/config-yaml.test.js +116 -0
- package/core/workspace-app/tests/unit/confirm-dialog.test.js +69 -0
- package/core/workspace-app/tests/unit/create-card.test.js +85 -0
- package/core/workspace-app/tests/unit/ddev-addons.test.js +144 -0
- package/core/workspace-app/tests/unit/ddev-auth-ssh.test.js +40 -0
- package/core/workspace-app/tests/unit/ddev-custom-commands.test.js +56 -0
- package/core/workspace-app/tests/unit/ddev-diagnose.test.js +57 -0
- package/core/workspace-app/tests/unit/ddev-domains.test.js +153 -0
- package/core/workspace-app/tests/unit/ddev-hostnames.test.js +143 -0
- package/core/workspace-app/tests/unit/ddev-import.test.js +82 -0
- package/core/workspace-app/tests/unit/ddev-mail.test.js +135 -0
- package/core/workspace-app/tests/unit/ddev-menu-and-create.test.js +28 -0
- package/core/workspace-app/tests/unit/ddev-mutagen.test.js +37 -0
- package/core/workspace-app/tests/unit/ddev-options.test.js +51 -0
- package/core/workspace-app/tests/unit/ddev-share.test.js +40 -0
- package/core/workspace-app/tests/unit/ddev-shim.test.js +57 -0
- package/core/workspace-app/tests/unit/ddev-snapshots.test.js +142 -0
- package/core/workspace-app/tests/unit/ddev-start-daemons.test.js +62 -0
- package/core/workspace-app/tests/unit/ddev-xdebug.test.js +41 -0
- package/core/workspace-app/tests/unit/deep-chat-origin.test.js +38 -0
- package/core/workspace-app/tests/unit/density.test.js +52 -0
- package/core/workspace-app/tests/unit/elevenlabs.test.js +453 -0
- package/core/workspace-app/tests/unit/event-log.test.js +102 -0
- package/core/workspace-app/tests/unit/favicon.test.js +68 -0
- package/core/workspace-app/tests/unit/files-browser.test.js +224 -0
- package/core/workspace-app/tests/unit/git-info.test.js +26 -0
- package/core/workspace-app/tests/unit/grid-and-list.test.js +103 -0
- package/core/workspace-app/tests/unit/host-tool-wrapper.test.js +18 -0
- package/core/workspace-app/tests/unit/html-patterns.test.js +51 -0
- package/core/workspace-app/tests/unit/ide-infra.test.js +28 -0
- package/core/workspace-app/tests/unit/images-ai.test.js +201 -0
- package/core/workspace-app/tests/unit/images-create.test.js +59 -0
- package/core/workspace-app/tests/unit/images-providers.test.js +248 -0
- package/core/workspace-app/tests/unit/images-svg.test.js +213 -0
- package/core/workspace-app/tests/unit/images-workspace.test.js +144 -0
- package/core/workspace-app/tests/unit/jobs-fragment.test.js +66 -0
- package/core/workspace-app/tests/unit/media-ux.test.js +164 -0
- package/core/workspace-app/tests/unit/modal-fit.test.js +87 -0
- package/core/workspace-app/tests/unit/modules-load.test.js +23 -0
- package/core/workspace-app/tests/unit/narration.test.js +186 -0
- package/core/workspace-app/tests/unit/navigation-editor.test.js +260 -0
- package/core/workspace-app/tests/unit/navigation.test.js +254 -0
- package/core/workspace-app/tests/unit/new-folder.test.js +121 -0
- package/core/workspace-app/tests/unit/new-screen-form.test.js +149 -0
- package/core/workspace-app/tests/unit/node-menu.test.js +161 -0
- package/core/workspace-app/tests/unit/notes.test.js +128 -0
- package/core/workspace-app/tests/unit/page-structure.test.js +40 -0
- package/core/workspace-app/tests/unit/page-width.test.js +59 -0
- package/core/workspace-app/tests/unit/php-version.test.js +90 -0
- package/core/workspace-app/tests/unit/plan-card.test.js +44 -0
- package/core/workspace-app/tests/unit/plugin-catalog.test.js +31 -0
- package/core/workspace-app/tests/unit/plugin-system.test.js +251 -0
- package/core/workspace-app/tests/unit/plugins-page.test.js +28 -0
- package/core/workspace-app/tests/unit/plugins.test.js +58 -0
- package/core/workspace-app/tests/unit/project-activity-filter.test.js +180 -0
- package/core/workspace-app/tests/unit/project-make.test.js +143 -0
- package/core/workspace-app/tests/unit/project-name.test.js +202 -0
- package/core/workspace-app/tests/unit/reader.test.js +62 -0
- package/core/workspace-app/tests/unit/release.test.js +92 -0
- package/core/workspace-app/tests/unit/remove-confirm.test.js +37 -0
- package/core/workspace-app/tests/unit/report-pdf.test.js +171 -0
- package/core/workspace-app/tests/unit/round-11.test.js +31 -0
- package/core/workspace-app/tests/unit/round-12.test.js +37 -0
- package/core/workspace-app/tests/unit/row-layout.test.js +585 -0
- package/core/workspace-app/tests/unit/row-menus-fold.test.js +29 -0
- package/core/workspace-app/tests/unit/rows-add-modal.test.js +68 -0
- package/core/workspace-app/tests/unit/screen-runner-queue.test.js +41 -0
- package/core/workspace-app/tests/unit/screen-window.test.js +116 -0
- package/core/workspace-app/tests/unit/screens-beside-running.test.js +19 -0
- package/core/workspace-app/tests/unit/screens-columns.test.js +79 -0
- package/core/workspace-app/tests/unit/screens-menu.test.js +84 -0
- package/core/workspace-app/tests/unit/screens-modal-overlay.test.js +14 -0
- package/core/workspace-app/tests/unit/screens-waiting.test.js +129 -0
- package/core/workspace-app/tests/unit/screens.test.js +74 -0
- package/core/workspace-app/tests/unit/second-storage.test.js +218 -0
- package/core/workspace-app/tests/unit/session-name.test.js +64 -0
- package/core/workspace-app/tests/unit/settings-file.test.js +173 -0
- package/core/workspace-app/tests/unit/settings-nested-list.test.js +54 -0
- package/core/workspace-app/tests/unit/settings-raw.test.js +177 -0
- package/core/workspace-app/tests/unit/shared-prefs.test.js +49 -0
- package/core/workspace-app/tests/unit/speech.test.js +290 -0
- package/core/workspace-app/tests/unit/static-caching.test.js +39 -0
- package/core/workspace-app/tests/unit/status-language.test.js +47 -0
- package/core/workspace-app/tests/unit/tab-modal.test.js +69 -0
- package/core/workspace-app/tests/unit/tab-title.test.js +37 -0
- package/core/workspace-app/tests/unit/template-literals.test.js +52 -0
- package/core/workspace-app/tests/unit/terminal-scrollback.test.js +61 -0
- package/core/workspace-app/tests/unit/terminal-size.test.js +103 -0
- package/core/workspace-app/tests/unit/terminal-style.test.js +84 -0
- package/core/workspace-app/tests/unit/terminal-windows.test.js +154 -0
- package/core/workspace-app/tests/unit/themes.test.js +453 -0
- package/core/workspace-app/tests/unit/tool-labels.test.js +34 -0
- package/core/workspace-app/tests/unit/topbar-icons.test.js +47 -0
- package/core/workspace-app/tests/unit/update-docker-gid.test.js +51 -0
- package/core/workspace-app/tests/unit/user-guide.test.js +60 -0
- package/core/workspace-app/tests/unit/version-check.test.js +98 -0
- package/core/workspace-app/tests/unit/version-link.test.js +50 -0
- package/core/workspace-app/tests/unit/video-borrow.test.js +198 -0
- package/core/workspace-app/tests/unit/video-edit-ask.test.js +93 -0
- package/core/workspace-app/tests/unit/video-edit-short.test.js +42 -0
- package/core/workspace-app/tests/unit/video-edit.test.js +417 -0
- package/core/workspace-app/tests/unit/video-transcript.test.js +237 -0
- package/core/workspace-app/tests/unit/waiting.test.js +48 -0
- package/core/workspace-app/tests/unit/wordpress-odoo-builders.test.js +38 -0
- package/core/workspace-app/tests/unit/workspace-bin.test.js +48 -0
- package/core/workspace-app/tests/unit/workspace-card-tools.test.js +30 -0
- package/core/workspace-app/tests/unit/workspace-delete.test.js +77 -0
- package/core/workspace-app/tests/unit/workspace-types.test.js +68 -0
- package/core/workspace-app/tests/unit/worktree-clone.test.js +250 -0
- package/package.json +38 -36
- /package/{PLUGINS.md → core/workspace-app/PLUGINS.md} +0 -0
- /package/{WORKSPACES.md → core/workspace-app/WORKSPACES.md} +0 -0
- /package/{actions → core/workspace-app/actions}/ai-items.js +0 -0
- /package/{actions → core/workspace-app/actions}/audio.js +0 -0
- /package/{actions → core/workspace-app/actions}/build-order.js +0 -0
- /package/{actions → core/workspace-app/actions}/checks.js +0 -0
- /package/{actions → core/workspace-app/actions}/claude-session.js +0 -0
- /package/{actions → core/workspace-app/actions}/commands-center.js +0 -0
- /package/{actions → core/workspace-app/actions}/composer.js +0 -0
- /package/{actions → core/workspace-app/actions}/ddev-addons.js +0 -0
- /package/{actions → core/workspace-app/actions}/ddev-mail.js +0 -0
- /package/{actions → core/workspace-app/actions}/folders.js +0 -0
- /package/{actions → core/workspace-app/actions}/images-svg.js +0 -0
- /package/{actions → core/workspace-app/actions}/images.js +0 -0
- /package/{actions → core/workspace-app/actions}/navigation.js +0 -0
- /package/{actions → core/workspace-app/actions}/node.js +0 -0
- /package/{actions → core/workspace-app/actions}/notes.js +0 -0
- /package/{actions → core/workspace-app/actions}/plugins.js +0 -0
- /package/{actions → core/workspace-app/actions}/project-make.js +0 -0
- /package/{actions → core/workspace-app/actions}/row-actions.js +0 -0
- /package/{actions → core/workspace-app/actions}/screens.js +0 -0
- /package/{actions → core/workspace-app/actions}/video-edit.js +0 -0
- /package/{ai-inventory.js → core/workspace-app/ai-inventory.js} +0 -0
- /package/{ai-items.js → core/workspace-app/ai-items.js} +0 -0
- /package/{assistant-cast.js → core/workspace-app/assistant-cast.js} +0 -0
- /package/{assistant-suggestions.js → core/workspace-app/assistant-suggestions.js} +0 -0
- /package/{audio-voice.js → core/workspace-app/audio-voice.js} +0 -0
- /package/{auth-google.js → core/workspace-app/auth-google.js} +0 -0
- /package/{build-ai.js → core/workspace-app/build-ai.js} +0 -0
- /package/{build-order-page.js → core/workspace-app/build-order-page.js} +0 -0
- /package/{build-order.js → core/workspace-app/build-order.js} +0 -0
- /package/{builder-args.js → core/workspace-app/builder-args.js} +0 -0
- /package/{changelog.js → core/workspace-app/changelog.js} +0 -0
- /package/{chat-threads.js → core/workspace-app/chat-threads.js} +0 -0
- /package/{checks.js → core/workspace-app/checks.js} +0 -0
- /package/{claude-args.js → core/workspace-app/claude-args.js} +0 -0
- /package/{claude-sessions.js → core/workspace-app/claude-sessions.js} +0 -0
- /package/{command-author.js → core/workspace-app/command-author.js} +0 -0
- /package/{command-block.js → core/workspace-app/command-block.js} +0 -0
- /package/{commands → core/workspace-app/commands}/defaults.yml +0 -0
- /package/{commands-page.js → core/workspace-app/commands-page.js} +0 -0
- /package/{commands.js → core/workspace-app/commands.js} +0 -0
- /package/{cucumber.js → core/workspace-app/cucumber.js} +0 -0
- /package/{ddev-addons-page.js → core/workspace-app/ddev-addons-page.js} +0 -0
- /package/{ddev-addons.js → core/workspace-app/ddev-addons.js} +0 -0
- /package/{ddev-custom-commands.js → core/workspace-app/ddev-custom-commands.js} +0 -0
- /package/{ddev-domains.js → core/workspace-app/ddev-domains.js} +0 -0
- /package/{ddev-import.js → core/workspace-app/ddev-import.js} +0 -0
- /package/{ddev-mail-page.js → core/workspace-app/ddev-mail-page.js} +0 -0
- /package/{ddev-mail.js → core/workspace-app/ddev-mail.js} +0 -0
- /package/{ddev-options.js → core/workspace-app/ddev-options.js} +0 -0
- /package/{ddev-snapshots.js → core/workspace-app/ddev-snapshots.js} +0 -0
- /package/{ddev.js → core/workspace-app/ddev.js} +0 -0
- /package/{docs → core/workspace-app/docs}/DEVELOPER-GUIDE.md +0 -0
- /package/{docs → core/workspace-app/docs}/README.md +0 -0
- /package/{docs → core/workspace-app/docs}/REFERENCE.md +0 -0
- /package/{docs → core/workspace-app/docs}/USER-GUIDE.md +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-board.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-coffee.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-colours.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-icons.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-moves.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-pick-cookieman.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-settings-voices.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/assistant/avatar-status.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/create-card/create-card.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/create-card/start-ai.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-clone-address.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-clone-worktree-off.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-clone-worktree-on.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-ddev-menu.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-domains.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-home.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-ide-menu.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-remove-refusal.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-rows-worktree.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-screens.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-settings.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/guide-workspace-page.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/home/card-settings.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/home/drag-reorder.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/home/edit-card.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/images/claude-code-image.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/images/edit-with-ai.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/images/gallery.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/images/generate-description.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/images/generate-plan.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/images/providers.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/images/svg-form.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/images/svg-result.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/images/upload.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/new-folder/2-form.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/new-folder/8-ddev-options.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/new-folder/files-folder.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/projects/ddev-custom-commands.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/projects/state-chip-stop.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/dashboard-dark.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/dashboard-light.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/dev-dark.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/dev-light.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/docs-dark.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/docs-light.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/icons/ai.svg +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/icons/code.svg +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/icons/docs.svg +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/icons/services.svg +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/icons/sites.svg +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/test-report-dark.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/test-report-light.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/test-scenarios.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/test-steps.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/videos-dark.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/readme/videos-light.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/screens-menu.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/screens-new.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/settings/auth-google-lists.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/settings/delete-1-row.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/settings/delete-2-confirm.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/settings/delete-3-type-name.png +0 -0
- /package/{docs → core/workspace-app/docs}/screenshots/settings/delete-4-type-yes.png +0 -0
- /package/{event-log.js → core/workspace-app/event-log.js} +0 -0
- /package/{files-browser.js → core/workspace-app/files-browser.js} +0 -0
- /package/{folders.js → core/workspace-app/folders.js} +0 -0
- /package/{format.js → core/workspace-app/format.js} +0 -0
- /package/{github-auth.js → core/workspace-app/github-auth.js} +0 -0
- /package/{html.js → core/workspace-app/html.js} +0 -0
- /package/{icons.js → core/workspace-app/icons.js} +0 -0
- /package/{images-ai.js → core/workspace-app/images-ai.js} +0 -0
- /package/{images-create.js → core/workspace-app/images-create.js} +0 -0
- /package/{images-page.js → core/workspace-app/images-page.js} +0 -0
- /package/{images-records.js → core/workspace-app/images-records.js} +0 -0
- /package/{images-render.js → core/workspace-app/images-render.js} +0 -0
- /package/{images-svg-core.js → core/workspace-app/images-svg-core.js} +0 -0
- /package/{images-svg-sanitize.js → core/workspace-app/images-svg-sanitize.js} +0 -0
- /package/{images-svg.js → core/workspace-app/images-svg.js} +0 -0
- /package/{images.js → core/workspace-app/images.js} +0 -0
- /package/{jobs.js → core/workspace-app/jobs.js} +0 -0
- /package/{linger.js → core/workspace-app/linger.js} +0 -0
- /package/{lists.js → core/workspace-app/lists.js} +0 -0
- /package/{media-info.js → core/workspace-app/media-info.js} +0 -0
- /package/{navigation-page.js → core/workspace-app/navigation-page.js} +0 -0
- /package/{navigation.js → core/workspace-app/navigation.js} +0 -0
- /package/{notes.js → core/workspace-app/notes.js} +0 -0
- /package/{palette-index.js → core/workspace-app/palette-index.js} +0 -0
- /package/{playwright.config.js → core/workspace-app/playwright.config.js} +0 -0
- /package/{plugin-install.js → core/workspace-app/plugin-install.js} +0 -0
- /package/{plugin-loader.js → core/workspace-app/plugin-loader.js} +0 -0
- /package/{plugin-manifest.js → core/workspace-app/plugin-manifest.js} +0 -0
- /package/{plugin-settings.js → core/workspace-app/plugin-settings.js} +0 -0
- /package/{plugins → core/workspace-app/plugins}/workspace-notes/index.js +0 -0
- /package/{project-make.js → core/workspace-app/project-make.js} +0 -0
- /package/{project-name.js → core/workspace-app/project-name.js} +0 -0
- /package/{public → core/workspace-app/public}/assistant-avatar-moves.js +0 -0
- /package/{public → core/workspace-app/public}/assistant-avatar-ui.js +0 -0
- /package/{public → core/workspace-app/public}/assistant-avatar.js +0 -0
- /package/{public → core/workspace-app/public}/avatar/druplicon.vrm +0 -0
- /package/{public → core/workspace-app/public}/css/base.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/ai-assistant.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/assistant-avatar.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/assistant-views.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/build-order.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/clone-as-a-git-worktree.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/command-palette.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/commands-center.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/confirm-dialog.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/create-card.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/ddev-menu.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/deep-chat.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/density.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/floating-assistant-workspace-pages.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/folders.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/full-height-left-assistant-sidebar-all-pages.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/full-height-right-actions-rail-pages-that-have-actions.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/grid-and-list.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/help-page.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/hero.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/images.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/layout-rhythm-and-spacing-polish.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/mic-on-any-field-that-wants-typing.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/modal-fit.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/page-width.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/plugins-page.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/project-cards.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/project-rows.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/reordering-the-workspace-cards.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/responsive-home-and-the-workspace-pages.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/running-commands-as-toasts.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/settings-editor-core-config-yml.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/short-results-as-a-toast-at-the-top.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/sound-player.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/suggest-agents-skills-commands.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/tab-modal.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/terminals.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/test-report-media-one-file-per-row-paged.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/top-toolbar-logo-breadcrumb.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/video-edit.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/web-ide-open-with.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/working-indicators.css +0 -0
- /package/{public → core/workspace-app/public}/css/components/workspace-cards.css +0 -0
- /package/{public → core/workspace-app/public}/favicon.ico +0 -0
- /package/{public → core/workspace-app/public}/favicon.png +0 -0
- /package/{public → core/workspace-app/public}/htmx.min.js +0 -0
- /package/{public → core/workspace-app/public}/logo.png +0 -0
- /package/{public → core/workspace-app/public}/media-player.js +0 -0
- /package/{public → core/workspace-app/public}/mic.js +0 -0
- /package/{public → core/workspace-app/public}/narration.js +0 -0
- /package/{public → core/workspace-app/public}/palette.js +0 -0
- /package/{public → core/workspace-app/public}/sortable.js +0 -0
- /package/{public → core/workspace-app/public}/suggest.js +0 -0
- /package/{public → core/workspace-app/public}/terminal.js +0 -0
- /package/{public → core/workspace-app/public}/themes/default/theme.css +0 -0
- /package/{public → core/workspace-app/public}/themes/ember/theme.css +0 -0
- /package/{public → core/workspace-app/public}/themes/press/theme.css +0 -0
- /package/{public → core/workspace-app/public}/themes/slate/theme.css +0 -0
- /package/{public → core/workspace-app/public}/touch-icon.png +0 -0
- /package/{public → core/workspace-app/public}/ui.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/LICENSE.txt +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/ace.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/ext-language_tools.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/ext-searchbox.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/mode-css.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/mode-html.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/mode-javascript.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/mode-markdown.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/mode-sh.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/mode-yaml.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/theme-textmate.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/theme-tomorrow_night.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/ace/worker-yaml.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/deep-chat.LICENSE +0 -0
- /package/{public → core/workspace-app/public}/vendor/deep-chat.bundle.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/dm-serif-text-LICENSE.txt +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/dm-serif-text-latin-400-italic.woff2 +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/dm-serif-text-latin-400-normal.woff2 +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/figtree-LICENSE.txt +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/figtree-latin-400-italic.woff2 +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/figtree-latin-400-normal.woff2 +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/figtree-latin-600-italic.woff2 +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/figtree-latin-600-normal.woff2 +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/jetbrains-mono-LICENSE.txt +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/jetbrains-mono-latin-400-normal.woff2 +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/ubuntu-mono-LICENSE.txt +0 -0
- /package/{public → core/workspace-app/public}/vendor/fonts/ubuntu-mono-latin-wght-normal.woff2 +0 -0
- /package/{public → core/workspace-app/public}/vendor/tabler-LICENSE.txt +0 -0
- /package/{public → core/workspace-app/public}/vendor/tabler-sprite.svg +0 -0
- /package/{public → core/workspace-app/public}/vendor/three/LICENSE +0 -0
- /package/{public → core/workspace-app/public}/vendor/three/addons/loaders/GLTFLoader.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/three/addons/utils/BufferGeometryUtils.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/three/addons/utils/SkeletonUtils.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/three/three.core.min.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/three/three.module.min.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/three-vrm/LICENSE +0 -0
- /package/{public → core/workspace-app/public}/vendor/three-vrm/three-vrm.module.min.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/uikit-icons.min.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/uikit.min.css +0 -0
- /package/{public → core/workspace-app/public}/vendor/uikit.min.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/bookmark-outlined.svg +0 -0
- /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/headset.svg +0 -0
- /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/menu.svg +0 -0
- /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/pause.svg +0 -0
- /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/play.svg +0 -0
- /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/share.svg +0 -0
- /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/sound-off.svg +0 -0
- /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/sound-on.svg +0 -0
- /package/{public → core/workspace-app/public}/vendor/webship-icons/ui/stop.svg +0 -0
- /package/{public → core/workspace-app/public}/vendor/xterm/addon-fit.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/xterm/addon-unicode11.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/xterm/addon-web-links.js +0 -0
- /package/{public → core/workspace-app/public}/vendor/xterm/xterm.css +0 -0
- /package/{public → core/workspace-app/public}/vendor/xterm/xterm.js +0 -0
- /package/{rag.js → core/workspace-app/rag.js} +0 -0
- /package/{reader.js → core/workspace-app/reader.js} +0 -0
- /package/{repo-blobs.js → core/workspace-app/repo-blobs.js} +0 -0
- /package/{report-pdf.js → core/workspace-app/report-pdf.js} +0 -0
- /package/{row-layout.js → core/workspace-app/row-layout.js} +0 -0
- /package/{screenrc → core/workspace-app/screenrc} +0 -0
- /package/{screens.js → core/workspace-app/screens.js} +0 -0
- /package/{scripts → core/workspace-app/scripts}/code-server-start.sh +0 -0
- /package/{scripts → core/workspace-app/scripts}/images-claude-finish.js +0 -0
- /package/{scripts → core/workspace-app/scripts}/screen-host.sh +0 -0
- /package/{scripts → core/workspace-app/scripts}/screen-runner.js +0 -0
- /package/{scripts → core/workspace-app/scripts}/screen-then.js +0 -0
- /package/{scripts → core/workspace-app/scripts}/update.sh +0 -0
- /package/{settings-file.js → core/workspace-app/settings-file.js} +0 -0
- /package/{speech.js → core/workspace-app/speech.js} +0 -0
- /package/{tab-modal.js → core/workspace-app/tab-modal.js} +0 -0
- /package/{test-reports.js → core/workspace-app/test-reports.js} +0 -0
- /package/{themes.js → core/workspace-app/themes.js} +0 -0
- /package/{transcripts.js → core/workspace-app/transcripts.js} +0 -0
- /package/{urls.js → core/workspace-app/urls.js} +0 -0
- /package/{validate.js → core/workspace-app/validate.js} +0 -0
- /package/{version-check.js → core/workspace-app/version-check.js} +0 -0
- /package/{video-edit.js → core/workspace-app/video-edit.js} +0 -0
- /package/{waiting.js → core/workspace-app/waiting.js} +0 -0
- /package/{workspace-card-tools.js → core/workspace-app/workspace-card-tools.js} +0 -0
- /package/{workspace-delete.js → core/workspace-app/workspace-delete.js} +0 -0
- /package/{workspace-types.js → core/workspace-app/workspace-types.js} +0 -0
- /package/{workspaces.js → core/workspace-app/workspaces.js} +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# AI provider keys for the sites this workspace builds.
|
|
4
|
+
#
|
|
5
|
+
# settings.yml carries an `ai_providers:` map (openai, anthropic, gemini, …)
|
|
6
|
+
# that parse_yaml flattens into $ai_providers_<provider>_api_key. The committed
|
|
7
|
+
# file ships placeholders; a developer's real keys live only in their own
|
|
8
|
+
# checkout. These helpers push those keys into an installed Drupal site that
|
|
9
|
+
# carries the AI stack (Drupal CMS AI, Webship AI), so "build me a Drupal CMS
|
|
10
|
+
# site with AI working" is one command instead of console clicking.
|
|
11
|
+
|
|
12
|
+
# A value counts as configured only when it is non-empty and not a placeholder.
|
|
13
|
+
function ai_provider_key_is_real() {
|
|
14
|
+
case "$1" in
|
|
15
|
+
''|CHANGE_ME|sk-change-this) return 1 ;;
|
|
16
|
+
*) return 0 ;;
|
|
17
|
+
esac
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
# Store one provider key on the installed site and point the AI provider
|
|
21
|
+
# module at it. Uses the Key module (how Drupal CMS AI stores secrets):
|
|
22
|
+
# a `key` config entity holds the value, and ai_provider_<name>.settings
|
|
23
|
+
# references it by id. Runs inside the project's DDEV containers only.
|
|
24
|
+
#
|
|
25
|
+
# set_one_ai_provider_key <provider> <api_key>
|
|
26
|
+
function set_one_ai_provider_key() {
|
|
27
|
+
local provider="$1";
|
|
28
|
+
local api_key="$2";
|
|
29
|
+
local module="ai_provider_${provider}";
|
|
30
|
+
|
|
31
|
+
if ! ddev drush pm:list --field=name --status=enabled 2>/dev/null | grep -qx "${module}" ; then
|
|
32
|
+
echo " ${module} is not enabled — skipping the ${provider} key." ;
|
|
33
|
+
return 0 ;
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# The Key entity. The value travels on STDIN, so it never appears in a
|
|
37
|
+
# command line, shell history, or process list.
|
|
38
|
+
printf '%s' "${api_key}" | ddev drush php:eval "
|
|
39
|
+
\$value = trim(file_get_contents('php://stdin'));
|
|
40
|
+
\$storage = \Drupal::entityTypeManager()->getStorage('key');
|
|
41
|
+
\$id = '${provider}_api_key';
|
|
42
|
+
\$key = \$storage->load(\$id) ?: \$storage->create(['id' => \$id, 'label' => '${provider} API key', 'key_type' => 'authentication']);
|
|
43
|
+
\$key->set('key_provider', 'config');
|
|
44
|
+
\$key->set('key_provider_settings', ['key_value' => \$value]);
|
|
45
|
+
\$key->save();
|
|
46
|
+
" || return 1 ;
|
|
47
|
+
|
|
48
|
+
ddev drush -y config:set "${module}.settings" api_key "${provider}_api_key" || return 1 ;
|
|
49
|
+
echo " ${provider}: key stored and wired to ${module}." ;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
# Wire every configured provider into the current project's site. Call it
|
|
53
|
+
# after install, from the project directory (like enable_*_extra_components).
|
|
54
|
+
# Quietly does nothing when the site has no AI stack or no real keys are set.
|
|
55
|
+
function set_ai_provider_keys() {
|
|
56
|
+
if ! ddev drush pm:list --field=name --status=enabled 2>/dev/null | grep -qx "key" ; then
|
|
57
|
+
echo "No Key module on this site — skipping AI provider keys." ;
|
|
58
|
+
return 0 ;
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
echo "Wiring AI provider keys from settings.yml (placeholders are skipped).";
|
|
62
|
+
|
|
63
|
+
if ai_provider_key_is_real "${ai_providers_openai_api_key}" ; then
|
|
64
|
+
set_one_ai_provider_key "openai" "${ai_providers_openai_api_key}" ;
|
|
65
|
+
fi
|
|
66
|
+
if ai_provider_key_is_real "${ai_providers_anthropic_api_key}" ; then
|
|
67
|
+
set_one_ai_provider_key "anthropic" "${ai_providers_anthropic_api_key}" ;
|
|
68
|
+
fi
|
|
69
|
+
if ai_provider_key_is_real "${ai_providers_gemini_api_key}" ; then
|
|
70
|
+
set_one_ai_provider_key "gemini" "${ai_providers_gemini_api_key}" ;
|
|
71
|
+
fi
|
|
72
|
+
}
|
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# The dashboard's own hostname, and getting it back after a reboot.
|
|
4
|
+
#
|
|
5
|
+
# Two problems that look like one. A DDEV project's containers carry `restart: no`, so nothing brings
|
|
6
|
+
# the dashboard back when the machine boots or when Docker restarts — `ddev describe` says `exited`
|
|
7
|
+
# and every workspace URL answers 404 from a router with nothing behind it. And a project answers only
|
|
8
|
+
# on the names DDEV knows about, so a name of your own choosing has to be given to it.
|
|
9
|
+
#
|
|
10
|
+
# WHY NOT A DOCKER RESTART POLICY. Setting `restart: unless-stopped` on the containers looks like the
|
|
11
|
+
# smaller fix and is the wrong one: DDEV rebuilds its containers on `ddev start` and pushes fresh
|
|
12
|
+
# router config each time, so a container resurrected behind DDEV's back comes up without a router
|
|
13
|
+
# entry and answers nothing. The supported way in is `ddev start`, so that is what runs at boot.
|
|
14
|
+
#
|
|
15
|
+
# A **user** service, not a system one. The projects live under $HOME, the Docker socket is reached
|
|
16
|
+
# with this user's group membership, and `ddev` reads ~/.ddev. A root unit would start them as the
|
|
17
|
+
# wrong user and strand every volume. Lingering (`loginctl enable-linger`) is what makes a user
|
|
18
|
+
# service run at BOOT rather than at first login — without it the dashboard would only appear once
|
|
19
|
+
# somebody signs in, which defeats the point.
|
|
20
|
+
|
|
21
|
+
readonly AUTOSTART_UNIT_NAME="webship-workspace.service";
|
|
22
|
+
readonly AUTOSTART_UNIT_DIR="${HOME}/.config/systemd/user";
|
|
23
|
+
readonly AUTOSTART_RUNNER="${WORKSPACE_SCRIPTS}/autostart-run.sh";
|
|
24
|
+
readonly AUTOSTART_RECORDER="${WORKSPACE_SCRIPTS}/autostart-stop.sh";
|
|
25
|
+
readonly AUTOSTART_WATCHER="${WORKSPACE_SCRIPTS}/autostart-watch.sh";
|
|
26
|
+
readonly AUTOSTART_WATCH_NAME="webship-workspace-watch";
|
|
27
|
+
|
|
28
|
+
# The dashboard's own DDEV project. Everything else in the tree is a site; this one is the way in.
|
|
29
|
+
function autostart_app_path() {
|
|
30
|
+
printf '%s' "${WORKSPACE_PATH}/workspace-app";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
# Which projects the boot service starts, resolved. Asks the runner rather than re-deriving it: the
|
|
34
|
+
# setting is a small vocabulary (`workspace`, `running`, `all`, or literal names) and a second copy of
|
|
35
|
+
# that logic here would drift from the one that actually runs at boot.
|
|
36
|
+
function autostart_projects() {
|
|
37
|
+
bash "${AUTOSTART_RUNNER}" --list 2>/dev/null ;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# The one name the dashboard answers on, as `<project>.<tld>`.
|
|
41
|
+
#
|
|
42
|
+
# `hub_domain`, the key the app ALREADY uses — workspaces.js reads it for every URL it builds, and
|
|
43
|
+
# urls.js derives the whole scheme from it. A second key here would be the same fact stored twice:
|
|
44
|
+
# set one, and the dashboard's links and DDEV's routing would disagree about where the site is. So
|
|
45
|
+
# this command reads and writes that one, and its job is to make DDEV agree with it.
|
|
46
|
+
function autostart_domain() {
|
|
47
|
+
printf '%s' "${hub_domain:-workspace.ddev.site}";
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# Rewrite one `key: value` line in the dashboard block of the settings file, in place.
|
|
51
|
+
#
|
|
52
|
+
# In place, and only that line: this file holds the real account password and the API keys on a live
|
|
53
|
+
# machine, it is never synced or committed, and a regenerating writer would reformat around secrets it
|
|
54
|
+
# has no business touching. One sed on one key is the whole edit.
|
|
55
|
+
function autostart_settings_write() {
|
|
56
|
+
local key="$1" value="$2" file="${WORKSPACE_CONFIG}/settings.yml";
|
|
57
|
+
[ -f "${file}" ] || { echo "No ${file}."; return 1 ; }
|
|
58
|
+
|
|
59
|
+
# Two shapes, because the two keys live at different levels: hub_domain is top-level (the app has
|
|
60
|
+
# always read it there), autostart is nested under dashboard:.
|
|
61
|
+
#
|
|
62
|
+
# Written UNQUOTED and at two spaces, because that is what every other value in this file does.
|
|
63
|
+
# parse_yaml strips quotes either way, so quoting was never a correctness question — it just left
|
|
64
|
+
# one block looking unlike the file it lives in, which is how a hand-edit later gets it wrong.
|
|
65
|
+
case "${key}" in
|
|
66
|
+
hub_domain)
|
|
67
|
+
if grep -qE "^${key}:" "${file}" ; then
|
|
68
|
+
# `#` as the sed delimiter: `|` and `/` both appear in things people paste here.
|
|
69
|
+
sed -i -E "s#^${key}:.*#${key}: ${value}#" "${file}" ;
|
|
70
|
+
else
|
|
71
|
+
printf '\n# The base domain every dashboard URL is built from, and what DDEV routes.\n# Kept in step with DDEV by core/scripts/autostart.sh.\n%s: %s\n' "${key}" "${value}" >> "${file}" ;
|
|
72
|
+
fi
|
|
73
|
+
;;
|
|
74
|
+
*)
|
|
75
|
+
if grep -qE "^ ${key}:" "${file}" ; then
|
|
76
|
+
sed -i -E "s#^ ${key}:.*# ${key}: ${value}#" "${file}" ;
|
|
77
|
+
elif grep -qE '^dashboard:' "${file}" ; then
|
|
78
|
+
sed -i -E "/^dashboard:/a\\ ${key}: ${value}" "${file}" ;
|
|
79
|
+
else
|
|
80
|
+
printf '\ndashboard:\n %s: %s\n' "${key}" "${value}" >> "${file}" ;
|
|
81
|
+
fi
|
|
82
|
+
;;
|
|
83
|
+
esac
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
# Does this TLD answer for names nobody has put in /etc/hosts?
|
|
87
|
+
#
|
|
88
|
+
# This is the whole question, and it is why the default is ddev.site rather than something branded.
|
|
89
|
+
# `*.ddev.site` is wildcard DNS pointing at 127.0.0.1 AT ANY DEPTH — `x.dev.workspace.ddev.site`
|
|
90
|
+
# resolves with an empty hosts file — which is the only reason this tree's nested scheme
|
|
91
|
+
# (<project>.<workspace>.workspace.<tld>) works at all.
|
|
92
|
+
#
|
|
93
|
+
# A TLD without that has to be written into /etc/hosts, and **/etc/hosts cannot hold wildcards**. Every
|
|
94
|
+
# nested name would need its own line, DDEV would ask for sudo on every start, and each new project
|
|
95
|
+
# would silently 404 until someone added it by hand. So a TLD that does not resolve is refused rather
|
|
96
|
+
# than half-applied, and --force is there for the case where you run your own wildcard DNS.
|
|
97
|
+
function autostart_tld_resolves() {
|
|
98
|
+
local tld="$1" probe ;
|
|
99
|
+
probe="ddev-probe-$$.${tld}";
|
|
100
|
+
getent hosts "${probe}" > /dev/null 2>&1 ;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
# Hand the name to DDEV rather than editing any config.yaml. `ddev config global --project-tld` is the
|
|
104
|
+
# supported writer and it sets the DEFAULT FOR EVERY PROJECT — the dashboard, every workspace page
|
|
105
|
+
# under it, and each project's own <project>.<tld> — which is what makes this one field rather than
|
|
106
|
+
# forty. Hand-editing that YAML is how a project stops parsing.
|
|
107
|
+
function autostart_apply_domain() {
|
|
108
|
+
local app ; app="$(autostart_app_path)";
|
|
109
|
+
local domain ; domain="$(autostart_domain)";
|
|
110
|
+
local want_name want_tld current_name ;
|
|
111
|
+
|
|
112
|
+
[ -d "${app}/.ddev" ] || { echo "No DDEV project at ${app}."; return 1 ; }
|
|
113
|
+
|
|
114
|
+
want_name="${domain%%.*}";
|
|
115
|
+
want_tld="${domain#*.}";
|
|
116
|
+
current_name="$(grep -E '^name:' "${app}/.ddev/config.yaml" | head -1 | sed -E 's/^name:[[:space:]]*//')";
|
|
117
|
+
|
|
118
|
+
if [ -z "${want_tld}" ] || [ "${want_tld}" == "${domain}" ] ; then
|
|
119
|
+
echo " '${domain}' has no TLD — it should look like workspace.ddev.site." ;
|
|
120
|
+
return 1 ;
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
# A rename is not a domain change: DDEV keys its volumes, containers and router entries on the
|
|
124
|
+
# project name, so renaming strands the old database volume and builds a fresh empty one.
|
|
125
|
+
if [ "${want_name}" != "${current_name}" ] ; then
|
|
126
|
+
if [ "${FORCE}" == 'yes' ] ; then
|
|
127
|
+
echo " renaming the project ${current_name} -> ${want_name} (--force)." ;
|
|
128
|
+
echo " the old volumes stay behind; find them later with cmd-tools-reclaim.sh." ;
|
|
129
|
+
else
|
|
130
|
+
echo " '${domain}' would rename the project ${current_name} -> ${want_name}." ;
|
|
131
|
+
echo " That strands its database volume and builds an empty one, so it is refused here." ;
|
|
132
|
+
echo " Keep the first label as '${current_name}', or pass --force if you meant it." ;
|
|
133
|
+
return 1 ;
|
|
134
|
+
fi
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
if ! autostart_tld_resolves "${want_tld}" ; then
|
|
138
|
+
if [ "${FORCE}" == 'yes' ] ; then
|
|
139
|
+
echo " '${want_tld}' has no wildcard DNS — going ahead anyway (--force)." ;
|
|
140
|
+
echo " DDEV will ask for sudo and write /etc/hosts, and nested names will NOT work." ;
|
|
141
|
+
else
|
|
142
|
+
echo " '${want_tld}' does not resolve: a name under it answers nothing." ;
|
|
143
|
+
echo "" ;
|
|
144
|
+
echo " ddev.site is wildcard DNS to 127.0.0.1 at any depth, which is what makes" ;
|
|
145
|
+
echo " <project>.<workspace>.workspace.<tld> work with an empty /etc/hosts." ;
|
|
146
|
+
echo " /etc/hosts cannot hold wildcards, so a TLD without its own DNS needs one line" ;
|
|
147
|
+
echo " per hostname, added by hand, with sudo, forever." ;
|
|
148
|
+
echo "" ;
|
|
149
|
+
echo " Point *.${want_tld} at 127.0.0.1 in your DNS first, then pass --force." ;
|
|
150
|
+
return 1 ;
|
|
151
|
+
fi
|
|
152
|
+
fi
|
|
153
|
+
|
|
154
|
+
echo " applying: ${want_name}.${want_tld} (project '${want_name}', TLD '${want_tld}')" ;
|
|
155
|
+
|
|
156
|
+
# GLOBAL, not per-project, and that is the whole point of setting it here.
|
|
157
|
+
#
|
|
158
|
+
# Every project in this tree inherits `project-tld` from DDEV's global config — none of them carry
|
|
159
|
+
# their own — so one global setting moves the dashboard, every workspace page under it, and every
|
|
160
|
+
# project's canonical <project>.<tld> together. A per-project override on the dashboard instead
|
|
161
|
+
# would move workspace.<tld> and leave all 40-odd sites answering on ddev.site, with the dashboard's
|
|
162
|
+
# own Launch buttons pointing at hostnames that no longer exist.
|
|
163
|
+
ddev config global --project-tld="${want_tld}" > /dev/null || return 1 ;
|
|
164
|
+
|
|
165
|
+
# A per-project override beats the global one, so name the projects that will not follow rather
|
|
166
|
+
# than leaving someone to wonder why their site did not move.
|
|
167
|
+
local overrides ;
|
|
168
|
+
overrides="$(find "${WORKSPACE_ROOT}" -mindepth 2 -maxdepth 4 -name config.yaml -path '*/.ddev/*' 2>/dev/null \
|
|
169
|
+
| xargs grep -l '^project_tld' 2>/dev/null | sed 's|/.ddev/config.yaml||; s|.*/||' | paste -sd' ' -)";
|
|
170
|
+
[ -n "${overrides}" ] && echo " note: these set their own project_tld and will NOT follow: ${overrides}" ;
|
|
171
|
+
|
|
172
|
+
# Laptop or hub. On ddev.site the router binds 127.0.0.1 and that is correct — the sites are for
|
|
173
|
+
# the person sitting here. A real TLD means this is a shared workspace on a Docker host or a
|
|
174
|
+
# dedicated server, where binding to loopback makes it reachable by nobody: the port is open, the
|
|
175
|
+
# DNS resolves, and every request from outside the box times out with nothing in any log. So the
|
|
176
|
+
# bind is widened to match, and said out loud, because it is the one change here that exposes
|
|
177
|
+
# something to the network.
|
|
178
|
+
if [ "${want_tld}" != 'ddev.site' ] ; then
|
|
179
|
+
if [ "$(ddev config global 2>/dev/null | grep -c 'router-bind-all-interfaces=true')" -eq 0 ] ; then
|
|
180
|
+
echo "" ;
|
|
181
|
+
echo " '${want_tld}' is a real domain, so this is a shared hub rather than a laptop." ;
|
|
182
|
+
echo " The router is bound to 127.0.0.1 and nothing outside this machine can reach it." ;
|
|
183
|
+
if [ "${FORCE}" == 'yes' ] ; then
|
|
184
|
+
ddev config global --router-bind-all-interfaces=true > /dev/null 2>&1 \
|
|
185
|
+
&& echo " opened the router to all interfaces (--force)." ;
|
|
186
|
+
echo " EVERY DDEV project on this machine is now reachable from the network." ;
|
|
187
|
+
echo " Put it behind a firewall or a reverse proxy, and remember the sites are dev sites." ;
|
|
188
|
+
else
|
|
189
|
+
echo " Open it deliberately, once you have a firewall in front:" ;
|
|
190
|
+
echo " ddev config global --router-bind-all-interfaces=true" ;
|
|
191
|
+
echo " (or re-run this with --force). Left closed for now — the domain change still applied." ;
|
|
192
|
+
fi
|
|
193
|
+
echo "" ;
|
|
194
|
+
fi
|
|
195
|
+
fi
|
|
196
|
+
|
|
197
|
+
# A TLD only reaches the router after a restart — router config is pushed on start.
|
|
198
|
+
echo " restarting the dashboard so the router learns it…" ;
|
|
199
|
+
( cd "${app}" && ddev restart > /dev/null 2>&1 ) || {
|
|
200
|
+
echo " ddev restart failed. If it asked for a sudo password, run it yourself:" ;
|
|
201
|
+
echo " cd ${app} && ddev restart" ;
|
|
202
|
+
return 1 ;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
# Every other running project still answers on the OLD name until it restarts too: its containers
|
|
206
|
+
# were started against the previous TLD and the router holds no entry for the new one. Listed
|
|
207
|
+
# rather than done silently — restarting a site mid-build is how a half-written database happens,
|
|
208
|
+
# and there can be forty of them.
|
|
209
|
+
local stale ;
|
|
210
|
+
stale="$(ddev list --json-output 2>/dev/null \
|
|
211
|
+
| jq -r --arg n "${want_name}" '.raw[]? | select(.status=="running") | select(.name != $n) | .name' 2>/dev/null \
|
|
212
|
+
| paste -sd' ' -)";
|
|
213
|
+
if [ -n "${stale}" ] ; then
|
|
214
|
+
echo "" ;
|
|
215
|
+
echo " Running, and still on the old TLD until they restart:" ;
|
|
216
|
+
printf ' %s\n' ${stale} ;
|
|
217
|
+
if [ "${RESTART_ALL}" == 'yes' ] ; then
|
|
218
|
+
echo " restarting them (--restart-all)…" ;
|
|
219
|
+
local one root ;
|
|
220
|
+
for one in ${stale} ; do
|
|
221
|
+
root="$(ddev list --json-output 2>/dev/null \
|
|
222
|
+
| jq -r --arg n "${one}" '.raw[]? | select(.name==$n) | .approot' 2>/dev/null | head -1)";
|
|
223
|
+
[ -d "${root}" ] || continue ;
|
|
224
|
+
( cd "${root}" && ddev restart > /dev/null 2>&1 ) \
|
|
225
|
+
&& echo " restarted ${one}" || echo " FAILED ${one}" ;
|
|
226
|
+
done
|
|
227
|
+
else
|
|
228
|
+
echo " Restart them when nothing is mid-build:" ;
|
|
229
|
+
echo " bash core/scripts/autostart.sh --apply --restart-all" ;
|
|
230
|
+
fi
|
|
231
|
+
fi
|
|
232
|
+
return 0 ;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function autostart_write_unit() {
|
|
236
|
+
mkdir -p "${AUTOSTART_UNIT_DIR}" ;
|
|
237
|
+
|
|
238
|
+
# Type=oneshot + RemainAfterExit: `ddev start` returns when the containers are up, and the unit
|
|
239
|
+
# should then read as active rather than dead. The long timeout is not padding — a first start after
|
|
240
|
+
# an update rebuilds images, and systemd killing that halfway leaves a broken project.
|
|
241
|
+
cat > "${AUTOSTART_UNIT_DIR}/${AUTOSTART_UNIT_NAME}" <<UNITEOF
|
|
242
|
+
[Unit]
|
|
243
|
+
Description=Webship Workspace — start the dashboard and its projects
|
|
244
|
+
Documentation=https://github.com/webship/workspace
|
|
245
|
+
After=network-online.target
|
|
246
|
+
Wants=network-online.target
|
|
247
|
+
# The window StartLimitBurst counts failures IN, and it belongs HERE in [Unit] — systemd accepts
|
|
248
|
+
# StartLimitBurst under [Service] too for compatibility, but silently ignored StartLimitIntervalSec
|
|
249
|
+
# there ("Unknown key name", ddev-workspace ran on the default 10s window for a day before this was
|
|
250
|
+
# caught). The window has to be wider than RestartSec * StartLimitBurst below, or the burst limit
|
|
251
|
+
# can never be reached and this restarts forever: 3 tries at 20s apart span 60s, so 150s leaves room
|
|
252
|
+
# for that plus the first attempt's own startup time. Below this, a genuinely broken start (bad
|
|
253
|
+
# config, a Docker daemon that never recovers) retries forever rather than failing after three
|
|
254
|
+
# tries — silently rebuilding project images on every attempt, which is the same failure shape as
|
|
255
|
+
# the disk filling up from unrelated builds.
|
|
256
|
+
StartLimitIntervalSec=150
|
|
257
|
+
StartLimitBurst=3
|
|
258
|
+
|
|
259
|
+
[Service]
|
|
260
|
+
Type=oneshot
|
|
261
|
+
RemainAfterExit=yes
|
|
262
|
+
ExecStart=/bin/bash ${AUTOSTART_RUNNER}
|
|
263
|
+
# Records what was running, so 'autostart: running' has something to restore. RemainAfterExit means
|
|
264
|
+
# this fires on shutdown and reboot rather than the instant ExecStart returns.
|
|
265
|
+
ExecStop=/bin/bash ${AUTOSTART_RECORDER}
|
|
266
|
+
TimeoutStartSec=900
|
|
267
|
+
TimeoutStopSec=60
|
|
268
|
+
# Docker may not be accepting connections the instant the user session starts.
|
|
269
|
+
Restart=on-failure
|
|
270
|
+
RestartSec=20
|
|
271
|
+
|
|
272
|
+
[Install]
|
|
273
|
+
WantedBy=default.target
|
|
274
|
+
UNITEOF
|
|
275
|
+
echo " wrote ${AUTOSTART_UNIT_DIR}/${AUTOSTART_UNIT_NAME}" ;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
# The boot service runs once. A Docker restart AFTER login stops every container and nothing starts them
|
|
279
|
+
# again; this timer looks every two minutes and runs the same start script when Docker has restarted.
|
|
280
|
+
function autostart_write_watch() {
|
|
281
|
+
mkdir -p "${AUTOSTART_UNIT_DIR}" ;
|
|
282
|
+
cat > "${AUTOSTART_UNIT_DIR}/${AUTOSTART_WATCH_NAME}.service" <<UNITEOF
|
|
283
|
+
[Unit]
|
|
284
|
+
Description=Webship Workspace — start the dashboard again after Docker restarts
|
|
285
|
+
Documentation=https://github.com/webship/workspace
|
|
286
|
+
|
|
287
|
+
[Service]
|
|
288
|
+
Type=oneshot
|
|
289
|
+
ExecStart=/bin/bash ${AUTOSTART_WATCHER}
|
|
290
|
+
TimeoutStartSec=900
|
|
291
|
+
UNITEOF
|
|
292
|
+
cat > "${AUTOSTART_UNIT_DIR}/${AUTOSTART_WATCH_NAME}.timer" <<UNITEOF
|
|
293
|
+
[Unit]
|
|
294
|
+
Description=Webship Workspace — look for a Docker restart every two minutes
|
|
295
|
+
|
|
296
|
+
[Timer]
|
|
297
|
+
OnBootSec=3min
|
|
298
|
+
OnUnitActiveSec=2min
|
|
299
|
+
AccuracySec=15s
|
|
300
|
+
|
|
301
|
+
[Install]
|
|
302
|
+
WantedBy=timers.target
|
|
303
|
+
UNITEOF
|
|
304
|
+
echo " wrote ${AUTOSTART_UNIT_DIR}/${AUTOSTART_WATCH_NAME}.{service,timer}" ;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function autostart_enable() {
|
|
308
|
+
command -v systemctl > /dev/null 2>&1 || { echo "No systemctl here — nothing to install."; return 1 ; }
|
|
309
|
+
|
|
310
|
+
autostart_write_unit ;
|
|
311
|
+
systemctl --user daemon-reload ;
|
|
312
|
+
systemctl --user enable "${AUTOSTART_UNIT_NAME}" > /dev/null 2>&1 ;
|
|
313
|
+
autostart_write_watch ;
|
|
314
|
+
systemctl --user daemon-reload ;
|
|
315
|
+
systemctl --user enable --now "${AUTOSTART_WATCH_NAME}.timer" > /dev/null 2>&1 \
|
|
316
|
+
&& echo " watching for a Docker restart (every two minutes)" ;
|
|
317
|
+
|
|
318
|
+
# Lingering is the difference between "starts at boot" and "starts when Rajab logs in". Without it
|
|
319
|
+
# the dashboard is missing until someone signs in, which is exactly the problem being solved.
|
|
320
|
+
if command -v loginctl > /dev/null 2>&1 ; then
|
|
321
|
+
if [ "$(loginctl show-user "${USER}" -p Linger --value 2>/dev/null)" != 'yes' ] ; then
|
|
322
|
+
echo " enabling lingering so it starts at BOOT, not at login (needs sudo once)…" ;
|
|
323
|
+
sudo loginctl enable-linger "${USER}" 2>/dev/null \
|
|
324
|
+
&& echo " lingering on" \
|
|
325
|
+
|| { echo " could not enable lingering — run this once yourself:" ;
|
|
326
|
+
echo " sudo loginctl enable-linger ${USER}" ;
|
|
327
|
+
echo " until then the dashboard starts at login rather than at boot." ; }
|
|
328
|
+
else
|
|
329
|
+
echo " lingering already on" ;
|
|
330
|
+
fi
|
|
331
|
+
fi
|
|
332
|
+
echo " enabled — it will run on the next boot. Prove it now with --now." ;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function autostart_disable() {
|
|
336
|
+
command -v systemctl > /dev/null 2>&1 || return 0 ;
|
|
337
|
+
systemctl --user disable --now "${AUTOSTART_UNIT_NAME}" > /dev/null 2>&1 ;
|
|
338
|
+
systemctl --user disable --now "${AUTOSTART_WATCH_NAME}.timer" > /dev/null 2>&1 ;
|
|
339
|
+
rm -f "${AUTOSTART_UNIT_DIR}/${AUTOSTART_UNIT_NAME}" "${AUTOSTART_UNIT_DIR}/${AUTOSTART_WATCH_NAME}.service" "${AUTOSTART_UNIT_DIR}/${AUTOSTART_WATCH_NAME}.timer" ;
|
|
340
|
+
systemctl --user daemon-reload ;
|
|
341
|
+
echo " removed. Projects are not touched; they keep running." ;
|
|
342
|
+
echo " Lingering was left on — turn it off with: sudo loginctl disable-linger ${USER}" ;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function autostart_status() {
|
|
346
|
+
local app ; app="$(autostart_app_path)";
|
|
347
|
+
local unit_state linger ;
|
|
348
|
+
|
|
349
|
+
unit_state="$(systemctl --user is-enabled "${AUTOSTART_UNIT_NAME}" 2>/dev/null)";
|
|
350
|
+
case "${unit_state}" in ''|not-found) unit_state='not installed' ;; esac ;
|
|
351
|
+
linger="$(loginctl show-user "${USER}" -p Linger --value 2>/dev/null || echo '?')";
|
|
352
|
+
|
|
353
|
+
echo "" ;
|
|
354
|
+
echo "── Autostart ────────────────────────────────────────────────────────" ;
|
|
355
|
+
printf " boot service : %s\n" "${unit_state}" ;
|
|
356
|
+
printf " lingering : %s%s\n" "${linger}" "$([ "${linger}" == 'yes' ] && echo '' || echo ' (without it, starts at login not at boot)')" ;
|
|
357
|
+
printf " setting : %s\n" "${dashboard_autostart:-workspace}" ;
|
|
358
|
+
printf " will start : %s\n" "$(autostart_projects | paste -sd' ' -)" ;
|
|
359
|
+
local domain tld ; domain="$(autostart_domain)" ; tld="${domain#*.}" ;
|
|
360
|
+
printf " domain : %s\n" "${domain}" ;
|
|
361
|
+
local global_tld ; global_tld="$(ddev config global 2>/dev/null | sed -n 's/^project-tld=//p')" ;
|
|
362
|
+
if [ "${global_tld}" == "${tld}" ] ; then
|
|
363
|
+
printf " DDEV TLD : %s — global, so every project inherits it\n" "${global_tld}" ;
|
|
364
|
+
else
|
|
365
|
+
printf " DDEV TLD : %s in DDEV vs %s in settings — run --apply to line them up\n" "${global_tld:-unset}" "${tld}" ;
|
|
366
|
+
fi
|
|
367
|
+
if autostart_tld_resolves "${tld}" ; then
|
|
368
|
+
printf " TLD DNS : *.%s resolves on its own — no /etc/hosts needed\n" "${tld}" ;
|
|
369
|
+
else
|
|
370
|
+
printf " TLD DNS : *.%s does NOT resolve — every name needs an /etc/hosts line\n" "${tld}" ;
|
|
371
|
+
fi
|
|
372
|
+
if [ "${tld}" == 'ddev.site' ] ; then
|
|
373
|
+
printf " reachable : this machine only (ddev.site, router on 127.0.0.1)\n" ;
|
|
374
|
+
elif ddev config global 2>/dev/null | grep -q 'router-bind-all-interfaces=true' ; then
|
|
375
|
+
printf " reachable : from the network — shared hub, router on all interfaces\n" ;
|
|
376
|
+
else
|
|
377
|
+
printf " reachable : this machine only — a real TLD but the router is still on 127.0.0.1\n" ;
|
|
378
|
+
printf " open it with: ddev config global --router-bind-all-interfaces=true\n" ;
|
|
379
|
+
fi
|
|
380
|
+
echo "" ;
|
|
381
|
+
echo " DDEV sees:" ;
|
|
382
|
+
( cd "${app}" 2>/dev/null && ddev describe 2>/dev/null \
|
|
383
|
+
| awk -F'│' '/web|Project:/ {gsub(/^[ \t]+|[ \t]+$/,"",$2); if ($2 != "") printf " %s\n", $2}' | head -3 ) \
|
|
384
|
+
|| echo " (no project at ${app})" ;
|
|
385
|
+
echo "" ;
|
|
386
|
+
echo " Every URL the dashboard answers on:" ;
|
|
387
|
+
( cd "${app}" 2>/dev/null && ddev describe -j 2>/dev/null \
|
|
388
|
+
| jq -r '.raw.urls[]?' 2>/dev/null | grep '^https' | sed 's/^/ /' | head -12 ) ;
|
|
389
|
+
echo "" ;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function autostart_command() {
|
|
393
|
+
local changed=0 ;
|
|
394
|
+
|
|
395
|
+
if [ ! "${DOMAIN}" == '_none_' ] ; then
|
|
396
|
+
# Hold it in the variable the apply step reads, but do NOT write the file yet — a refused domain
|
|
397
|
+
# must not end up recorded as the truth. The write happens below, only once DDEV took it.
|
|
398
|
+
hub_domain="${DOMAIN}";
|
|
399
|
+
changed=1 ;
|
|
400
|
+
fi
|
|
401
|
+
|
|
402
|
+
[ "${APPLY}" == 'yes' ] && changed=1 ;
|
|
403
|
+
|
|
404
|
+
if [ "${changed}" -eq 1 ] ; then
|
|
405
|
+
echo "" ;
|
|
406
|
+
echo "→ applying the domain to the dashboard project" ;
|
|
407
|
+
autostart_apply_domain || { echo " nothing was changed, in DDEV or in the settings." ; return 1 ; }
|
|
408
|
+
if [ ! "${DOMAIN}" == '_none_' ] ; then
|
|
409
|
+
autostart_settings_write 'hub_domain' "${DOMAIN}" || return 1 ;
|
|
410
|
+
echo " domain is now: ${DOMAIN}" ;
|
|
411
|
+
fi
|
|
412
|
+
echo " done" ;
|
|
413
|
+
fi
|
|
414
|
+
|
|
415
|
+
if [ "${ENABLE}" == 'yes' ] ; then
|
|
416
|
+
echo "" ; echo "→ installing the boot service" ; autostart_enable || return 1 ;
|
|
417
|
+
fi
|
|
418
|
+
|
|
419
|
+
if [ "${DISABLE}" == 'yes' ] ; then
|
|
420
|
+
echo "" ; echo "→ removing the boot service" ; autostart_disable ;
|
|
421
|
+
fi
|
|
422
|
+
|
|
423
|
+
if [ "${NOW}" == 'yes' ] ; then
|
|
424
|
+
echo "" ; echo "→ running exactly what the boot service runs" ;
|
|
425
|
+
bash "${AUTOSTART_RUNNER}" || return 1 ;
|
|
426
|
+
fi
|
|
427
|
+
|
|
428
|
+
autostart_status ;
|
|
429
|
+
}
|