@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,119 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
################################################################################
|
|
4
|
+
## Webship Workspace — align the dashboard's docker group with this host
|
|
5
|
+
################################################################################
|
|
6
|
+
## The dashboard runs in its own DDEV web container with Docker-outside-of-Docker:
|
|
7
|
+
## the host's /var/run/docker.sock is bind-mounted in, and that socket is
|
|
8
|
+
## root:docker with the HOST's docker GID. The container's web user therefore has
|
|
9
|
+
## to share that exact GID, or every `ddev` command inside the dashboard fails:
|
|
10
|
+
##
|
|
11
|
+
## Docker error: permission denied while trying to connect to the docker API
|
|
12
|
+
##
|
|
13
|
+
## which does not look like a permissions problem from the outside. It looks like
|
|
14
|
+
## a dashboard where every project is "Stopped" forever, no Start/Stop/Drush item
|
|
15
|
+
## ever appears, and pressing Start seems to do nothing — while the project is in
|
|
16
|
+
## fact running perfectly well on the host.
|
|
17
|
+
##
|
|
18
|
+
## bash core/scripts/docker-gid.sh align it, if it differs
|
|
19
|
+
## bash core/scripts/docker-gid.sh --check report, change nothing
|
|
20
|
+
## bash core/scripts/docker-gid.sh --quiet only speak when something changed
|
|
21
|
+
##
|
|
22
|
+
## The GID has to be baked at BUILD time, in
|
|
23
|
+
## .ddev/web-build/Dockerfile.workspace-app: the container's main process runs as
|
|
24
|
+
## uid 1000 (`Config.User=1000:1000`), so no entrypoint script can groupmod its
|
|
25
|
+
## way out of it, and supervisord launches the app without calling initgroups() —
|
|
26
|
+
## so it must be the web user's PRIMARY group, not a supplementary one.
|
|
27
|
+
##
|
|
28
|
+
## Which means the value in that file is machine-specific, in a file that
|
|
29
|
+
## cmd-tools sync-tooling.sh mirrors wholesale. That is why this exists as a
|
|
30
|
+
## script rather than a note in the README: install.sh runs it during setup, and
|
|
31
|
+
## sync-tooling.sh runs it after mirroring, so a pull cannot leave the dashboard
|
|
32
|
+
## blind to Docker.
|
|
33
|
+
################################################################################
|
|
34
|
+
|
|
35
|
+
set -u
|
|
36
|
+
|
|
37
|
+
CHECK_ONLY='no'
|
|
38
|
+
QUIET='no'
|
|
39
|
+
while [ $# -gt 0 ]; do
|
|
40
|
+
case "$1" in
|
|
41
|
+
-c|--check) CHECK_ONLY='yes'; shift ;;
|
|
42
|
+
-q|--quiet) QUIET='yes'; shift ;;
|
|
43
|
+
-h|--help) sed -n '3,34p' "${BASH_SOURCE[0]}" | sed 's/^## \{0,1\}//'; exit 0 ;;
|
|
44
|
+
*) echo "Unknown option: $1 (see --help)"; exit 1 ;;
|
|
45
|
+
esac
|
|
46
|
+
done
|
|
47
|
+
|
|
48
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
49
|
+
DOCKERFILE="${ROOT}/core/workspace-app/.ddev/web-build/Dockerfile.workspace-app"
|
|
50
|
+
COMPOSE="${ROOT}/core/workspace-app/.ddev/docker-compose.dood.yaml"
|
|
51
|
+
|
|
52
|
+
function say() { [ "${QUIET}" == 'yes' ] || echo "$@" ; }
|
|
53
|
+
function warn() { echo "$@" ; }
|
|
54
|
+
|
|
55
|
+
if [ ! -f "${DOCKERFILE}" ] ; then
|
|
56
|
+
warn " ✗ No ${DOCKERFILE#${ROOT}/} — nothing to align."
|
|
57
|
+
exit 1
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# The socket is the authority when it is there: it is the thing the container has
|
|
61
|
+
# to reach. Fall back to the docker group, for a machine where Docker is not up.
|
|
62
|
+
host_gid=''
|
|
63
|
+
if [ -S /var/run/docker.sock ] ; then
|
|
64
|
+
host_gid="$(stat -c %g /var/run/docker.sock 2>/dev/null)"
|
|
65
|
+
fi
|
|
66
|
+
if [ -z "${host_gid}" ] ; then
|
|
67
|
+
host_gid="$(getent group docker 2>/dev/null | cut -d: -f3)"
|
|
68
|
+
fi
|
|
69
|
+
if [ -z "${host_gid}" ] ; then
|
|
70
|
+
warn " ✗ No docker group and no /var/run/docker.sock — is Docker installed?"
|
|
71
|
+
exit 1
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
# Both numbers in the file are the same GID: the group, then the web user's primary group.
|
|
75
|
+
baked="$(grep -oE 'groupmod -g [0-9]+ docker' "${DOCKERFILE}" | grep -oE '[0-9]+' | head -1)"
|
|
76
|
+
if [ -z "${baked}" ] ; then
|
|
77
|
+
warn " ✗ Could not find the docker GID in ${DOCKERFILE##*/} — has that line changed?"
|
|
78
|
+
exit 1
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
# The build-time GID makes the group exist in the image; the compose group_add is
|
|
82
|
+
# what puts the running process in it. Both have to be right, and they are the same
|
|
83
|
+
# number, so they are checked and written together.
|
|
84
|
+
granted=""
|
|
85
|
+
if [ -f "${COMPOSE}" ] ; then
|
|
86
|
+
granted="$(sed -n '/group_add:/,/^[^ ]/p' "${COMPOSE}" | grep -oE '"[0-9]+"' | tr -d '"' | head -1)"
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
if [ "${baked}" == "${host_gid}" ] && { [ -z "${granted}" ] || [ "${granted}" == "${host_gid}" ]; } ; then
|
|
90
|
+
say " ✓ dashboard docker GID ${baked} matches this host"
|
|
91
|
+
exit 0
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
if [ "${CHECK_ONLY}" == 'yes' ] ; then
|
|
95
|
+
warn " ✗ dashboard docker GID is ${baked}${granted:+ (granted ${granted})}, this host's docker socket is ${host_gid}"
|
|
96
|
+
warn " Every ddev command inside the dashboard fails, so every project reads as Stopped."
|
|
97
|
+
warn " Fix it: bash core/scripts/docker-gid.sh && (cd core/workspace-app && ddev restart)"
|
|
98
|
+
exit 1
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
# Rewrite both occurrences on that one line, and nothing else in the file.
|
|
102
|
+
sed -i -E "s/groupmod -g [0-9]+ docker/groupmod -g ${host_gid} docker/; s/groupadd -g [0-9]+ docker/groupadd -g ${host_gid} docker/; s/usermod -g [0-9]+ \\\$username/usermod -g ${host_gid} \$username/" "${DOCKERFILE}"
|
|
103
|
+
|
|
104
|
+
# group_add in the compose override: the one the running process actually gets.
|
|
105
|
+
if [ -f "${COMPOSE}" ] && [ -n "${granted}" ] ; then
|
|
106
|
+
sed -i -E "/group_add:/,/^[^ ]/ s/\"${granted}\"/\"${host_gid}\"/" "${COMPOSE}"
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
after="$(grep -oE 'groupmod -g [0-9]+ docker' "${DOCKERFILE}" | grep -oE '[0-9]+' | head -1)"
|
|
110
|
+
if [ "${after}" != "${host_gid}" ] ; then
|
|
111
|
+
warn " ✗ Tried to set the docker GID to ${host_gid} and the file still says ${after}."
|
|
112
|
+
warn " Edit ${DOCKERFILE#${ROOT}/} by hand — the line is near the end."
|
|
113
|
+
exit 1
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
warn " ✓ dashboard docker GID ${baked} → ${host_gid} (this host's docker socket)"
|
|
117
|
+
warn " The image carries the old GID until it is rebuilt:"
|
|
118
|
+
warn " cd ${ROOT}/core/workspace-app && ddev restart"
|
|
119
|
+
exit 0
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
argparse "$@" <<ARGEOF || exit 1
|
|
4
|
+
parser.add_argument('PROJECT_NAME',
|
|
5
|
+
help='The name of the project. It becomes https://<PROJECT_NAME>.ddev.site')
|
|
6
|
+
parser.add_argument('-v', '--site-template-version',
|
|
7
|
+
default="",
|
|
8
|
+
help='Composer constraint for the site template. Example: --site-template-version "^1.0". Default: the latest release.')
|
|
9
|
+
parser.add_argument('-p', '--php-version',
|
|
10
|
+
default="8.3",
|
|
11
|
+
help='PHP version for the DDEV project [default %(default)s].')
|
|
12
|
+
parser.add_argument('-i', '--install',
|
|
13
|
+
action='store_true',
|
|
14
|
+
default=False,
|
|
15
|
+
help='Install the site with this template after building it. Without this the build stops at a codebase, exactly as every other builder in the workspace does, and you pick the template in the browser installer.')
|
|
16
|
+
parser.add_argument('-s', '--skip-install',
|
|
17
|
+
action='store_true',
|
|
18
|
+
default=False,
|
|
19
|
+
help='Explicitly stop at the codebase. That is already what happens without --install; the flag exists so a script that passes it keeps working.')
|
|
20
|
+
parser.add_argument('-l', '--launch',
|
|
21
|
+
action='store_true',
|
|
22
|
+
default=False,
|
|
23
|
+
help='Open the site in a browser when it is ready.')
|
|
24
|
+
parser.add_argument('-r', '--require',
|
|
25
|
+
default="_none_",
|
|
26
|
+
nargs='+',
|
|
27
|
+
help='Require more packages by composer. Example: --require "drupal/token:~1.0"')
|
|
28
|
+
ARGEOF
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# Tracks what ai-items installed where, so a later run can tell "is this stale"
|
|
4
|
+
# without re-copying anything. One lock file per .claude root (global ~/.claude,
|
|
5
|
+
# or a project's own .claude/), covering agents, skills and prompts together.
|
|
6
|
+
#
|
|
7
|
+
# Two kinds of source get two kinds of hash, same split as skills.sh:
|
|
8
|
+
# repo-sourced (ai_items_fetch, dest claude) -> the git object sha for that
|
|
9
|
+
# path at the fetched ref. We already hold a local clone when fetching, so
|
|
10
|
+
# `git rev-parse <ref>:<path>` gets it for free — no extra network call.
|
|
11
|
+
# workspace-sourced (install_ai_item) -> a local content hash of the
|
|
12
|
+
# workspace draft, recomputed on check with no network at all.
|
|
13
|
+
#
|
|
14
|
+
# ai_items_check reads the lock and, only for entries still claiming a repo
|
|
15
|
+
# source, fetches the WHOLE remote tree once (one `gh api` call covers every
|
|
16
|
+
# item being checked) rather than one call per item.
|
|
17
|
+
|
|
18
|
+
function ai_items_lock_file() {
|
|
19
|
+
local install_dir="$1";
|
|
20
|
+
echo "$(dirname "${install_dir}")/.ai-items-lock.json" ;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
# Local content hash: sha256 of a file, or a sorted hash-of-hashes for a directory.
|
|
24
|
+
# Deterministic across runs on the same content; not meant to match any external hash.
|
|
25
|
+
function ai_items_local_hash() {
|
|
26
|
+
local path="$1";
|
|
27
|
+
if [ -f "${path}" ]; then
|
|
28
|
+
sha256sum "${path}" | awk '{print $1}' ;
|
|
29
|
+
elif [ -d "${path}" ]; then
|
|
30
|
+
find "${path}" -type f | LC_ALL=C sort | xargs sha256sum 2>/dev/null | sha256sum | awk '{print $1}' ;
|
|
31
|
+
fi
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
# Add or update one item's entry in the lock file next to `install_dir`.
|
|
35
|
+
function ai_items_lock_set() {
|
|
36
|
+
local install_dir="$1" kind="$2" name="$3" source="$4" source_type="$5" source_path="$6" hash="$7";
|
|
37
|
+
local lock_file; lock_file=$(ai_items_lock_file "${install_dir}") ;
|
|
38
|
+
python3 - "${lock_file}" "${kind}" "${name}" "${source}" "${source_type}" "${source_path}" "${hash}" <<'PYEOF'
|
|
39
|
+
import json, sys, pathlib, datetime
|
|
40
|
+
lock_file, kind, name, source, source_type, source_path, hash_ = sys.argv[1:8]
|
|
41
|
+
p = pathlib.Path(lock_file)
|
|
42
|
+
try:
|
|
43
|
+
data = json.loads(p.read_text())
|
|
44
|
+
except Exception:
|
|
45
|
+
data = {"version": 1, "items": {}}
|
|
46
|
+
data.setdefault("items", {})
|
|
47
|
+
key = f"{kind}:{name}"
|
|
48
|
+
now = datetime.datetime.now(datetime.timezone.utc).isoformat()
|
|
49
|
+
existing = data["items"].get(key, {})
|
|
50
|
+
data["items"][key] = {
|
|
51
|
+
"kind": kind,
|
|
52
|
+
"name": name,
|
|
53
|
+
"source": source,
|
|
54
|
+
"sourceType": source_type,
|
|
55
|
+
"sourcePath": source_path,
|
|
56
|
+
"hash": hash_,
|
|
57
|
+
"installedAt": existing.get("installedAt", now),
|
|
58
|
+
"updatedAt": now,
|
|
59
|
+
}
|
|
60
|
+
p.parent.mkdir(parents=True, exist_ok=True)
|
|
61
|
+
p.write_text(json.dumps(data, indent=2, sort_keys=True) + "\n")
|
|
62
|
+
PYEOF
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
# Rows of "name\tsourceType\tsource\tsourcePath\thash" for entries of one kind
|
|
66
|
+
# (optionally one name), read straight out of the lock file.
|
|
67
|
+
function ai_items_lock_rows() {
|
|
68
|
+
local lock_file="$1" kind="$2" name="${3:-}";
|
|
69
|
+
[ -f "${lock_file}" ] || return 0 ;
|
|
70
|
+
python3 - "${lock_file}" "${kind}" "${name}" <<'PYEOF'
|
|
71
|
+
import json, sys
|
|
72
|
+
lock_file, kind, name = sys.argv[1:4]
|
|
73
|
+
try:
|
|
74
|
+
data = json.loads(open(lock_file).read())
|
|
75
|
+
except Exception:
|
|
76
|
+
data = {"items": {}}
|
|
77
|
+
for _, entry in sorted(data.get("items", {}).items()):
|
|
78
|
+
if entry.get("kind") != kind:
|
|
79
|
+
continue
|
|
80
|
+
if name and name not in ("", "_all_") and entry.get("name") != name:
|
|
81
|
+
continue
|
|
82
|
+
print("\t".join([
|
|
83
|
+
entry.get("name", ""), entry.get("sourceType", ""), entry.get("source", ""),
|
|
84
|
+
entry.get("sourcePath", ""), entry.get("hash", ""),
|
|
85
|
+
]))
|
|
86
|
+
PYEOF
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
# Compare the lock against reality for one install location, without touching
|
|
90
|
+
# the installed files. Repo-sourced entries are checked against ONE fetched
|
|
91
|
+
# remote tree (whichever ref the entry itself recorded); workspace-sourced
|
|
92
|
+
# entries are checked against the current workspace draft, purely locally.
|
|
93
|
+
function ai_items_check() {
|
|
94
|
+
local kind="$1" name="${2:-}" to="${3:-}";
|
|
95
|
+
local target; target=$(ai_items_install_path "${kind}" "${to}") || return 1 ;
|
|
96
|
+
if [ ! -d "${target}" ]; then
|
|
97
|
+
echo "Nothing installed at ${target}." ;
|
|
98
|
+
return 1 ;
|
|
99
|
+
fi
|
|
100
|
+
local lock_file; lock_file=$(ai_items_lock_file "${target}") ;
|
|
101
|
+
if [ ! -f "${lock_file}" ]; then
|
|
102
|
+
echo "No lock file at ${lock_file} — nothing workspace-tracked yet (installed before checking existed, or copied by hand).";
|
|
103
|
+
ai_items_skills_cli_check "${kind}" "${to}" ;
|
|
104
|
+
return 0 ;
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
echo "*---------------------------------------------------------------------*";
|
|
108
|
+
echo " ${kind} — ${target}";
|
|
109
|
+
echo "*---------------------------------------------------------------------*";
|
|
110
|
+
|
|
111
|
+
local rows; rows=$(ai_items_lock_rows "${lock_file}" "${kind}" "${name}") ;
|
|
112
|
+
if [ -z "${rows}" ]; then
|
|
113
|
+
echo " Nothing workspace-tracked for '${name:-_all_}'.";
|
|
114
|
+
ai_items_skills_cli_check "${kind}" "${to}" ;
|
|
115
|
+
return 0 ;
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
local tree_json="" repo_checked="";
|
|
119
|
+
local item_name source_type source source_path hash status remote_hash;
|
|
120
|
+
|
|
121
|
+
while IFS=$'\t' read -r item_name source_type source source_path hash ; do
|
|
122
|
+
[ -z "${item_name}" ] && continue ;
|
|
123
|
+
status="unknown";
|
|
124
|
+
if [ "${source_type}" == 'repo' ] ; then
|
|
125
|
+
# One recursive tree fetch covers every repo-sourced item being checked —
|
|
126
|
+
# cached per <repo>@<ref>, not re-fetched per item.
|
|
127
|
+
if [ "${repo_checked}" != "${source}" ] ; then
|
|
128
|
+
ensure_gh_cli > /dev/null 2>&1 ;
|
|
129
|
+
local repo="${source%@*}" ref="${source##*@}";
|
|
130
|
+
tree_json=$(gh api "repos/${repo}/git/trees/${ref}?recursive=1" 2>/dev/null) ;
|
|
131
|
+
repo_checked="${source}";
|
|
132
|
+
fi
|
|
133
|
+
if [ -z "${tree_json}" ] ; then
|
|
134
|
+
status="could not reach ${source}";
|
|
135
|
+
else
|
|
136
|
+
remote_hash=$(echo "${tree_json}" | jq -r --arg p "${source_path}" '.tree[]? | select(.path==$p) | .sha' 2>/dev/null) ;
|
|
137
|
+
if [ -z "${remote_hash}" ] ; then
|
|
138
|
+
status="removed upstream";
|
|
139
|
+
elif [ "${remote_hash}" == "${hash}" ] ; then
|
|
140
|
+
status="up to date";
|
|
141
|
+
else
|
|
142
|
+
status="update available";
|
|
143
|
+
fi
|
|
144
|
+
fi
|
|
145
|
+
else
|
|
146
|
+
# Workspace-sourced: recompute the draft's current hash, no network.
|
|
147
|
+
local draft_path="${WORKSPACE_ROOT}/${source_path}";
|
|
148
|
+
if [ ! -e "${draft_path}" ] ; then
|
|
149
|
+
status="draft removed (${draft_path})";
|
|
150
|
+
else
|
|
151
|
+
remote_hash=$(ai_items_local_hash "${draft_path}") ;
|
|
152
|
+
if [ "${remote_hash}" == "${hash}" ] ; then
|
|
153
|
+
status="up to date";
|
|
154
|
+
else
|
|
155
|
+
status="draft changed since install";
|
|
156
|
+
fi
|
|
157
|
+
fi
|
|
158
|
+
fi
|
|
159
|
+
printf " %-32s %-14s %s\n" "${item_name}" "(${source_type})" "${status}";
|
|
160
|
+
done <<< "${rows}"
|
|
161
|
+
|
|
162
|
+
ai_items_skills_cli_check "${kind}" "${to}" ;
|
|
163
|
+
return 0 ;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
# Skills the skills.sh CLI installed live in ITS lock — its own `check` covers them.
|
|
167
|
+
# Global scope only: that CLI's check reads ~/.agents/.skill-lock.json, not a project's.
|
|
168
|
+
function ai_items_skills_cli_check() {
|
|
169
|
+
local kind="$1" to="$2";
|
|
170
|
+
[ "${kind}" == 'ai-skills' ] || return 0 ;
|
|
171
|
+
ai_items_skills_cli_available || return 0 ;
|
|
172
|
+
if [ -n "${to}" ] && [ ! "${to}" == '_none_' ] && [ ! "${to}" == 'claude' ] ; then return 0 ; fi
|
|
173
|
+
echo "skills.sh CLI (npx skills check):" ;
|
|
174
|
+
DISABLE_TELEMETRY=1 npx -y skills check || echo " (skills.sh CLI check failed — the workspace-tracked report above stands)" ;
|
|
175
|
+
}
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# `--add <source>` and `--update`: the skills.sh verbs, on top of the lock file.
|
|
4
|
+
#
|
|
5
|
+
# add any GitHub repo -> ~/.claude (or one project's .claude/) + lock entry
|
|
6
|
+
# update re-copy every lock entry whose source moved, nothing else
|
|
7
|
+
#
|
|
8
|
+
# The Webship repo keeps its own dedicated verb (--fetch, curated + filtered);
|
|
9
|
+
# --add is for everything else: a public skills repo, a client's repo, a fork.
|
|
10
|
+
|
|
11
|
+
# Normalize a source into "owner/repo<TAB>ref<TAB>subpath" (ref/subpath may be empty).
|
|
12
|
+
# Accepts: owner/repo, owner/repo@ref, https://github.com/owner/repo[.git],
|
|
13
|
+
# and https://github.com/owner/repo/tree/ref[/subpath].
|
|
14
|
+
function ai_items_parse_source() {
|
|
15
|
+
local input="$1" owner_repo="" ref="" subpath="";
|
|
16
|
+
|
|
17
|
+
case "${input}" in
|
|
18
|
+
*github.com/*)
|
|
19
|
+
local path="${input#*github.com/}"; path="${path%/}";
|
|
20
|
+
if [[ "${path}" == */tree/* ]] ; then
|
|
21
|
+
owner_repo="${path%%/tree/*}";
|
|
22
|
+
local rest="${path#*/tree/}";
|
|
23
|
+
ref="${rest%%/*}";
|
|
24
|
+
[ "${rest}" != "${ref}" ] && subpath="${rest#*/}";
|
|
25
|
+
else
|
|
26
|
+
owner_repo="${path}";
|
|
27
|
+
fi
|
|
28
|
+
owner_repo="${owner_repo%.git}";
|
|
29
|
+
;;
|
|
30
|
+
*/*)
|
|
31
|
+
owner_repo="${input}";
|
|
32
|
+
if [[ "${owner_repo}" == *@* ]] ; then
|
|
33
|
+
ref="${owner_repo##*@}"; owner_repo="${owner_repo%@*}";
|
|
34
|
+
fi
|
|
35
|
+
;;
|
|
36
|
+
*)
|
|
37
|
+
echo "Not a source I can read: '${input}'. Use owner/repo, owner/repo@ref, or a github.com URL." >&2 ;
|
|
38
|
+
return 1 ;
|
|
39
|
+
;;
|
|
40
|
+
esac
|
|
41
|
+
|
|
42
|
+
if ! echo "${owner_repo}" | grep -qE '^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$' ; then
|
|
43
|
+
echo "Not a source I can read: '${input}'. Use owner/repo, owner/repo@ref, or a github.com URL." >&2 ;
|
|
44
|
+
return 1 ;
|
|
45
|
+
fi
|
|
46
|
+
if [[ "${subpath}" == *..* ]] ; then
|
|
47
|
+
echo "Refusing subpath with '..': ${subpath}" >&2 ;
|
|
48
|
+
return 1 ;
|
|
49
|
+
fi
|
|
50
|
+
printf '%s\t%s\t%s\n' "${owner_repo}" "${ref}" "${subpath}" ;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
# Shallow-clone one repo@ref into a temp dir and print the dir. gh's credential
|
|
54
|
+
# helper covers private repos the caller can read; public ones need nothing.
|
|
55
|
+
function ai_items_clone_source() {
|
|
56
|
+
local owner_repo="$1" ref="$2" tmp;
|
|
57
|
+
tmp=$(mktemp -d) ;
|
|
58
|
+
ensure_git_github_auth ;
|
|
59
|
+
local ref_args=() ;
|
|
60
|
+
[ -n "${ref}" ] && ref_args=(--branch "${ref}") ;
|
|
61
|
+
if ! git clone --quiet --depth 1 "${ref_args[@]}" "https://github.com/${owner_repo}.git" "${tmp}/repo" 2>/dev/null ; then
|
|
62
|
+
echo "Could not clone ${owner_repo}${ref:+@${ref}} — check the name, ref and access." >&2 ;
|
|
63
|
+
rm -rf "${tmp}" ;
|
|
64
|
+
return 1 ;
|
|
65
|
+
fi
|
|
66
|
+
echo "${tmp}/repo" ;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
# Discover items of one kind in a checkout, as "name<TAB>path-in-repo" rows.
|
|
70
|
+
# Skills are directories holding a SKILL.md; agents and prompts are .md files.
|
|
71
|
+
# Container dirs cover the skills.sh conventions plus this workspace's own.
|
|
72
|
+
function ai_items_discover() {
|
|
73
|
+
local kind="$1" root="$2" base="${3:-}";
|
|
74
|
+
local search="${root}${base:+/${base}}";
|
|
75
|
+
[ -d "${search}" ] || return 0 ;
|
|
76
|
+
|
|
77
|
+
if [ "${kind}" == 'ai-skills' ] ; then
|
|
78
|
+
# A subpath pointing straight at one skill.
|
|
79
|
+
if [ -f "${search}/SKILL.md" ] && [ -n "${base}" ] ; then
|
|
80
|
+
printf '%s\t%s\n' "$(basename "${search}")" "${base}" ;
|
|
81
|
+
return 0 ;
|
|
82
|
+
fi
|
|
83
|
+
local d container;
|
|
84
|
+
for container in "" "skills" ".claude/skills" ".agents/skills" ; do
|
|
85
|
+
local dir="${search}${container:+/${container}}";
|
|
86
|
+
[ -d "${dir}" ] || continue ;
|
|
87
|
+
for d in "${dir}"/*/ ; do
|
|
88
|
+
[ -f "${d}SKILL.md" ] || continue ;
|
|
89
|
+
local rel="${d#${root}/}"; rel="${rel%/}";
|
|
90
|
+
printf '%s\t%s\n' "$(basename "${d}")" "${rel}" ;
|
|
91
|
+
done
|
|
92
|
+
done
|
|
93
|
+
else
|
|
94
|
+
local container_names;
|
|
95
|
+
if [ "${kind}" == 'ai-agents' ] ; then
|
|
96
|
+
container_names=".claude/agents agents";
|
|
97
|
+
else
|
|
98
|
+
container_names=".claude/commands commands prompts";
|
|
99
|
+
fi
|
|
100
|
+
local f container;
|
|
101
|
+
for container in ${container_names} ; do
|
|
102
|
+
local dir="${search}/${container}";
|
|
103
|
+
[ -d "${dir}" ] || continue ;
|
|
104
|
+
for f in "${dir}"/*.md ; do
|
|
105
|
+
[ -f "${f}" ] || continue ;
|
|
106
|
+
case "$(basename "${f}")" in README.md|AGENTS.md|CLAUDE.md|RULES.md) continue ;; esac
|
|
107
|
+
local rel="${f#${root}/}";
|
|
108
|
+
printf '%s\t%s\n' "$(basename "${f}" .md)" "${rel}" ;
|
|
109
|
+
done
|
|
110
|
+
done
|
|
111
|
+
fi | sort -u ;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
# The skills.sh CLI (github.com/vercel-labs/skills) is the ecosystem's own installer
|
|
115
|
+
# for the skills kind — same SKILL.md format, richer source support, its own lock and
|
|
116
|
+
# `update`. Delegate to it when node is here; agents and prompts stay on the bash path
|
|
117
|
+
# because that CLI only handles skills. AI_ITEMS_NO_SKILLS_CLI=1 opts out.
|
|
118
|
+
function ai_items_skills_cli_available() {
|
|
119
|
+
[ -n "${AI_ITEMS_NO_SKILLS_CLI}" ] && return 1 ;
|
|
120
|
+
command -v npx > /dev/null 2>&1 ;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
# DISABLE_TELEMETRY: the CLI reports installed skill names to skills.sh for its
|
|
124
|
+
# leaderboard — fine for public repos, not for client or private ones, so off always.
|
|
125
|
+
function ai_items_skills_cli_add() {
|
|
126
|
+
local name="$1" source="$2" to="$3";
|
|
127
|
+
local skill_filter="${name:-*}";
|
|
128
|
+
[ "${skill_filter}" == '_all_' ] && skill_filter='*' ;
|
|
129
|
+
echo "Using the skills.sh CLI (npx skills add) — its own lock manages these; agents and prompts stay on the workspace tooling." ;
|
|
130
|
+
if [ -z "${to}" ] || [ "${to}" == '_none_' ] || [ "${to}" == 'claude' ] ; then
|
|
131
|
+
DISABLE_TELEMETRY=1 npx -y skills add "${source}" --skill "${skill_filter}" -a claude-code --copy -g -y ;
|
|
132
|
+
else
|
|
133
|
+
local project_dir="${WORKSPACE_ROOT}/${to}";
|
|
134
|
+
[ -d "${project_dir}" ] || { echo "No ${to}." >&2 ; return 1 ; }
|
|
135
|
+
( cd "${project_dir}" && DISABLE_TELEMETRY=1 npx -y skills add "${source}" --skill "${skill_filter}" -a claude-code --copy -y ) ;
|
|
136
|
+
fi
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function ai_items_skills_cli_update() {
|
|
140
|
+
local to="$1";
|
|
141
|
+
if [ -z "${to}" ] || [ "${to}" == '_none_' ] || [ "${to}" == 'claude' ] ; then
|
|
142
|
+
DISABLE_TELEMETRY=1 npx -y skills update -g -y ;
|
|
143
|
+
else
|
|
144
|
+
local project_dir="${WORKSPACE_ROOT}/${to}";
|
|
145
|
+
[ -d "${project_dir}" ] || return 0 ;
|
|
146
|
+
( cd "${project_dir}" && DISABLE_TELEMETRY=1 npx -y skills update -p -y ) ;
|
|
147
|
+
fi
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
# Install items of one kind from any GitHub repo, and lock what was copied.
|
|
151
|
+
# name one item, or _all_/empty for everything discovered
|
|
152
|
+
# source owner/repo[@ref] or a github.com URL (tree URLs carry ref + subpath)
|
|
153
|
+
# to empty for ~/.claude, or <workspace>/<project>
|
|
154
|
+
function ai_items_add() {
|
|
155
|
+
local kind="$1" name="$2" source="$3" to="${4:-}";
|
|
156
|
+
name=$(ai_items_sanitize_name "${name}") || return 1 ;
|
|
157
|
+
|
|
158
|
+
if [ "${kind}" == 'ai-skills' ] && ai_items_skills_cli_available ; then
|
|
159
|
+
if ai_items_skills_cli_add "${name}" "${source}" "${to}" ; then
|
|
160
|
+
return 0 ;
|
|
161
|
+
fi
|
|
162
|
+
echo "skills.sh CLI could not add it — falling back to the workspace installer." ;
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
local parsed owner_repo ref subpath;
|
|
166
|
+
parsed=$(ai_items_parse_source "${source}") || return 1 ;
|
|
167
|
+
IFS=$'\t' read -r owner_repo ref subpath <<< "${parsed}" ;
|
|
168
|
+
|
|
169
|
+
local target; target=$(ai_items_install_path "${kind}" "${to}") || return 1 ;
|
|
170
|
+
local checkout; checkout=$(ai_items_clone_source "${owner_repo}" "${ref}") || return 1 ;
|
|
171
|
+
local tmp_root; tmp_root=$(dirname "${checkout}") ;
|
|
172
|
+
local ref_name; ref_name=$(git -C "${checkout}" rev-parse --abbrev-ref HEAD 2>/dev/null) ;
|
|
173
|
+
|
|
174
|
+
local rows; rows=$(ai_items_discover "${kind}" "${checkout}" "${subpath}") ;
|
|
175
|
+
if [ -z "${rows}" ]; then
|
|
176
|
+
echo "No ${kind} found in ${owner_repo}${ref:+@${ref}}${subpath:+ under ${subpath}}." ;
|
|
177
|
+
rm -rf "${tmp_root}" ;
|
|
178
|
+
return 1 ;
|
|
179
|
+
fi
|
|
180
|
+
|
|
181
|
+
mkdir -p "${target}" ;
|
|
182
|
+
local copied=0 skipped=0 item path;
|
|
183
|
+
while IFS=$'\t' read -r item path ; do
|
|
184
|
+
[ -z "${item}" ] && continue ;
|
|
185
|
+
if [ -n "${name}" ] && [ "${name}" != '_all_' ] && [ "${item}" != "${name}" ] ; then continue ; fi
|
|
186
|
+
# Discovered names come from a remote repo: same character rule as everywhere else.
|
|
187
|
+
if ! echo "${item}" | grep -qE '^[a-zA-Z0-9_.-]+$' ; then
|
|
188
|
+
echo " skipping '${item}': unsafe name." ; skipped=$((skipped+1)) ; continue ;
|
|
189
|
+
fi
|
|
190
|
+
local sha; sha=$(git -C "${checkout}" rev-parse "HEAD:${path}" 2>/dev/null) ;
|
|
191
|
+
if [ "${kind}" == 'ai-skills' ] ; then
|
|
192
|
+
rsync -a --delete "${checkout}/${path}/" "${target}/${item}/" || { skipped=$((skipped+1)) ; continue ; }
|
|
193
|
+
else
|
|
194
|
+
cp "${checkout}/${path}" "${target}/" || { skipped=$((skipped+1)) ; continue ; }
|
|
195
|
+
fi
|
|
196
|
+
copied=$((copied+1)) ;
|
|
197
|
+
[ -n "${sha}" ] && ai_items_lock_set "${target}" "${kind}" "${item}" \
|
|
198
|
+
"${owner_repo}@${ref_name}" "repo" "${path}" "${sha}" ;
|
|
199
|
+
echo " + ${item}" ;
|
|
200
|
+
done <<< "${rows}"
|
|
201
|
+
rm -rf "${tmp_root}" ;
|
|
202
|
+
|
|
203
|
+
if [ "${copied}" -eq 0 ]; then
|
|
204
|
+
echo "No ${kind%s} '${name}' in ${owner_repo}${ref:+@${ref}} — nothing installed." ;
|
|
205
|
+
return 1 ;
|
|
206
|
+
fi
|
|
207
|
+
echo "Added ${copied} ${kind} from ${owner_repo}${ref:+@${ref}} into ${target}." ;
|
|
208
|
+
echo "Review third-party ${kind} before use — a session runs them with its full permissions." ;
|
|
209
|
+
echo "Restart your Claude Code session to pick it up." ;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
# Re-copy every lock entry of one kind whose source moved. Repo entries are
|
|
213
|
+
# grouped so each repo@ref clones once; workspace entries re-install from the
|
|
214
|
+
# draft. Nothing is touched when the recorded hash still matches.
|
|
215
|
+
function ai_items_update() {
|
|
216
|
+
local kind="$1" name="${2:-}" to="${3:-}";
|
|
217
|
+
local target; target=$(ai_items_install_path "${kind}" "${to}") || return 1 ;
|
|
218
|
+
local lock_file; lock_file=$(ai_items_lock_file "${target}") ;
|
|
219
|
+
|
|
220
|
+
# No workspace-tracked entries is not "nothing to do" for skills: the
|
|
221
|
+
# skills.sh CLI keeps its own lock, and its update below still runs.
|
|
222
|
+
local rows="";
|
|
223
|
+
if [ -f "${lock_file}" ]; then
|
|
224
|
+
rows=$(ai_items_lock_rows "${lock_file}" "${kind}" "${name}") ;
|
|
225
|
+
fi
|
|
226
|
+
if [ -z "${rows}" ]; then
|
|
227
|
+
echo "Nothing workspace-tracked for '${name:-_all_}' at ${target}." ;
|
|
228
|
+
fi
|
|
229
|
+
|
|
230
|
+
local updated=0 checked=0 current_source="" checkout="" tmp_root="";
|
|
231
|
+
local item_name source_type source source_path hash;
|
|
232
|
+
|
|
233
|
+
# Sorting by source groups repo entries so one clone serves all of them.
|
|
234
|
+
while IFS=$'\t' read -r item_name source_type source source_path hash ; do
|
|
235
|
+
[ -z "${item_name}" ] && continue ;
|
|
236
|
+
checked=$((checked+1)) ;
|
|
237
|
+
|
|
238
|
+
if [ "${source_type}" == 'repo' ] ; then
|
|
239
|
+
if [ "${source}" != "${current_source}" ] ; then
|
|
240
|
+
[ -n "${tmp_root}" ] && rm -rf "${tmp_root}" ;
|
|
241
|
+
checkout=$(ai_items_clone_source "${source%@*}" "${source##*@}") || { checkout=""; tmp_root=""; current_source="${source}"; continue ; }
|
|
242
|
+
tmp_root=$(dirname "${checkout}") ;
|
|
243
|
+
current_source="${source}";
|
|
244
|
+
fi
|
|
245
|
+
[ -n "${checkout}" ] || { printf " %-32s %s\n" "${item_name}" "source unreachable" ; continue ; }
|
|
246
|
+
local sha; sha=$(git -C "${checkout}" rev-parse "HEAD:${source_path}" 2>/dev/null) ;
|
|
247
|
+
if [ -z "${sha}" ] ; then
|
|
248
|
+
printf " %-32s %s\n" "${item_name}" "removed upstream — left as is" ;
|
|
249
|
+
elif [ "${sha}" == "${hash}" ] ; then
|
|
250
|
+
printf " %-32s %s\n" "${item_name}" "up to date" ;
|
|
251
|
+
else
|
|
252
|
+
if [ "${kind}" == 'ai-skills' ] ; then
|
|
253
|
+
rsync -a --delete "${checkout}/${source_path}/" "${target}/${item_name}/" ;
|
|
254
|
+
else
|
|
255
|
+
cp "${checkout}/${source_path}" "${target}/" ;
|
|
256
|
+
fi
|
|
257
|
+
ai_items_lock_set "${target}" "${kind}" "${item_name}" "${source}" "repo" "${source_path}" "${sha}" ;
|
|
258
|
+
updated=$((updated+1)) ;
|
|
259
|
+
printf " %-32s %s\n" "${item_name}" "updated" ;
|
|
260
|
+
fi
|
|
261
|
+
else
|
|
262
|
+
local draft_path="${WORKSPACE_ROOT}/${source_path}";
|
|
263
|
+
if [ ! -e "${draft_path}" ] ; then
|
|
264
|
+
printf " %-32s %s\n" "${item_name}" "draft removed — left as is" ;
|
|
265
|
+
continue ;
|
|
266
|
+
fi
|
|
267
|
+
local new_hash; new_hash=$(ai_items_local_hash "${draft_path}") ;
|
|
268
|
+
if [ "${new_hash}" == "${hash}" ] ; then
|
|
269
|
+
printf " %-32s %s\n" "${item_name}" "up to date" ;
|
|
270
|
+
else
|
|
271
|
+
if [ "${kind}" == 'ai-skills' ] ; then
|
|
272
|
+
rsync -a "${draft_path}/" "${target}/${item_name}/" ;
|
|
273
|
+
else
|
|
274
|
+
cp "${draft_path}" "${target}/" ;
|
|
275
|
+
fi
|
|
276
|
+
ai_items_lock_set "${target}" "${kind}" "${item_name}" "workspace" "workspace" "${source_path}" "${new_hash}" ;
|
|
277
|
+
updated=$((updated+1)) ;
|
|
278
|
+
printf " %-32s %s\n" "${item_name}" "updated from draft" ;
|
|
279
|
+
fi
|
|
280
|
+
fi
|
|
281
|
+
done <<< "$(echo "${rows}" | sort -t$'\t' -k3,3)"
|
|
282
|
+
|
|
283
|
+
[ -n "${tmp_root}" ] && rm -rf "${tmp_root}" ;
|
|
284
|
+
echo "Checked ${checked}, updated ${updated}.";
|
|
285
|
+
|
|
286
|
+
# Skills the skills.sh CLI installed live in ITS lock, not this one — its own
|
|
287
|
+
# update covers them, after the workspace-tracked entries above. Its update has
|
|
288
|
+
# no per-skill filter, so a NAMED update stays on the workspace lock alone
|
|
289
|
+
# rather than refreshing every CLI-tracked skill as a side effect.
|
|
290
|
+
if [ "${kind}" == 'ai-skills' ] && ai_items_skills_cli_available \
|
|
291
|
+
&& { [ -z "${name}" ] || [ "${name}" == '_all_' ] ; } ; then
|
|
292
|
+
echo "skills.sh CLI (npx skills update):" ;
|
|
293
|
+
ai_items_skills_cli_update "${to}" || echo " (skills.sh CLI update failed — workspace-tracked items above are done)" ;
|
|
294
|
+
fi
|
|
295
|
+
|
|
296
|
+
[ "${updated}" -gt 0 ] && echo "Restart your Claude Code session to pick the updates up." ;
|
|
297
|
+
return 0 ;
|
|
298
|
+
}
|