@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,179 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# ElevenLabs for the final voiceover of a narrated video (videos/cmd-tools-elevenlabs.sh).
|
|
4
|
+
# The key is read here and handed to libs/elevenlabs.py in one process's environment, never on a command line.
|
|
5
|
+
|
|
6
|
+
ELEVENLABS_BLOCK='
|
|
7
|
+
# ElevenLabs, for the final voiceover of a narrated video (videos/cmd-tools-elevenlabs.sh). Nothing is
|
|
8
|
+
# sent to ElevenLabs unless a person agrees to a run. ELEVENLABS_API_KEY in the environment wins over api_key.
|
|
9
|
+
# voice_id may be an id or a voice name such as Brian; voice and model are accepted for voice_id and model_id.
|
|
10
|
+
elevenlabs:
|
|
11
|
+
api_key: CHANGE_ME
|
|
12
|
+
voice_id: ask
|
|
13
|
+
model_id: eleven_v4
|
|
14
|
+
region: global
|
|
15
|
+
# Brand names are respelled for the voice only (built in: Webship=Var-dot; Webship=Var-base). Add more as
|
|
16
|
+
# "Word=Respelling; Word=Respelling" when a voice misreads one.
|
|
17
|
+
pronunciation: ""
|
|
18
|
+
';
|
|
19
|
+
|
|
20
|
+
# parse_yaml keeps a value's quotes.
|
|
21
|
+
function elevenlabs_setting() {
|
|
22
|
+
local value="$1";
|
|
23
|
+
case "${value}" in
|
|
24
|
+
\"*\") value="${value#\"}"; value="${value%\"}" ;;
|
|
25
|
+
\'*\') value="${value#\'}"; value="${value%\'}" ;;
|
|
26
|
+
esac
|
|
27
|
+
printf '%s' "${value}";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function elevenlabs_key_source() {
|
|
31
|
+
local settings_key;
|
|
32
|
+
settings_key="$(elevenlabs_setting "${elevenlabs_api_key}")";
|
|
33
|
+
if [ -n "${ELEVENLABS_API_KEY:-}" ] ; then echo 'environment' ; return 0 ; fi
|
|
34
|
+
case "${settings_key}" in
|
|
35
|
+
''|CHANGE_ME|sk-change-this) return 1 ;;
|
|
36
|
+
esac
|
|
37
|
+
echo 'settings.yml';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function elevenlabs_key() {
|
|
41
|
+
case "$(elevenlabs_key_source)" in
|
|
42
|
+
environment) printf '%s' "${ELEVENLABS_API_KEY}" ;;
|
|
43
|
+
settings.yml) elevenlabs_setting "${elevenlabs_api_key}" ;;
|
|
44
|
+
esac
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function elevenlabs_base() {
|
|
48
|
+
if [ -n "${ELEVENLABS_API_BASE:-}" ] ; then echo "${ELEVENLABS_API_BASE%/}" ; return 0 ; fi
|
|
49
|
+
case "$(elevenlabs_setting "${elevenlabs_region}")" in
|
|
50
|
+
us) echo 'https://api.us.elevenlabs.io' ;;
|
|
51
|
+
eu) echo 'https://api.eu.residency.elevenlabs.io' ;;
|
|
52
|
+
in) echo 'https://api.in.residency.elevenlabs.io' ;;
|
|
53
|
+
sg) echo 'https://api.sg.residency.elevenlabs.io' ;;
|
|
54
|
+
*) echo 'https://api.elevenlabs.io' ;;
|
|
55
|
+
esac
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function elevenlabs_model() {
|
|
59
|
+
local model;
|
|
60
|
+
model="$(elevenlabs_setting "${elevenlabs_model_id:-${elevenlabs_model:-}}")";
|
|
61
|
+
echo "${ELEVENLABS_MODEL:-${model:-eleven_v4}}";
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function elevenlabs_voice() {
|
|
65
|
+
local voice;
|
|
66
|
+
voice="$(elevenlabs_setting "${elevenlabs_voice_id:-${elevenlabs_voice:-}}")";
|
|
67
|
+
case "${voice}" in ''|ask|CHANGE_ME) voice='' ;; esac
|
|
68
|
+
echo "${ELEVENLABS_VOICE:-${voice}}";
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function elevenlabs_engine() {
|
|
72
|
+
ELEVENLABS_API_KEY="$(elevenlabs_key)" ELEVENLABS_API_BASE="$(elevenlabs_base)" \
|
|
73
|
+
ELEVENLABS_MODEL="$(elevenlabs_model)" ELEVENLABS_VOICE="$(elevenlabs_voice)" \
|
|
74
|
+
ELEVENLABS_PRONUNCIATION="${ELEVENLABS_PRONUNCIATION:-$(elevenlabs_setting "${elevenlabs_pronunciation:-}")}" \
|
|
75
|
+
python3 "${WORKSPACE_SCRIPTS}/libs/elevenlabs.py" "$@" ;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function elevenlabs_status() {
|
|
79
|
+
local key_source voice;
|
|
80
|
+
key_source="$(elevenlabs_key_source)";
|
|
81
|
+
voice="$(elevenlabs_voice)";
|
|
82
|
+
echo "ElevenLabs";
|
|
83
|
+
if [ -n "${key_source}" ] ; then echo " key: set (${key_source})" ; else echo " key: not set" ; fi
|
|
84
|
+
echo " block: $(grep -q '^elevenlabs:' "${WORKSPACE_CONFIG}/settings.yml" 2>/dev/null && echo 'in settings.yml' || echo 'missing from settings.yml (run -a init)')";
|
|
85
|
+
echo " server: $(elevenlabs_base)";
|
|
86
|
+
echo " model: $(elevenlabs_model)";
|
|
87
|
+
echo " voice: ${voice:-ask each time (list them with -a voices)}";
|
|
88
|
+
if [ -z "${key_source}" ] ; then
|
|
89
|
+
echo "";
|
|
90
|
+
echo "No key, so the final voiceover stage is not offered. Add one at /settings (ElevenLabs); never paste it into a chat.";
|
|
91
|
+
return 3 ;
|
|
92
|
+
fi
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function elevenlabs_init() {
|
|
96
|
+
local file="${WORKSPACE_CONFIG}/settings.yml";
|
|
97
|
+
if [ ! -f "${file}" ] ; then echo "No settings.yml at ${file}." ; return 1 ; fi
|
|
98
|
+
if grep -q '^elevenlabs:' "${file}" ; then
|
|
99
|
+
echo "settings.yml already has an elevenlabs: block. Set api_key at /settings (ElevenLabs).";
|
|
100
|
+
return 0 ;
|
|
101
|
+
fi
|
|
102
|
+
[ -n "$(tail -c1 "${file}")" ] && printf '\n' >> "${file}" ;
|
|
103
|
+
printf '%s' "${ELEVENLABS_BLOCK}" >> "${file}" ;
|
|
104
|
+
echo "Added an elevenlabs: block to ${file} with a placeholder key. Open /settings, find ElevenLabs and set the key there.";
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function elevenlabs_mcp() {
|
|
108
|
+
local name='elevenlabs' url;
|
|
109
|
+
url="$(elevenlabs_base)/v1/mcp";
|
|
110
|
+
if ! command -v claude > /dev/null 2>&1 ; then echo "The Claude Code CLI (claude) is not on PATH." ; return 1 ; fi
|
|
111
|
+
case "$1" in
|
|
112
|
+
status)
|
|
113
|
+
timeout 60 claude mcp get "${name}" 2>&1 || echo "Not registered in Claude Code yet. Run -a mcp-register." ;
|
|
114
|
+
;;
|
|
115
|
+
register)
|
|
116
|
+
if claude mcp get "${name}" > /dev/null 2>&1 ; then
|
|
117
|
+
echo "${name} is already registered. -a mcp-unregister removes it first if the address must change.";
|
|
118
|
+
return 0 ;
|
|
119
|
+
fi
|
|
120
|
+
claude mcp add --transport http --scope user "${name}" "${url}" || return 1 ;
|
|
121
|
+
echo "";
|
|
122
|
+
echo "Registered ${name} (${url}). No key is stored: it signs in with OAuth.";
|
|
123
|
+
echo " Open a NEW session, run /mcp, pick ${name} and sign in with your ElevenLabs account.";
|
|
124
|
+
echo " It manages ElevenLabs agents and can generate speech samples. An agent update is published directly,";
|
|
125
|
+
echo " with no draft, so keep its write tools on ask-first in the client.";
|
|
126
|
+
;;
|
|
127
|
+
unregister)
|
|
128
|
+
claude mcp remove --scope user "${name}" && echo "Removed ${name} from the Claude Code CLI." ;
|
|
129
|
+
;;
|
|
130
|
+
esac
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function elevenlabs_usage() {
|
|
134
|
+
cat <<'USAGE'
|
|
135
|
+
usage: cmd-tools-elevenlabs.sh -a ACTION [options]
|
|
136
|
+
|
|
137
|
+
Free, nothing is sent to ElevenLabs:
|
|
138
|
+
-a status key, voice, model and server (exit 3 when no key is set)
|
|
139
|
+
-a init add the elevenlabs: block to settings.yml when it is missing
|
|
140
|
+
-a sections --script FILE the timed sections of a voiceover script and their characters
|
|
141
|
+
|
|
142
|
+
Reads the account, no credits spent:
|
|
143
|
+
-a check status, plan and characters left
|
|
144
|
+
-a voices [--search WORD] the voices on the account
|
|
145
|
+
|
|
146
|
+
Spends credits, so it prints a plan and stops unless --confirm is given:
|
|
147
|
+
-a speak --text-file F --out F.mp3 [--voice ID]
|
|
148
|
+
-a voiceover --script S.md --video V.mp4 --out O.mp4 [--voice ID] [--drop-optional] [--max-speedup 1.08] [--redo]
|
|
149
|
+
-a isolate --audio TAKE --out CLEAN.mp3
|
|
150
|
+
-a polish --audio TAKE --video V.mp4 --out O.mp4 [--isolate] [--no-normalize]
|
|
151
|
+
|
|
152
|
+
The hosted MCP server (OAuth, no key stored):
|
|
153
|
+
-a mcp-status | mcp-register | mcp-unregister
|
|
154
|
+
|
|
155
|
+
Add --json for machine-readable output and --force to replace an existing file.
|
|
156
|
+
Exit codes: 0 ok, 1 error, 2 usage, 3 no key, 4 plan only, 5 sections do not fit.
|
|
157
|
+
USAGE
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function elevenlabs_main() {
|
|
161
|
+
local action='status';
|
|
162
|
+
while [ $# -gt 0 ] ; do
|
|
163
|
+
case "$1" in
|
|
164
|
+
-h|--help) elevenlabs_usage ; return 0 ;;
|
|
165
|
+
-a|--action) action="$2"; shift 2 || { elevenlabs_usage >&2 ; return 2 ; } ;;
|
|
166
|
+
*) break ;;
|
|
167
|
+
esac
|
|
168
|
+
done
|
|
169
|
+
case "${action}" in
|
|
170
|
+
status) elevenlabs_status ;;
|
|
171
|
+
init) elevenlabs_init ;;
|
|
172
|
+
check) elevenlabs_status && elevenlabs_engine account "$@" ;;
|
|
173
|
+
sections|voices|speak|isolate|voiceover|polish) elevenlabs_engine "${action}" "$@" ;;
|
|
174
|
+
mcp-status) elevenlabs_mcp status ;;
|
|
175
|
+
mcp-register) elevenlabs_mcp register ;;
|
|
176
|
+
mcp-unregister) elevenlabs_mcp unregister ;;
|
|
177
|
+
*) echo "Unknown action: ${action}" >&2 ; elevenlabs_usage >&2 ; return 2 ;;
|
|
178
|
+
esac
|
|
179
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# Change file permissions and ownership
|
|
4
|
+
function set_chmod() {
|
|
5
|
+
sudo chmod 775 -R ${WORKSPACE_ROOT}/${doc_name}/${PROJECT_NAME} ;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
# Change file permissions and ownership
|
|
9
|
+
function set_chown() {
|
|
10
|
+
sudo chown www-data:${user_name} -R ${WORKSPACE_ROOT}/${doc_name}/${PROJECT_NAME} ;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
# Securing file permissions and ownership.
|
|
14
|
+
function set_chmod_chown() {
|
|
15
|
+
echo "Securing file permissions and ownership";
|
|
16
|
+
sudo chmod 775 -R ${WORKSPACE_ROOT}/${doc_name}/${PROJECT_NAME} ;
|
|
17
|
+
sudo chown www-data:${user_name} -R ${WORKSPACE_ROOT}/${doc_name}/${PROJECT_NAME} ;
|
|
18
|
+
}
|
|
19
|
+
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
################################################################################
|
|
4
|
+
## Knowing what a project's folder IS, before anything deletes it.
|
|
5
|
+
################################################################################
|
|
6
|
+
## Once a project can be cloned as a git worktree (see fun-clone-project.sh) a
|
|
7
|
+
## workspace folder holds three different kinds of thing that all look identical
|
|
8
|
+
## in `ls`:
|
|
9
|
+
##
|
|
10
|
+
## plain a git checkout that nothing else depends on
|
|
11
|
+
## primary the checkout that owns the real .git — other folders live off it
|
|
12
|
+
## linked a worktree; its .git is a FILE pointing at the primary's
|
|
13
|
+
##
|
|
14
|
+
## The difference matters exactly once, and destructively:
|
|
15
|
+
##
|
|
16
|
+
## * Deleting a PRIMARY deletes the shared .git, and every linked worktree of it
|
|
17
|
+
## becomes an orphan — a directory full of files git can no longer say
|
|
18
|
+
## anything about. The branches, the stashes and the reflog go with it. That
|
|
19
|
+
## is unrecoverable in a way that deleting a worktree is not.
|
|
20
|
+
## * Deleting a LINKED worktree is cheap — unless it holds commits that were
|
|
21
|
+
## never pushed, which is the one thing `git worktree remove` will happily
|
|
22
|
+
## destroy for you.
|
|
23
|
+
##
|
|
24
|
+
## So remove_project asks these questions first and refuses rather than guessing.
|
|
25
|
+
## Everything here is read-only except git_worktree_prune, which only tidies
|
|
26
|
+
## administrative data git itself calls stale.
|
|
27
|
+
################################################################################
|
|
28
|
+
|
|
29
|
+
# plain | primary | linked | none — what this directory is.
|
|
30
|
+
function git_worktree_role() {
|
|
31
|
+
local dir="${1:-}" common toplevel
|
|
32
|
+
[ -n "${dir}" ] && [ -d "${dir}" ] || { echo 'none' ; return 0 ; }
|
|
33
|
+
git -C "${dir}" rev-parse --git-dir > /dev/null 2>&1 || { echo 'none' ; return 0 ; }
|
|
34
|
+
|
|
35
|
+
# In a linked worktree the git dir sits INSIDE the primary's .git as
|
|
36
|
+
# worktrees/<name>, so the two paths differ. In the primary they are the same.
|
|
37
|
+
local gitdir gitcommon
|
|
38
|
+
gitdir="$(git -C "${dir}" rev-parse --absolute-git-dir 2>/dev/null)"
|
|
39
|
+
gitcommon="$(git -C "${dir}" rev-parse --path-format=absolute --git-common-dir 2>/dev/null)"
|
|
40
|
+
if [ -n "${gitdir}" ] && [ -n "${gitcommon}" ] && [ "${gitdir}" != "${gitcommon}" ] ; then
|
|
41
|
+
echo 'linked' ; return 0 ;
|
|
42
|
+
fi
|
|
43
|
+
# The primary. Whether it is "primary" or merely "plain" is about whether
|
|
44
|
+
# anything else depends on it.
|
|
45
|
+
if [ -n "$(git_worktree_others "${dir}")" ] ; then
|
|
46
|
+
echo 'primary' ;
|
|
47
|
+
else
|
|
48
|
+
echo 'plain' ;
|
|
49
|
+
fi
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
# The other worktrees of this repository, one absolute path per line, this
|
|
53
|
+
# directory excluded. Parsed from the porcelain form, which is stable output
|
|
54
|
+
# meant for scripts — `git worktree list` without it aligns columns and would
|
|
55
|
+
# break on a path containing spaces.
|
|
56
|
+
function git_worktree_others() {
|
|
57
|
+
local dir="${1:-}" self
|
|
58
|
+
[ -n "${dir}" ] && [ -d "${dir}" ] || return 0
|
|
59
|
+
git -C "${dir}" rev-parse --git-dir > /dev/null 2>&1 || return 0
|
|
60
|
+
self="$(cd "${dir}" && pwd -P)"
|
|
61
|
+
git -C "${dir}" worktree list --porcelain 2>/dev/null \
|
|
62
|
+
| sed -n 's/^worktree //p' \
|
|
63
|
+
| while IFS= read -r p ; do
|
|
64
|
+
[ -n "${p}" ] || continue
|
|
65
|
+
# Compare resolved paths: a symlinked workspace root would otherwise make
|
|
66
|
+
# a folder look like a different one from itself.
|
|
67
|
+
[ "$( (cd "${p}" 2>/dev/null && pwd -P) || echo "${p}")" == "${self}" ] && continue
|
|
68
|
+
echo "${p}" ;
|
|
69
|
+
done
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
# The primary worktree's path — where the real .git lives.
|
|
73
|
+
function git_worktree_primary() {
|
|
74
|
+
local dir="${1:-}"
|
|
75
|
+
[ -n "${dir}" ] && [ -d "${dir}" ] || return 0
|
|
76
|
+
git -C "${dir}" rev-parse --git-dir > /dev/null 2>&1 || return 0
|
|
77
|
+
git -C "${dir}" worktree list --porcelain 2>/dev/null | sed -n '1s/^worktree //p'
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
# The branch checked out here, or '' when detached.
|
|
81
|
+
function git_worktree_branch() {
|
|
82
|
+
local dir="${1:-}" b
|
|
83
|
+
b="$(git -C "${dir}" rev-parse --abbrev-ref HEAD 2>/dev/null)"
|
|
84
|
+
[ "${b}" == 'HEAD' ] && b=''
|
|
85
|
+
echo "${b}"
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
# How many commits reachable from HEAD are on NO remote — i.e. what deleting this
|
|
89
|
+
# folder would destroy. Counting against every remote rather than against an
|
|
90
|
+
# upstream, because a worktree branch created locally has no upstream at all and
|
|
91
|
+
# `@{upstream}` would simply error, which is the case that most needs the answer.
|
|
92
|
+
function git_worktree_unpushed() {
|
|
93
|
+
local dir="${1:-}" n
|
|
94
|
+
[ -n "${dir}" ] && [ -d "${dir}" ] || { echo 0 ; return 0 ; }
|
|
95
|
+
git -C "${dir}" rev-parse --git-dir > /dev/null 2>&1 || { echo 0 ; return 0 ; }
|
|
96
|
+
n="$(git -C "${dir}" rev-list --count HEAD --not --remotes 2>/dev/null)"
|
|
97
|
+
echo "${n:-0}"
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
# Uncommitted work in the folder: tracked changes plus untracked files that are
|
|
101
|
+
# not ignored. Unpushed commits are not the only thing a delete throws away.
|
|
102
|
+
function git_worktree_dirty() {
|
|
103
|
+
local dir="${1:-}"
|
|
104
|
+
[ -n "${dir}" ] && [ -d "${dir}" ] || { echo 0 ; return 0 ; }
|
|
105
|
+
git -C "${dir}" rev-parse --git-dir > /dev/null 2>&1 || { echo 0 ; return 0 ; }
|
|
106
|
+
# `grep -c` prints 0 AND exits 1 when nothing matches, so a `|| echo 0` fallback
|
|
107
|
+
# prints a SECOND zero and the caller reads "0 0". Count the lines instead.
|
|
108
|
+
local n
|
|
109
|
+
n="$(git -C "${dir}" status --porcelain --untracked-files=normal 2>/dev/null | wc -l | tr -d '[:space:]')"
|
|
110
|
+
echo "${n:-0}"
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
# After a worktree's directory is gone, its registration in the primary is stale.
|
|
114
|
+
# git says so on every `worktree list` until it is pruned, and a new worktree at
|
|
115
|
+
# the same path is refused while it stands. Only ever called with the primary.
|
|
116
|
+
function git_worktree_prune() {
|
|
117
|
+
local primary="${1:-}"
|
|
118
|
+
[ -n "${primary}" ] && [ -d "${primary}" ] || return 0
|
|
119
|
+
git -C "${primary}" worktree prune 2>/dev/null || true
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
# One human line about a folder, for a listing or a confirmation. Says nothing at
|
|
123
|
+
# all for a folder that is not a git checkout, so callers can print it blind.
|
|
124
|
+
function git_worktree_summary() {
|
|
125
|
+
local dir="${1:-}" role others n branch unpushed
|
|
126
|
+
role="$(git_worktree_role "${dir}")"
|
|
127
|
+
case "${role}" in
|
|
128
|
+
none) return 0 ;;
|
|
129
|
+
linked)
|
|
130
|
+
branch="$(git_worktree_branch "${dir}")"
|
|
131
|
+
unpushed="$(git_worktree_unpushed "${dir}")"
|
|
132
|
+
printf 'a git worktree on %s of %s' "${branch:-a detached HEAD}" "$(git_worktree_primary "${dir}")" ;
|
|
133
|
+
[ "${unpushed}" -gt 0 ] && printf ' — %s unpushed commit(s)' "${unpushed}" ;
|
|
134
|
+
echo ;;
|
|
135
|
+
primary)
|
|
136
|
+
n="$(git_worktree_others "${dir}" | grep -c .)"
|
|
137
|
+
echo "the main checkout, with ${n} worktree(s) depending on its .git" ;;
|
|
138
|
+
plain)
|
|
139
|
+
branch="$(git_worktree_branch "${dir}")"
|
|
140
|
+
echo "a git checkout on ${branch:-a detached HEAD}" ;;
|
|
141
|
+
esac
|
|
142
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# gitlab-ci-local (https://github.com/firecow/gitlab-ci-local) runs a project's
|
|
4
|
+
# GitLab CI pipeline in local Docker containers. It is how the Webship
|
|
5
|
+
# green-gate is enforced: before committing to an issue-fork branch or pushing
|
|
6
|
+
# anything to git.drupalcode.org, the full pipeline runs locally and the push
|
|
7
|
+
# waits until every stage and every job is green.
|
|
8
|
+
#
|
|
9
|
+
# Drupal projects include drupal/gitlab_templates, whose jobs die on an unset
|
|
10
|
+
# _GITLAB_TEMPLATES_REPO unless the template variables are resolved. The
|
|
11
|
+
# standard fix is a wrapper that adds --remote-variables over SSH (upstream
|
|
12
|
+
# says HTTPS clones "do not work completely without issues"), which these
|
|
13
|
+
# functions install once as ~/.local/bin/drupal-ci-local.
|
|
14
|
+
|
|
15
|
+
# Make sure gitlab-ci-local is on PATH; offer the install paths if not.
|
|
16
|
+
function ensure_gitlab_ci_local() {
|
|
17
|
+
if command -v gitlab-ci-local > /dev/null 2>&1 ; then
|
|
18
|
+
return 0 ;
|
|
19
|
+
fi
|
|
20
|
+
echo "gitlab-ci-local is not installed — installing with npm.";
|
|
21
|
+
npm install -g gitlab-ci-local || {
|
|
22
|
+
echo "npm install failed. Alternatives:" ;
|
|
23
|
+
echo " brew install gitlab-ci-local # macOS" ;
|
|
24
|
+
echo " see https://github.com/firecow/gitlab-ci-local#installation" ;
|
|
25
|
+
return 1 ;
|
|
26
|
+
}
|
|
27
|
+
command -v gitlab-ci-local > /dev/null 2>&1 || {
|
|
28
|
+
echo "Still not on PATH — check npm's global bin directory." ;
|
|
29
|
+
return 1 ;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
# The Drupal wrapper: gitlab-ci-local plus the drupal/gitlab_templates remote
|
|
34
|
+
# variables. Written once, then everything Drupal runs through it.
|
|
35
|
+
function ensure_drupal_ci_wrapper() {
|
|
36
|
+
local wrapper="${HOME}/.local/bin/drupal-ci-local";
|
|
37
|
+
if [ -x "${wrapper}" ]; then
|
|
38
|
+
return 0 ;
|
|
39
|
+
fi
|
|
40
|
+
mkdir -p "${HOME}/.local/bin" ;
|
|
41
|
+
cat > "${wrapper}" <<'WRAP'
|
|
42
|
+
#!/bin/bash
|
|
43
|
+
# gitlab-ci-local wired for drupal/gitlab_templates. SSH on purpose: upstream
|
|
44
|
+
# documents that HTTPS template clones do not work completely without issues.
|
|
45
|
+
gitlab-ci-local \
|
|
46
|
+
--remote-variables git@git.drupal.org:project/gitlab_templates=includes/include.drupalci.variables.yml=main \
|
|
47
|
+
--variable="_GITLAB_TEMPLATES_REPO=project/gitlab_templates" \
|
|
48
|
+
"$@"
|
|
49
|
+
WRAP
|
|
50
|
+
chmod +x "${wrapper}" ;
|
|
51
|
+
echo "Installed ${wrapper}." ;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# Everything a run needs, checked up front with real error messages.
|
|
55
|
+
function gitlab_ci_local_doctor() {
|
|
56
|
+
local ok=0;
|
|
57
|
+
ensure_gitlab_ci_local || ok=1 ;
|
|
58
|
+
ensure_drupal_ci_wrapper || ok=1 ;
|
|
59
|
+
if ! docker info > /dev/null 2>&1 ; then
|
|
60
|
+
echo "Docker is not reachable — every job runs in a container. Start Docker first." ;
|
|
61
|
+
ok=1 ;
|
|
62
|
+
fi
|
|
63
|
+
if ! ssh -o BatchMode=yes -o ConnectTimeout=8 git@git.drupal.org 2>&1 | grep -q 'Welcome to GitLab' ; then
|
|
64
|
+
echo "SSH to git.drupal.org failed — the Drupal template variables are fetched over SSH." ;
|
|
65
|
+
echo "Load your key into ssh-agent, or add one: https://git.drupalcode.org/-/user_settings/ssh_keys" ;
|
|
66
|
+
ok=1 ;
|
|
67
|
+
fi
|
|
68
|
+
return ${ok} ;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
# Run a project's pipeline (or one job) with the green-gate framing.
|
|
72
|
+
function gitlab_ci_local_run() {
|
|
73
|
+
local project_path="${WORKSPACE_ROOT}/${doc_name}/${PROJECT_NAME}";
|
|
74
|
+
|
|
75
|
+
if [ ! -d "${project_path}" ]; then
|
|
76
|
+
echo "No such project: ${project_path}";
|
|
77
|
+
return 1 ;
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
gitlab_ci_local_doctor || return 1 ;
|
|
81
|
+
cd "${project_path}" ;
|
|
82
|
+
|
|
83
|
+
# Pick the file: --slim prefers the project's committed .gitlab-ci-local.yml
|
|
84
|
+
# (the reproducible subset); otherwise the real pipeline.
|
|
85
|
+
local ci_args="";
|
|
86
|
+
local runner="drupal-ci-local";
|
|
87
|
+
if [ "${SLIM}" == 'yes' ] ; then
|
|
88
|
+
if [ ! -f ".gitlab-ci-local.yml" ]; then
|
|
89
|
+
echo "No .gitlab-ci-local.yml in this project — run without --slim, or add one";
|
|
90
|
+
echo "(see the webship-gitlab-ci-local-runner skill for the pattern).";
|
|
91
|
+
return 1 ;
|
|
92
|
+
fi
|
|
93
|
+
ci_args="--file .gitlab-ci-local.yml";
|
|
94
|
+
runner="gitlab-ci-local"; # the slim file is self-contained, no templates
|
|
95
|
+
elif [ ! -f ".gitlab-ci.yml" ]; then
|
|
96
|
+
echo "No .gitlab-ci.yml here — nothing to run.";
|
|
97
|
+
return 1 ;
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
if [ ! "${VARIABLE}" == '_none_' ] ; then
|
|
101
|
+
ci_args="${ci_args} --variable ${VARIABLE}";
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
# gitignore the artifacts dir once, quietly.
|
|
105
|
+
if [ -d .git ] && ! grep -qs '^\.gitlab-ci-local/' .gitignore 2>/dev/null ; then
|
|
106
|
+
echo ".gitlab-ci-local/" >> .gitignore ;
|
|
107
|
+
echo "Added .gitlab-ci-local/ to .gitignore (artifacts and logs land there)." ;
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
if [ "${LIST}" == 'yes' ] ; then
|
|
111
|
+
${runner} ${ci_args} --list ;
|
|
112
|
+
return $? ;
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
echo "*---------------------------------------------------------------------*";
|
|
116
|
+
echo " Green-gate run: ${doc_name}/${PROJECT_NAME}${JOB:+ — job: ${JOB}}";
|
|
117
|
+
echo "*---------------------------------------------------------------------*";
|
|
118
|
+
|
|
119
|
+
local output_file;
|
|
120
|
+
output_file=$(mktemp) ;
|
|
121
|
+
if [ -n "${JOB}" ] && [ ! "${JOB}" == '_none_' ] ; then
|
|
122
|
+
${runner} ${ci_args} "${JOB}" 2>&1 | tee "${output_file}" ;
|
|
123
|
+
else
|
|
124
|
+
${runner} ${ci_args} 2>&1 | tee "${output_file}" ;
|
|
125
|
+
fi
|
|
126
|
+
local status=${PIPESTATUS[0]} ;
|
|
127
|
+
|
|
128
|
+
# Known blocker: gitlab-ci-local crashes evaluating any rule whose =~ regex
|
|
129
|
+
# embeds a $variable (firecow/gitlab-ci-local#1893), and drupal/gitlab_templates
|
|
130
|
+
# has used that pattern for years — every ref, every gitlab-ci-local version.
|
|
131
|
+
# Until that lands upstream, the slim .gitlab-ci-local.yml is the only
|
|
132
|
+
# runnable path for a templates-based project.
|
|
133
|
+
if [ ${status} -ne 0 ] && grep -q 'Error attempting to evaluate the following rules' "${output_file}" ; then
|
|
134
|
+
echo "";
|
|
135
|
+
echo "This is firecow/gitlab-ci-local#1893: a \$variable nested inside an =~ regex";
|
|
136
|
+
echo "crashes rule evaluation, and drupal/gitlab_templates uses that pattern on";
|
|
137
|
+
echo "every ref. The full templates pipeline cannot run locally until that bug";
|
|
138
|
+
echo "is fixed upstream. Run the reproducible subset instead:";
|
|
139
|
+
echo " bash cmd-tools-gitlab-ci-local.sh ${PROJECT_NAME} --slim";
|
|
140
|
+
echo "(add a .gitlab-ci-local.yml first if the project has none — the";
|
|
141
|
+
echo "webship-gitlab-ci-local-runner skill carries the pattern), and gate the";
|
|
142
|
+
echo "template-only jobs on the remote pipeline.";
|
|
143
|
+
fi
|
|
144
|
+
rm -f "${output_file}" ;
|
|
145
|
+
|
|
146
|
+
echo "";
|
|
147
|
+
if [ ${status} -eq 0 ] ; then
|
|
148
|
+
echo "GREEN — every executed job passed. Jobs that cannot run locally are";
|
|
149
|
+
echo "not a pass: gate those on the remote pipeline before merging.";
|
|
150
|
+
else
|
|
151
|
+
echo "RED (exit ${status}) — the push is blocked. Fix the failing job and";
|
|
152
|
+
echo "re-run; never mask it with allow_failure or || true.";
|
|
153
|
+
fi
|
|
154
|
+
cd "${WORKSPACE_ROOT}/${doc_name}";
|
|
155
|
+
return ${status} ;
|
|
156
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# The command layer over fun-ddev-hostnames.sh: one project, or a listing of the
|
|
4
|
+
# whole workspace. Kept apart from the functions that touch DDEV so the reporting
|
|
5
|
+
# path cannot accidentally write anything.
|
|
6
|
+
|
|
7
|
+
function hostnames_command() {
|
|
8
|
+
local workspace_dir="${WORKSPACE_ROOT}/${doc_name}"
|
|
9
|
+
local project="${PROJECT_NAME}"
|
|
10
|
+
|
|
11
|
+
if [ -z "${project}" ] || [ "${project}" == '_none_' ] ; then
|
|
12
|
+
hostnames_list_workspace ;
|
|
13
|
+
return 0 ;
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
project="$(trim_project_name "${project}")"
|
|
17
|
+
local dir="${workspace_dir}/${project}"
|
|
18
|
+
if [ ! -d "${dir}" ] ; then
|
|
19
|
+
echo "No project '${project}' in ${workspace_dir}." ; return 1 ;
|
|
20
|
+
fi
|
|
21
|
+
if [ ! -f "${dir}/.ddev/config.yaml" ] ; then
|
|
22
|
+
echo "'${project}' is not a DDEV project — there is no hostname to change." ; return 1 ;
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
local changed='no'
|
|
26
|
+
if [ "${REMOVE}" != '_none_' ] && [ -n "${REMOVE}" ] ; then
|
|
27
|
+
ddev_hostnames_remove "${dir}" "${REMOVE}" || return 1 ;
|
|
28
|
+
changed='yes' ;
|
|
29
|
+
fi
|
|
30
|
+
local to_add=()
|
|
31
|
+
[ "${ADD}" != '_none_' ] && [ -n "${ADD}" ] && to_add+=("${ADD}")
|
|
32
|
+
if [ "${WITH_WORKSPACE}" == 'yes' ] ; then
|
|
33
|
+
to_add+=("$(ddev_workspace_hostname "${project}" "${doc_name}")")
|
|
34
|
+
fi
|
|
35
|
+
if [ "${#to_add[@]}" -gt 0 ] ; then
|
|
36
|
+
echo "Adding to ${doc_name}/${project}:" ;
|
|
37
|
+
ddev_hostnames_add "${dir}" "${to_add[@]}" || return 1 ;
|
|
38
|
+
changed='yes' ;
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
echo "" ;
|
|
42
|
+
echo "*---------------------------------------------------------------------*" ;
|
|
43
|
+
echo " ${doc_name}/${project} answers at" ;
|
|
44
|
+
echo "*---------------------------------------------------------------------*" ;
|
|
45
|
+
ddev_hostnames_report "${dir}" "${project}" "${doc_name}" ;
|
|
46
|
+
|
|
47
|
+
# --start is honoured whether or not anything changed here. It was gated on
|
|
48
|
+
# `changed` at first, so `--start` on a project whose hostname was added a
|
|
49
|
+
# minute ago printed the report and did nothing — and the hostname stayed 404,
|
|
50
|
+
# which looks exactly like the feature not working.
|
|
51
|
+
if [ "${changed}" == 'yes' ] || [ "${START}" == 'yes' ] ; then
|
|
52
|
+
if [ "${START}" == 'yes' ] ; then
|
|
53
|
+
echo "" ;
|
|
54
|
+
echo "Starting the project so the router picks the change up…" ;
|
|
55
|
+
( cd "${dir}" && ddev start -y ) || return 1 ;
|
|
56
|
+
else
|
|
57
|
+
echo "" ;
|
|
58
|
+
echo " Not live yet: a hostname reaches the router on the next start." ;
|
|
59
|
+
echo " Re-run with --start, or: cd ${dir} && ddev start" ;
|
|
60
|
+
fi
|
|
61
|
+
fi
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# Every project in this workspace and what it answers at. The reason this exists
|
|
65
|
+
# as a listing: two projects claiming one hostname is invisible one project at a
|
|
66
|
+
# time, and it is exactly the mistake --with-workspace exists to avoid.
|
|
67
|
+
function hostnames_list_workspace() {
|
|
68
|
+
local workspace_dir="${WORKSPACE_ROOT}/${doc_name}" d p extra tld
|
|
69
|
+
tld="$(ddev_project_tld)"
|
|
70
|
+
echo "*---------------------------------------------------------------------*" ;
|
|
71
|
+
echo " ${doc_name}: what each project answers at (TLD: ${tld})" ;
|
|
72
|
+
echo "*---------------------------------------------------------------------*" ;
|
|
73
|
+
local found=0
|
|
74
|
+
for d in "${workspace_dir}"/*/ ; do
|
|
75
|
+
[ -d "${d}" ] || continue
|
|
76
|
+
p="$(basename "${d}")"
|
|
77
|
+
[ -f "${d}/.ddev/config.yaml" ] || continue
|
|
78
|
+
found=$((found+1))
|
|
79
|
+
extra="$(ddev_hostnames_list "${d}" | paste -sd' ' -)"
|
|
80
|
+
printf " %-34s %s\n" "${p}" "$(ddev_project_name "${d}" 2>/dev/null).${tld}" ;
|
|
81
|
+
[ -n "${extra}" ] && printf " %-34s + %s\n" "" "${extra}" ;
|
|
82
|
+
done
|
|
83
|
+
[ "${found}" -eq 0 ] && echo " no DDEV projects here." ;
|
|
84
|
+
echo "" ;
|
|
85
|
+
echo " Add one: bash cmd-tools-hostnames.sh <project> --add <label> --start" ;
|
|
86
|
+
echo " Or the flat, workspace-qualified one (<project>-${doc_name}):" ;
|
|
87
|
+
echo " bash cmd-tools-hostnames.sh <project> --with-workspace --start" ;
|
|
88
|
+
}
|