@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
package/README.md
CHANGED
|
@@ -1,380 +1,44 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Webship Workspace
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
served at **https://workspace.ddev.site** through DDEV.
|
|
3
|
+
A container-based development workspace with a web dashboard, for Webship projects: Drupal, Drupal CMS, the Webship products, and whatever else your folders hold. The core ships **empty**. Everything else is a plugin you add when you need it.
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
in `public/htmx.min.js`). All pages are server-rendered; interactions swap in
|
|
8
|
-
HTML fragments. Destructive actions ask in one shared confirm dialog — Wait!
|
|
9
|
-
Are you sure you want to proceed with this action? — and fire on its Yes alone.
|
|
5
|
+

|
|
10
6
|
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
The toolbar says, beside the product name, and `core/workspace-app/scripts/update.sh --check`
|
|
14
|
-
says the same thing. Both read **`core/workspace-app/.app-version`**, a file holding a tag and
|
|
15
|
-
nothing else.
|
|
16
|
-
|
|
17
|
-
It is written by all three things that install this tree, which is the point:
|
|
18
|
-
|
|
19
|
-
| | writes the stamp |
|
|
20
|
-
| --- | --- |
|
|
21
|
-
| `core/scripts/install.sh` | the latest release tag, read from the repository |
|
|
22
|
-
| `core/scripts/sync-tooling.sh --pull` | the tag the clone is sitting on |
|
|
23
|
-
| `core/workspace-app/scripts/update.sh` | the tag it just installed |
|
|
24
|
-
|
|
25
|
-
Before that only the **updater** wrote it, so a machine installed any other way answered
|
|
26
|
-
`Installed: (untracked)` and was told an update was available to the version it already had —
|
|
27
|
-
for ever. With one person that is a curiosity; across a team it is the support question nobody
|
|
28
|
-
can answer, and an update prompt everyone learns to ignore.
|
|
29
|
-
|
|
30
|
-
**When it cannot be told, it says so** — `version unknown` in the toolbar, with the three
|
|
31
|
-
commands that would set it in the tooltip. A wrong version is worse than an absent one, because
|
|
32
|
-
it stops the question being asked.
|
|
33
|
-
|
|
34
|
-
`package.json`'s `"version"` is **not** it. That is npm metadata for an app that is never
|
|
35
|
-
published, it has said `1.0.0` since the first commit, and a unit test fails if anything starts
|
|
36
|
-
displaying it.
|
|
37
|
-
|
|
38
|
-
## One `ddev start` at a time
|
|
39
|
-
|
|
40
|
-
Every router-mutating verb — `start`, `stop`, `restart`, `poweroff`, `delete` — tears down the
|
|
41
|
-
**one shared** `ddev-router` and rebuilds it with the routes of whatever is running. Two at once
|
|
42
|
-
race on a single container, and the loser can leave it removed: every `*.ddev.site` address dies,
|
|
43
|
-
the hub included, with healthy web containers behind it, and DDEV then refuses to start anything
|
|
44
|
-
until `ddev poweroff`. Five clicks in thirty-eight seconds did exactly that.
|
|
45
|
-
|
|
46
|
-
`core/scripts/ddev-shim/ddev` is a wrapper that holds a lock for those five verbs and `exec`s the
|
|
47
|
-
real binary for everything else. It is **first on PATH inside the dashboard's container**
|
|
48
|
-
(`/usr/local/sbin` precedes `/usr/local/bin`), so it covers the assistant's Bash calls, the
|
|
49
|
-
`cmd-*.sh` scripts, the Web IDE's terminals and anyone in `ddev ssh` — not just the buttons.
|
|
50
|
-
`install.sh` offers the same file on the host, where it needs root.
|
|
51
|
-
|
|
52
|
-
Four rules it lives by, because a wrong wrapper breaks *every* `ddev` call including the
|
|
53
|
-
dashboard's own twenty-second status reads:
|
|
54
|
-
|
|
55
|
-
1. the real binary is found by **absolute path** and checked not to be the wrapper — resolving
|
|
56
|
-
through PATH would find the wrapper again and fork for ever;
|
|
57
|
-
2. anything that is not a router verb is `exec`'d with **no lock and no subshell** —
|
|
58
|
-
`ddev list --json-output` costs what it always cost, and read-only verbs still run in parallel;
|
|
59
|
-
3. **nothing is fatal** — a missing `flock`, an uncreatable lock file, and it says so once and runs
|
|
60
|
-
the command anyway, because refusing to run `ddev` is worse than the fault being prevented;
|
|
61
|
-
4. it **never re-locks a lock already held**. The dashboard wraps its own calls, and taking the same
|
|
62
|
-
lock from inside deadlocks for the full 1800s timeout — proven by experiment before
|
|
63
|
-
`DDEV_ROUTER_LOCK_HELD` existed. Whoever holds the lock sets it; the wrapper exports it onward.
|
|
64
|
-
|
|
65
|
-
The shim exists twice, because Docker cannot `COPY` from outside its build context:
|
|
66
|
-
`core/scripts/ddev-shim/ddev` is the source, `.ddev/web-build/ddev-shim-ddev` is the copy the image
|
|
67
|
-
takes, and a unit test fails if they differ.
|
|
68
|
-
|
|
69
|
-
## The Web IDE (code-server)
|
|
70
|
-
|
|
71
|
-
Every project row carries a **Codebase** menu, right after SCREENS, and every document
|
|
72
|
-
workspace (`docs`, `worklogs`, `specs`, the `ai-*` folders) carries a **Files** one. Both offer
|
|
73
|
-
the same three destinations, and the split is the point — it is GitLab's, and it is what stops
|
|
74
|
-
a link that silently does nothing:
|
|
75
|
-
|
|
76
|
-
| | opens | needs |
|
|
77
|
-
| --- | --- | --- |
|
|
78
|
-
| **Web IDE** | VS Code in the browser, at `https://ide.<hub_domain>/?folder=<path>` | nothing — works from any device |
|
|
79
|
-
| **Visual Studio Code** | `vscode://file<path>` — the VS Code on the machine the *browser* is running on | the `vscode://` handler, which VS Code registers on install |
|
|
80
|
-
| **IntelliJ IDEA** | `jetbrains://idea/open?file=<path>` — likewise, IDEA on that machine | the JetBrains Toolbox URL handler |
|
|
81
|
-
| **Copy the path** | the path, for `code <path>` or `idea <path>` in a terminal | nothing |
|
|
82
|
-
|
|
83
|
-
**It is code-server, pinned, on its own hostname.** `4.135.0` is baked into
|
|
84
|
-
`.ddev/web-build/Dockerfile.workspace-app` from the standalone tarball — pinned because an
|
|
85
|
-
editor that changes under people between image rebuilds is a support question nobody can
|
|
86
|
-
answer. It runs as a `web_extra_daemon` bound to **127.0.0.1:8443**, and
|
|
87
|
-
`.ddev/nginx_full/nginx-site.conf` proxies `ide.workspace.ddev.site` to it. Loopback plus that
|
|
88
|
-
one vhost is the whole access control.
|
|
89
|
-
|
|
90
|
-
A **hostname, not a subpath**: code-server is a single-page app that builds absolute URLs for
|
|
91
|
-
its workers, its websocket and its static assets, and upstream's guidance is a dedicated
|
|
92
|
-
(sub)domain. It costs nothing here — `*.workspace` is already in `additional_hostnames`, so
|
|
93
|
-
DDEV's router routes it and the project certificate already covers it. The vhost uses an
|
|
94
|
-
**exact** `server_name` so it wins over the regex block that sends everything else to the Node
|
|
95
|
-
app, and carries the websocket `Upgrade`/`Connection` headers plus long read timeouts —
|
|
96
|
-
without those the editor loads and then hangs "reconnecting…", because the terminal, the
|
|
97
|
-
extension host and the file watcher are all websockets.
|
|
98
|
-
|
|
99
|
-
**Its state lives in the workspace tree**, at `.code-server/` (gitignored): settings,
|
|
100
|
-
keybindings and installed extensions survive an image rebuild, which they would not if they
|
|
101
|
-
sat in the container.
|
|
102
|
-
|
|
103
|
-
**When it is down the menu says so** rather than offering a dead link — a cached loopback
|
|
104
|
-
probe, warmed at boot so the first render after a restart already knows. The note names the
|
|
105
|
-
fix: `ddev restart`, or `docker exec ddev-workspace-web supervisorctl status`.
|
|
106
|
-
|
|
107
|
-
### What makes it work — the actual options
|
|
108
|
-
|
|
109
|
-
**Serving it** (`scripts/code-server-start.sh`, run as a `web_extra_daemon`):
|
|
110
|
-
|
|
111
|
-
| flag | why |
|
|
112
|
-
| --- | --- |
|
|
113
|
-
| `--bind-addr 127.0.0.1:8443` | loopback only; the `ide.*` vhost is the whole access control |
|
|
114
|
-
| `--auth none` | see the security note below — not a casual choice |
|
|
115
|
-
| `--user-data-dir`, `--extensions-dir` under `.code-server/` | settings and extensions survive an image rebuild |
|
|
116
|
-
| `--disable-telemetry`, `--disable-update-check` | nothing phones home; the version is pinned in the image |
|
|
117
|
-
| `--app-name 'Webship Workspace IDE'` | the title bar and welcome page say where you are |
|
|
118
|
-
|
|
119
|
-
**Nginx**, in `.ddev/nginx_full/nginx-site.conf`: an **exact** `server_name ide.workspace.ddev.site`
|
|
120
|
-
(beats the regex block that routes everything else to the Node app), `proxy_set_header Upgrade` +
|
|
121
|
-
`Connection $connection_upgrade` with a `map` for it, `proxy_read_timeout 86400s`,
|
|
122
|
-
`proxy_buffering off`, `client_max_body_size 0`. The websocket headers are not optional: the
|
|
123
|
-
terminal, the extension host and the file watcher are all websockets, and without them the editor
|
|
124
|
-
loads and then hangs *reconnecting…*.
|
|
125
|
-
|
|
126
|
-
**Editor settings**, seeded once into `.code-server/data/User/settings.json` (never overwritten, so
|
|
127
|
-
your own changes stick):
|
|
128
|
-
|
|
129
|
-
| setting | why |
|
|
130
|
-
| --- | --- |
|
|
131
|
-
| `security.workspace.trust.enabled: false` | VS Code opens every folder in **Restricted Mode** and refuses to start a terminal until you answer *"Do you trust the authors…"*. That prompt is for code you downloaded; here every folder is a project on this machine, opened from a dashboard that already offers a shell |
|
|
132
|
-
| `terminal.integrated.profiles.linux` → **Claude Code**, **Claude Code (accept edits)** | the terminal dropdown offers them by name, so agents and skills are one click away instead of requiring you to know to type `claude` |
|
|
133
|
-
| `files.associations` → `.module`, `.install`, `.theme`, `.profile`, `.engine`, `.inc` as PHP | without it the editor treats the files a Drupal developer opens most as plain text: no highlighting, no outline |
|
|
134
|
-
| `files.exclude` / `search.exclude` → `node_modules`, `vendor`, `web/core`, `web/modules/contrib` | a Drupal site is ~21,000 PHP files of which almost none are yours; search is useless otherwise |
|
|
135
|
-
| `files.watcherExclude` → the same trees plus `.git/objects`, `graphify-out`, `.ddev` | **one** built Drupal project is ~21,000 directories, 11,800 of them in those three trees, against a kernel limit of 65,536 watches **shared across the machine**. Without this, two open projects and the editor reports *Unable to watch for file changes* and silently stops noticing edits made outside it — a `composer install`, a `git checkout`, an agent |
|
|
136
|
-
| `extensions.autoUpdate: "off"` | the same reason code-server is pinned |
|
|
137
|
-
| `workbench.startupEditor: "none"`, `update.mode: "none"`, `telemetry.telemetryLevel: "off"` | no welcome page, no update nag, no telemetry |
|
|
138
|
-
|
|
139
|
-
### Claude Code is in the editor, when it is configured
|
|
140
|
-
|
|
141
|
-
The official extension (**`Anthropic.claude-code`**, on Open VSX — which is the registry
|
|
142
|
-
code-server queries, so no marketplace switch and no `.vsix` juggling) is installed by
|
|
143
|
-
`scripts/code-server-start.sh` on first start, and appears in the activity bar with its own
|
|
144
|
-
chat (`Ctrl+Alt+I`).
|
|
145
|
-
|
|
146
|
-
**Gated on Claude Code being usable here**, which means two things: the `claude` CLI on PATH, and
|
|
147
|
-
a credentials file in `~/.claude` (the container bind-mounts it from the host). On a machine where
|
|
148
|
-
Claude Code has never been logged in, installing it would put a panel in the editor whose only
|
|
149
|
-
behaviour is to ask for a login that belongs on the host — so there the IDE keeps the terminal
|
|
150
|
-
profiles and nothing else, and the script says so. Log in on the host with `claude`, then
|
|
151
|
-
`ddev restart`.
|
|
152
|
-
|
|
153
|
-
Installed **once**, when missing, with a timeout, and never fatally: an editor that will not start
|
|
154
|
-
because a registry was slow is worse than an editor without one extension. `extensions.autoUpdate`
|
|
155
|
-
is `"off"` for the same reason the code-server version is pinned.
|
|
156
|
-
|
|
157
|
-
### Agents and skills are already loaded
|
|
158
|
-
|
|
159
|
-
Nothing to install per project. The IDE runs **inside the dashboard's container**, which bind-mounts
|
|
160
|
-
`~/.claude` — so a terminal there has the `claude` CLI with the **same agents, skills and commands as
|
|
161
|
-
a session on the host** (86 / 42 / 6 on this machine), and Claude Code reads `CLAUDE.md` and
|
|
162
|
-
`AGENTS.md` from the working directory upwards, so the folder's own rules apply automatically.
|
|
163
|
-
|
|
164
|
-
In the IDE: **Terminal → new terminal dropdown → Claude Code**. Or type `claude` in any terminal.
|
|
165
|
-
Inside it, `@` and `/` list the same items the dashboard's assistant offers, because they are the
|
|
166
|
-
same files.
|
|
167
|
-
|
|
168
|
-
**For local VS Code / IntelliJ** (the other two entries in the menu) nothing is configured — they
|
|
169
|
-
open the folder on your own machine, with your own settings and your own extensions. Agents and
|
|
170
|
-
skills come from your own `~/.claude` there, which is the point of that split.
|
|
171
|
-
|
|
172
|
-
### Security posture, stated plainly
|
|
173
|
-
|
|
174
|
-
**This dashboard has no authentication, and that is only safe because it is loopback-only.**
|
|
175
|
-
It runs shell commands, serves an interactive terminal at `/terminal/<session>`, and a Web IDE
|
|
176
|
-
with write access to the whole tree and a terminal of its own — in a container that mounts the
|
|
177
|
-
Docker socket and the DDEV registry. Anyone who can reach the port has all of it.
|
|
178
|
-
|
|
179
|
-
What keeps that acceptable is that nothing is reachable from the network: DDEV's router binds
|
|
180
|
-
`127.0.0.1` (`router_bind_all_interfaces: false`, its default) and the machine answers nothing
|
|
181
|
-
on its LAN address.
|
|
182
|
-
|
|
183
|
-
**Two settings end that**, and both get changed for a good-looking reason:
|
|
184
|
-
|
|
185
|
-
| setting | why someone changes it |
|
|
186
|
-
| --- | --- |
|
|
187
|
-
| `router_bind_all_interfaces: true` | DDEV documents it for Let's Encrypt, and for reaching a project from a phone |
|
|
188
|
-
| `hub_domain: <a public domain>` | this README says the same system runs as a remote hub |
|
|
189
|
-
|
|
190
|
-
So both are watched for, in the two places a person will be:
|
|
191
|
-
|
|
192
|
-
- **`install.sh --check`** prints `✓ exposure loopback only` or a block naming the setting that
|
|
193
|
-
changed and what is reachable because of it;
|
|
194
|
-
- **the dashboard itself** shows a banner on every page, not dismissible, because the person who
|
|
195
|
-
flips that setting a month later is not running the installer.
|
|
196
|
-
|
|
197
|
-
If the hub is ever put on a public domain, the dashboard **and** the IDE need real
|
|
198
|
-
authentication in front of them. One decision, not two.
|
|
199
|
-
|
|
200
|
-
### Other things the security pass fixed
|
|
201
|
-
|
|
202
|
-
- `core/config/settings.yml` (real API keys) and `.screens/.runner-token` (the screen runner's
|
|
203
|
-
entire access control) were **world-readable at `775`** while the CLI-managed secrets beside
|
|
204
|
-
them were correctly `600`. Both are `600` now.
|
|
205
|
-
- One **high-severity** dependency advisory (`js-yaml`, exponential parsing → DoS) — fixed.
|
|
206
|
-
- Security headers were set at **three** `writeHead` sites out of fifty-six, so every page but
|
|
207
|
-
the graph viewer went without. They are set once in the request handler now: `nosniff`,
|
|
208
|
-
`no-referrer`, `SAMEORIGIN`.
|
|
209
|
-
|
|
210
|
-
### The IDE’s own posture
|
|
211
|
-
|
|
212
|
-
`--auth none`. The dashboard has no login of its own until Sign in with Google (`auth.google`) is
|
|
213
|
-
turned on, and it already serves a real interactive terminal at `/terminal/<session>`, so a second
|
|
214
|
-
password in front of one door would be theatre.
|
|
215
|
-
What this means concretely: **anyone who can reach the dashboard's origin can edit any file in
|
|
216
|
-
`~/workspace` and run commands in that container**, which has the Docker socket and the DDEV
|
|
217
|
-
registry mounted.
|
|
218
|
-
|
|
219
|
-
That is acceptable for a local tool on `*.ddev.site` and **not** acceptable on a public
|
|
220
|
-
`hub_domain`. If the hub is ever put on a public domain, the IDE *and* the dashboard need real
|
|
221
|
-
authentication in front of them — the same decision, not two.
|
|
222
|
-
|
|
223
|
-
## What it does
|
|
224
|
-
|
|
225
|
-
- **Home** (`/`): the workspace cards grid — one card per folder in
|
|
226
|
-
`core/config/settings.yml`'s `workspaces:` list (read live, so adding a
|
|
227
|
-
workspace there shows up without code changes), with live project counts.
|
|
228
|
-
- **Per-workspace pages** (`/dev`, `/test`, `/demos`, …): each workspace's own
|
|
229
|
-
project list with per-project **Backup / Filemode / Remove** actions, plus a
|
|
230
|
-
**Build** form listing that folder's `cmd-*-project.sh` builder scripts.
|
|
231
|
-
- **AI Assistant** on every page (inline on home, floating 🤖 widget on
|
|
232
|
-
workspace pages): quick actions (New Drupal 11, New Webship, Status) and a
|
|
233
|
-
free-text chat backed by the local `claude` CLI in restricted, tool-free
|
|
234
|
-
print mode.
|
|
235
|
-
- All actions run the real `cmd-*.sh` scripts (and `ddev`) against
|
|
236
|
-
`~/workspace` — this is a control panel, not a mock.
|
|
237
|
-
|
|
238
|
-
## Setup
|
|
239
|
-
|
|
240
|
-
You need the workspace files and DDEV. The quickest way to the files is the ZIP — no git, no
|
|
241
|
-
clone: on [github.com/webship/workspace](https://github.com/webship/workspace) switch to the `1.0.x`
|
|
242
|
-
branch, press **Code ▾ → Download ZIP**, unzip it and rename the folder to `~/workspace` (the full
|
|
243
|
-
walkthrough, and two other ways, are in the [root README](docs/REFERENCE.md#get-started)).
|
|
244
|
-
|
|
245
|
-
Then, once:
|
|
7
|
+
## Install
|
|
246
8
|
|
|
247
9
|
```bash
|
|
248
|
-
|
|
249
|
-
|
|
10
|
+
# 1. Node.js 20 or newer, Docker, and DDEV (https://ddev.readthedocs.io)
|
|
11
|
+
# 2. The workspace, from npm
|
|
12
|
+
npm install -g @webship.co/workspace
|
|
13
|
+
webship-workspace init ~/workspace # the core, an empty settings file, the dashboard started
|
|
250
14
|
```
|
|
251
15
|
|
|
252
|
-
|
|
253
|
-
restoring and removing projects — can be done from there without another command.
|
|
254
|
-
|
|
255
|
-
### How it runs
|
|
256
|
-
|
|
257
|
-
The Node app runs **inside** the DDEV web container as a `web_extra_daemon`,
|
|
258
|
-
with Docker-outside-of-Docker so it can manage sibling DDEV projects:
|
|
259
|
-
|
|
260
|
-
- `.ddev/docker-compose.dood.yaml` bind-mounts the host's
|
|
261
|
-
`/var/run/docker.sock` and your `~/workspace` tree (at the same absolute
|
|
262
|
-
path, via `${HOME}` interpolation).
|
|
263
|
-
- `.ddev/web-build/Dockerfile.workspace-app` installs the `docker` CLI and the
|
|
264
|
-
`ddev` binary in the web image, and aligns the container's `docker` group
|
|
265
|
-
GID with the host's.
|
|
266
|
-
- `.ddev/nginx_full/nginx-site.conf` proxies the site to the app on
|
|
267
|
-
`127.0.0.1:3000` inside the container.
|
|
16
|
+
Open https://workspace.ddev.site. It is empty: no workspace folders, no plugins. Add what you need, one package at a time, from **Settings → Plugins** (the catalogue) or the command line:
|
|
268
17
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
`groupmod`/`usermod` line in `.ddev/web-build/Dockerfile.workspace-app`
|
|
276
|
-
(which is what `sg docker` in the supervisord command resolves) and
|
|
277
|
-
`group_add` in `.ddev/docker-compose.dood.yaml` (which is what actually puts
|
|
278
|
-
the running process in the group — DDEV pins `user: 1000:1000`, so a
|
|
279
|
-
build-time `usermod` never reaches it).
|
|
280
|
-
|
|
281
|
-
`core/scripts/docker-gid.sh` writes both from the host's socket.
|
|
282
|
-
`core/scripts/install.sh` runs it at setup and reports it in its survey, and
|
|
283
|
-
`core/scripts/sync-tooling.sh` runs it **after** mirroring — this directory is
|
|
284
|
-
mirrored wholesale, so a hand edit would be overwritten by the next `--pull`.
|
|
285
|
-
Check it any time:
|
|
286
|
-
|
|
287
|
-
```
|
|
288
|
-
bash core/scripts/docker-gid.sh --check
|
|
289
|
-
```
|
|
290
|
-
- **The DDEV project registry** (`~/.ddev`) is bind-mounted in, so `ddev list`
|
|
291
|
-
in here sees the same projects as the host. Without it the container has its
|
|
292
|
-
own empty registry and reports one project — itself — which produces the same
|
|
293
|
-
"everything is Stopped" symptom by a different route.
|
|
294
|
-
- **Bind-mounted host paths are a trap Docker sets.** A bind mount whose source
|
|
295
|
-
does not exist is *created* — as a directory, owned by root. Every optional tool
|
|
296
|
-
the dashboard shares from the host is such a source, so on a machine without
|
|
297
|
-
`twg` the first start used to create `~/.local/bin/twg` **and `~/.local/bin`**
|
|
298
|
-
as root: the JIRA button then never appeared however complete `jira:` was, and
|
|
299
|
-
nothing could install a user binary there any more, including the
|
|
300
|
-
`drupal-ci-local` wrapper the GitLab CI green-gate writes.
|
|
301
|
-
|
|
302
|
-
`core/scripts/host-mounts.sh` creates each of those paths as you before Docker
|
|
303
|
-
can, and comments the `twg` volume out of `.ddev/docker-compose.twg.yaml` while
|
|
304
|
-
`twg` is not installed — restoring it the moment it is. It runs from the
|
|
305
|
-
project's own `pre-start` hook and from `install.sh`. `--check` reports without
|
|
306
|
-
changing anything, and it names the paths only root can hand back.
|
|
307
|
-
- **Jira** needs the Teamwork Graph CLI on the host:
|
|
308
|
-
[teamworkgraph.com/cli](https://teamworkgraph.com/cli) ·
|
|
309
|
-
[developer.atlassian.com/cloud/twg-cli](https://developer.atlassian.com/cloud/twg-cli/)
|
|
310
|
-
```
|
|
311
|
-
curl -fsSL --retry 2 https://teamwork-graph.atlassian.com/cli/install | bash
|
|
312
|
-
~/.local/bin/twg doctor
|
|
313
|
-
```
|
|
314
|
-
It is mounted in rather than installed in the image: one binary, one OAuth
|
|
315
|
-
session, and `twg login` on the host reaches the container instantly. When it is
|
|
316
|
-
absent the JIRA button renders **disabled**, with the reason in its tooltip,
|
|
317
|
-
rather than vanishing.
|
|
318
|
-
- **Upsun** needs its CLI on the host, mounted in the same way and for the same
|
|
319
|
-
reason as `twg` — one binary, one session:
|
|
320
|
-
[developer.upsun.com/cli](https://developer.upsun.com/cli)
|
|
321
|
-
|
|
322
|
-
Upsun's own installer sets up an apt repository, so it needs root and an
|
|
323
|
-
interactive password; in a pipe it fails with *"sudo: A terminal is required to
|
|
324
|
-
authenticate"*. `install.sh` therefore prefers the **release tarball** — one
|
|
325
|
-
static binary into `~/.local/bin`, no root at all — and falls back to the
|
|
326
|
-
official installer only if GitHub is unreachable:
|
|
18
|
+
```bash
|
|
19
|
+
webship-workspace plugin require dev # npm install @webship.co/workspace-dev into the dashboard
|
|
20
|
+
webship-workspace plugin activate dev # on the workspaces list
|
|
21
|
+
webship-workspace plugin install dev # the folder, its settings file, its commands
|
|
22
|
+
webship-workspace catalog # everything you can add
|
|
23
|
+
```
|
|
327
24
|
|
|
328
|
-
|
|
329
|
-
ver=$(wget -qO- https://api.github.com/repos/upsun/cli/releases/latest \
|
|
330
|
-
| sed -n 's/.*"tag_name": *"v\([^"]*\)".*/\1/p' | head -1)
|
|
331
|
-
wget -qO- https://github.com/upsun/cli/releases/download/v$ver/upsun_${ver}_linux_amd64.tar.gz \
|
|
332
|
-
| tar -xz -C /tmp upsun && install -m 0755 /tmp/upsun ~/.local/bin/upsun
|
|
333
|
-
upsun login # browser OAuth; writes SSH certificates
|
|
334
|
-
```
|
|
25
|
+
Nothing is added to `package.json` until you ask for it. The skeleton and the management stay in the core.
|
|
335
26
|
|
|
336
|
-
|
|
337
|
-
writes a session into the host keyring, and a container cannot reach a keyring — so
|
|
338
|
-
every UPSUN action in the dashboard (the environment list, the live URLs, *Get
|
|
339
|
-
database & files*) authenticates with an API **token** instead:
|
|
27
|
+
## What a plugin is
|
|
340
28
|
|
|
341
|
-
|
|
342
|
-
# core/config/settings.yml
|
|
343
|
-
upsun:
|
|
344
|
-
cli_token: … # Upsun console → My profile → API tokens
|
|
345
|
-
```
|
|
29
|
+
An npm package `@webship.co/workspace-<name>` (repository `github.com/webship/workspace-<name>`, branch `1.0.x`), written in TypeScript against `@webship.co/workspace-plugin-api`. Families share a base: hosting providers (`upsun`, `acquia`, `digitalocean`, `cpanel`, `aws`, `azure`, `godaddy`), git forges (`github`, `gitlab`, `bitbucket`), container runtimes (`docker`, `lando`, `docksal`, `podman`, `kubernetes`), and every workspace folder (`dev`, `test`, `drupal-modules`, `drupal-themes`, `docs`, `images`, `ai-agents`, …) is a plugin too.
|
|
346
30
|
|
|
347
|
-
|
|
348
|
-
actions answer *"No Upsun API token configured"*; with the wrong **kind** of token
|
|
349
|
-
they answer *"The request could not be authorized. Unable to authenticate the
|
|
350
|
-
provided API token"* — which reads like an expiry. An **Atlassian** token in that
|
|
351
|
-
field, recognisable because they start `ATATT`, produces exactly that message.
|
|
352
|
-
`bash core/scripts/install.sh --check` reports the field by shape, never its value.
|
|
31
|
+
## Read more
|
|
353
32
|
|
|
354
|
-
|
|
33
|
+
**New here?** The dashboard's own guide is in [core/workspace-app/docs](core/workspace-app/docs): the [user guide](core/workspace-app/docs/USER-GUIDE.md) for the pages and what each button does (also served at `/help`), and the [developer guide](core/workspace-app/docs/DEVELOPER-GUIDE.md) for how the app is built.
|
|
355
34
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
-
|
|
362
|
-
container** (installed in the web image via `npm install -g
|
|
363
|
-
@anthropic-ai/claude-code`); it authenticates through your host's
|
|
364
|
-
`~/.claude` + `~/.claude.json`, which are bind-mounted in. If you've never
|
|
365
|
-
logged in to Claude Code on the host, run `claude` there once first.
|
|
366
|
-
- **Voice input**: the mic button uses the browser's Web Speech API
|
|
367
|
-
(Chrome/Edge; hidden automatically on browsers without support).
|
|
35
|
+
- [Getting started](core/docs/getting-started.md) — the first hour: install, add a workspace folder, build a site.
|
|
36
|
+
- [Plugins](core/docs/plugins.md) — the four steps, the families, writing one.
|
|
37
|
+
- [Workspaces](core/docs/workspaces.md) — folders, types, builders and the `cmd-*.sh` commands.
|
|
38
|
+
- [Testing](core/docs/testing.md) — unit tests and the webship-js browser suite.
|
|
39
|
+
- [Releases](core/docs/releases.md) — versions, npm, and how changes land (issues and pull requests).
|
|
40
|
+
- [The plugin contract](core/workspace-app/PLUGINS.md) — the manifest and the api, for plugin authors.
|
|
368
41
|
|
|
369
|
-
##
|
|
42
|
+
## License
|
|
370
43
|
|
|
371
|
-
|
|
372
|
-
**delete**) and has host-Docker access. The AI assistant runs in **agent
|
|
373
|
-
mode**: its `claude -p` calls are allowed Bash/Read/Glob/Grep inside the
|
|
374
|
-
container (Write/Edit stay disallowed, and its instructions forbid deleting
|
|
375
|
-
anything unasked), so a chat message can really build, start, stop, back up
|
|
376
|
-
and open projects — and steer the page afterwards via NAVIGATE/OPEN/REFRESH
|
|
377
|
-
directives. Every action and chat message is appended to `actions.log`.
|
|
378
|
-
It binds only to the DDEV-internal port and is meant for local development
|
|
379
|
-
machines — do not expose `workspace.ddev.site` beyond localhost without
|
|
380
|
-
adding authentication.
|
|
44
|
+
GPL-2.0-or-later. Made by [Webship](https://webship.co).
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* webship-workspace — install and manage a Webship Workspace from npm.
|
|
4
|
+
*
|
|
5
|
+
* webship-workspace init [dir] make a workspace at dir (default ~/workspace): the core, an
|
|
6
|
+
* empty settings file, the dashboard installed and started
|
|
7
|
+
* webship-workspace plugin <verb> <name> require | activate | install | configure | deactivate | uninstall | list
|
|
8
|
+
* webship-workspace catalog the plugins you can add, by family
|
|
9
|
+
* webship-workspace update [dir] refresh the core of an existing workspace from this package
|
|
10
|
+
*
|
|
11
|
+
* The core ships empty: no workspace folders, no plugins. Everything is added later, one npm package
|
|
12
|
+
* at a time, when you ask for it (`plugin require <name>` is `npm install @webship.co/workspace-<name>`
|
|
13
|
+
* into the dashboard's package.json). The skeleton and the management stay in the core.
|
|
14
|
+
*
|
|
15
|
+
* Plain Node, no dependencies: this runs before anything is installed. Env for tests:
|
|
16
|
+
* WEBSHIP_WORKSPACE_SKIP_NPM=1 do not run npm install in the dashboard
|
|
17
|
+
* WEBSHIP_WORKSPACE_SKIP_DDEV=1 do not start the dashboard
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const fs = require('fs');
|
|
21
|
+
const os = require('os');
|
|
22
|
+
const path = require('path');
|
|
23
|
+
const { spawnSync } = require('child_process');
|
|
24
|
+
|
|
25
|
+
const PKG_ROOT = path.resolve(__dirname, '..', '..'); // the package: core/, README.md, LICENSE
|
|
26
|
+
const CORE_SRC = path.join(PKG_ROOT, 'core');
|
|
27
|
+
|
|
28
|
+
const say = (s) => process.stdout.write(`${s}\n`);
|
|
29
|
+
const fail = (s, code = 1) => { process.stderr.write(`${s}\n`); process.exit(code); };
|
|
30
|
+
|
|
31
|
+
function run(cmd, args, cwd, env = {}) {
|
|
32
|
+
const r = spawnSync(cmd, args, { cwd, stdio: 'inherit', env: { ...process.env, ...env } });
|
|
33
|
+
if (r.error) fail(`${cmd} could not be run: ${r.error.message}`);
|
|
34
|
+
return r.status === 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Copy core/ into the workspace, skipping what belongs to a running install, never overwriting a settings file. */
|
|
38
|
+
function copyCore(dest) {
|
|
39
|
+
const SKIP = new Set(['node_modules', 'actions.log', 'package-lock.json']);
|
|
40
|
+
// This machine's own files are never copied from the package: settings.yml comes from the lean
|
|
41
|
+
// template (once), workspace and plugin settings come with their plugins, the install record is local.
|
|
42
|
+
const NEVER = /^core\/config\/(settings\.yml|workspace\..*\.settings\.yml|plugin\..*\.settings\.yml|plugins\.installed\.yml)$|^core\/workspace-app\/\.ddev\/config\.local\.yaml$/;
|
|
43
|
+
const KEEP_IF_PRESENT = /^core\/config\/style\.yml$/;
|
|
44
|
+
const walk = (src, rel) => {
|
|
45
|
+
for (const e of fs.readdirSync(src, { withFileTypes: true })) {
|
|
46
|
+
if (SKIP.has(e.name)) continue;
|
|
47
|
+
const from = path.join(src, e.name);
|
|
48
|
+
const relPath = path.join(rel, e.name);
|
|
49
|
+
const to = path.join(dest, relPath);
|
|
50
|
+
if (e.isDirectory()) { fs.mkdirSync(to, { recursive: true }); walk(from, relPath); continue; }
|
|
51
|
+
if (NEVER.test(relPath)) continue;
|
|
52
|
+
if (KEEP_IF_PRESENT.test(relPath) && fs.existsSync(to)) continue;
|
|
53
|
+
fs.mkdirSync(path.dirname(to), { recursive: true });
|
|
54
|
+
fs.copyFileSync(from, to);
|
|
55
|
+
fs.chmodSync(to, fs.statSync(from).mode & 0o777);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
walk(CORE_SRC, 'core');
|
|
59
|
+
// The dashboard's version chip reads this file, never package.json (an installation is not the package).
|
|
60
|
+
fs.writeFileSync(path.join(dest, 'core', 'workspace-app', '.app-version'), require(path.join(PKG_ROOT, 'package.json')).version + '\n');
|
|
61
|
+
for (const f of ['README.md', 'LICENSE']) if (fs.existsSync(path.join(PKG_ROOT, f)) && !fs.existsSync(path.join(dest, f))) fs.copyFileSync(path.join(PKG_ROOT, f), path.join(dest, f));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** settings.yml from the lean template: an empty workspaces list, no plugins, the placeholders to fill. */
|
|
65
|
+
function writeSettings(dest) {
|
|
66
|
+
const file = path.join(dest, 'core', 'config', 'settings.yml');
|
|
67
|
+
if (fs.existsSync(file)) return false;
|
|
68
|
+
const template = path.join(CORE_SRC, 'config', 'settings.template.yml');
|
|
69
|
+
fs.copyFileSync(template, file);
|
|
70
|
+
fs.chmodSync(file, 0o600);
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function catalogText() {
|
|
75
|
+
const { FAMILIES, SCOPE } = require(path.join(CORE_SRC, 'workspace-app', 'plugin-catalog.js'));
|
|
76
|
+
const lines = ['What you can add (one npm package each; nothing is installed until you ask):', ''];
|
|
77
|
+
for (const f of FAMILIES) {
|
|
78
|
+
lines.push(`${f.label} — ${f.about}`);
|
|
79
|
+
for (const [name, label] of f.plugins) lines.push(` ${name.padEnd(24)} ${label} (${SCOPE}/workspace-${name})`);
|
|
80
|
+
lines.push('');
|
|
81
|
+
}
|
|
82
|
+
lines.push('Add one: webship-workspace plugin require <name> then activate, install, configure — or Settings → Plugins in the dashboard.');
|
|
83
|
+
return lines.join('\n');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function init(dirArg, { update = false } = {}) {
|
|
87
|
+
const dest = path.resolve(dirArg || process.env.WEBSHIP_WORKSPACE_DIR || path.join(os.homedir(), 'workspace'));
|
|
88
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
89
|
+
say(`${update ? 'Updating' : 'Making'} the Webship Workspace at ${dest}`);
|
|
90
|
+
copyCore(dest);
|
|
91
|
+
const wroteSettings = writeSettings(dest);
|
|
92
|
+
say(wroteSettings ? ' core/config/settings.yml written (empty: no workspaces, no plugins yet)' : ' core/config/settings.yml kept as it is');
|
|
93
|
+
const app = path.join(dest, 'core', 'workspace-app');
|
|
94
|
+
if (!process.env.WEBSHIP_WORKSPACE_SKIP_NPM) {
|
|
95
|
+
say(' installing the dashboard (npm install in core/workspace-app)…');
|
|
96
|
+
if (!run('npm', ['install', '--no-audit', '--no-fund'], app)) fail('npm install failed in core/workspace-app.');
|
|
97
|
+
}
|
|
98
|
+
if (!process.env.WEBSHIP_WORKSPACE_SKIP_DDEV) {
|
|
99
|
+
const ddev = spawnSync('ddev', ['--version'], { encoding: 'utf8' });
|
|
100
|
+
if (ddev.error || ddev.status !== 0) {
|
|
101
|
+
say(' DDEV is not installed: the dashboard runs in a DDEV project. Install it (https://ddev.readthedocs.io) and run: webship-workspace init ' + (dirArg || ''));
|
|
102
|
+
} else {
|
|
103
|
+
say(' starting the dashboard (ddev start in core/workspace-app)…');
|
|
104
|
+
run('ddev', ['start', '-y'], app);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
say('');
|
|
108
|
+
say(`Done. The dashboard: https://workspace.ddev.site (the tooling: ${dest}/core/scripts)`);
|
|
109
|
+
say('');
|
|
110
|
+
say(catalogText());
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function plugin(verb, name) {
|
|
114
|
+
const verbs = ['require', 'activate', 'install', 'configure', 'deactivate', 'uninstall', 'list', 'restart'];
|
|
115
|
+
if (!verbs.includes(verb)) fail(`plugin <${verbs.join('|')}> [name]`);
|
|
116
|
+
const root = process.env.WORKSPACE_ROOT || path.resolve(process.env.WEBSHIP_WORKSPACE_DIR || path.join(os.homedir(), 'workspace'));
|
|
117
|
+
const script = path.join(root, 'core', 'scripts', 'plugins.sh');
|
|
118
|
+
if (!fs.existsSync(script)) fail(`No workspace at ${root} (core/scripts/plugins.sh is missing). Run: webship-workspace init`);
|
|
119
|
+
// A bare name means the npm package of that name: `plugin require git` is `npm install @webship.co/workspace-git`.
|
|
120
|
+
const spec = verb === 'require' && name && !/[@:/]/.test(name) ? `@webship.co/workspace-${name}` : name;
|
|
121
|
+
const args = [script, `--${verb}`];
|
|
122
|
+
if (spec) args.push(spec);
|
|
123
|
+
process.exit(run('bash', args, root) ? 0 : 1);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const [cmd, ...rest] = process.argv.slice(2);
|
|
127
|
+
switch (cmd) {
|
|
128
|
+
case 'init': init(rest[0]); break;
|
|
129
|
+
case 'update': init(rest[0], { update: true }); break;
|
|
130
|
+
case 'plugin': plugin(rest[0], rest[1]); break;
|
|
131
|
+
case 'catalog': say(catalogText()); break;
|
|
132
|
+
default:
|
|
133
|
+
say(fs.readFileSync(__filename, 'utf8').split('\n').slice(2, 14).map((l) => l.replace(/^ \* ?/, '')).join('\n'));
|
|
134
|
+
process.exit(cmd ? 1 : 0);
|
|
135
|
+
}
|