tower-studio 0.1.2 → 0.1.3
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/bin/tower.mjs +5 -15
- package/next.config.ts +1 -8
- package/package.json +10 -11
- package/prisma/dev.db +0 -0
- package/public/vs/_commonjsHelpers-CT9FvmAN.js +1 -0
- package/public/vs/abap-D-t0cyap.js +1 -0
- package/public/vs/apex-CcIm7xu6.js +1 -0
- package/public/vs/assets/css.worker-HnVq6Ewq.js +93 -0
- package/public/vs/assets/editor.worker-Be8ye1pW.js +26 -0
- package/public/vs/assets/html.worker-B51mlPHg.js +470 -0
- package/public/vs/assets/json.worker-DKiEKt88.js +58 -0
- package/public/vs/assets/ts.worker-CMbG-7ft.js +67731 -0
- package/public/vs/azcli-BA0tQDCg.js +1 -0
- package/public/vs/basic-languages/monaco.contribution.js +1 -0
- package/public/vs/bat-C397hTD6.js +1 -0
- package/public/vs/bicep-DF5aW17k.js +2 -0
- package/public/vs/cameligo-plsz8qhj.js +1 -0
- package/public/vs/clojure-Y2auQMzK.js +1 -0
- package/public/vs/coffee-Bu45yuWE.js +1 -0
- package/public/vs/cpp-CkKPQIni.js +1 -0
- package/public/vs/csharp-CX28MZyh.js +1 -0
- package/public/vs/csp-D8uWnyxW.js +1 -0
- package/public/vs/css-CaeNmE3S.js +3 -0
- package/public/vs/cssMode-CjiAH6dQ.js +1 -0
- package/public/vs/cypher-DVThT8BS.js +1 -0
- package/public/vs/dart-CmGfCvrO.js +1 -0
- package/public/vs/dockerfile-CZqqYdch.js +1 -0
- package/public/vs/ecl-30fUercY.js +1 -0
- package/public/vs/editor/editor.main.css +1 -0
- package/public/vs/editor/editor.main.js +5 -0
- package/public/vs/editor.api-CalNCsUg.js +903 -0
- package/public/vs/elixir-xjPaIfzF.js +1 -0
- package/public/vs/flow9-DqtmStfK.js +1 -0
- package/public/vs/freemarker2-Cz_sV6Md.js +3 -0
- package/public/vs/fsharp-BOMdg4U1.js +1 -0
- package/public/vs/go-D_hbi-Jt.js +1 -0
- package/public/vs/graphql-CKUU4kLG.js +1 -0
- package/public/vs/handlebars-OwglfO-1.js +1 -0
- package/public/vs/hcl-DTaboeZW.js +1 -0
- package/public/vs/html-Pa1xEWsY.js +1 -0
- package/public/vs/htmlMode-Bz67EXwp.js +1 -0
- package/public/vs/ini-CsNwO04R.js +1 -0
- package/public/vs/java-CI4ZMsH9.js +1 -0
- package/public/vs/javascript-PczUCGdz.js +1 -0
- package/public/vs/jsonMode-DULH5oaX.js +7 -0
- package/public/vs/julia-BwzEvaQw.js +1 -0
- package/public/vs/kotlin-IUYPiTV8.js +1 -0
- package/public/vs/language/css/monaco.contribution.js +1 -0
- package/public/vs/language/html/monaco.contribution.js +1 -0
- package/public/vs/language/json/monaco.contribution.js +1 -0
- package/public/vs/language/typescript/monaco.contribution.js +1 -0
- package/public/vs/less-C0eDYdqa.js +2 -0
- package/public/vs/lexon-iON-Kj97.js +1 -0
- package/public/vs/liquid-DqKjdPGy.js +1 -0
- package/public/vs/loader.js +1368 -0
- package/public/vs/lspLanguageFeatures-kM9O9rjY.js +4 -0
- package/public/vs/lua-DtygF91M.js +1 -0
- package/public/vs/m3-CsR4AuFi.js +1 -0
- package/public/vs/markdown-C_rD0bIw.js +1 -0
- package/public/vs/mdx-DEWtB1K5.js +1 -0
- package/public/vs/mips-CiYP61RB.js +1 -0
- package/public/vs/monaco.contribution-D2OdxNBt.js +1 -0
- package/public/vs/monaco.contribution-DO3azKX8.js +1 -0
- package/public/vs/monaco.contribution-EcChJV6a.js +1 -0
- package/public/vs/monaco.contribution-qLAYrEOP.js +1 -0
- package/public/vs/msdax-C38-sJlp.js +1 -0
- package/public/vs/mysql-CdtbpvbG.js +1 -0
- package/public/vs/nls.messages-loader.js +1 -0
- package/public/vs/nls.messages.cs.js.js +17 -0
- package/public/vs/nls.messages.de.js.js +17 -0
- package/public/vs/nls.messages.es.js.js +17 -0
- package/public/vs/nls.messages.fr.js.js +15 -0
- package/public/vs/nls.messages.it.js.js +15 -0
- package/public/vs/nls.messages.ja.js.js +17 -0
- package/public/vs/nls.messages.js.js +10 -0
- package/public/vs/nls.messages.ko.js.js +25 -0
- package/public/vs/nls.messages.pl.js.js +17 -0
- package/public/vs/nls.messages.pt-br.js.js +6 -0
- package/public/vs/nls.messages.ru.js.js +17 -0
- package/public/vs/nls.messages.tr.js.js +15 -0
- package/public/vs/nls.messages.zh-cn.js.js +17 -0
- package/public/vs/nls.messages.zh-tw.js.js +15 -0
- package/public/vs/objective-c-CntZFaHX.js +1 -0
- package/public/vs/pascal-r6kuqfl_.js +1 -0
- package/public/vs/pascaligo-BiXoTmXh.js +1 -0
- package/public/vs/perl-DABw_TcH.js +1 -0
- package/public/vs/pgsql-me_jFXeX.js +1 -0
- package/public/vs/php-D_kh-9LK.js +1 -0
- package/public/vs/pla-VfZjczW0.js +1 -0
- package/public/vs/postiats-BBSzz8Pk.js +1 -0
- package/public/vs/powerquery-Dt-g_2cc.js +1 -0
- package/public/vs/powershell-B-7ap1zc.js +1 -0
- package/public/vs/protobuf-BmtuEB1A.js +2 -0
- package/public/vs/pug-BRpRNeEb.js +1 -0
- package/public/vs/python-Cr0UkIbn.js +1 -0
- package/public/vs/qsharp-BzsFaUU9.js +1 -0
- package/public/vs/r-f8dDdrp4.js +1 -0
- package/public/vs/razor-BYAHOTkz.js +1 -0
- package/public/vs/redis-fvZQY4PI.js +1 -0
- package/public/vs/redshift-45Et0LQi.js +1 -0
- package/public/vs/restructuredtext-C7UUFKFD.js +1 -0
- package/public/vs/ruby-CZO8zYTz.js +1 -0
- package/public/vs/rust-Bfetafyc.js +1 -0
- package/public/vs/sb-3GYllVck.js +1 -0
- package/public/vs/scala-foMgrKo1.js +1 -0
- package/public/vs/scheme-CHdMtr7p.js +1 -0
- package/public/vs/scss-C1cmLt9V.js +3 -0
- package/public/vs/shell-ClXCKCEW.js +1 -0
- package/public/vs/solidity-MZ6ExpPy.js +1 -0
- package/public/vs/sophia-DWkuSsPQ.js +1 -0
- package/public/vs/sparql-AUGFYSyk.js +1 -0
- package/public/vs/sql-32GpJSV2.js +1 -0
- package/public/vs/st-CuDFIVZ_.js +1 -0
- package/public/vs/swift-n-2HociN.js +3 -0
- package/public/vs/systemverilog-Ch4vA8Yt.js +1 -0
- package/public/vs/tcl-D74tq1nH.js +1 -0
- package/public/vs/tsMode-CZz1Umrk.js +11 -0
- package/public/vs/twig-C6taOxMV.js +1 -0
- package/public/vs/typescript-DfOrAzoV.js +1 -0
- package/public/vs/typespec-D-PIh9Xw.js +1 -0
- package/public/vs/vb-Dyb2648j.js +1 -0
- package/public/vs/wgsl-BhLXMOR0.js +298 -0
- package/public/vs/workers-DcJshg-q.js +1 -0
- package/public/vs/xml-CdsdnY8S.js +1 -0
- package/public/vs/yaml-DYGvmE88.js +1 -0
- package/src/actions/__tests__/agent-actions-username.test.ts +30 -0
- package/src/actions/__tests__/asset-actions.test.ts +251 -0
- package/src/actions/__tests__/assistant-actions.test.ts +20 -0
- package/src/actions/__tests__/cli-profile-actions.test.ts +243 -0
- package/src/actions/__tests__/label-actions.test.ts +187 -0
- package/src/actions/__tests__/note-actions.test.ts +237 -0
- package/src/actions/__tests__/onboarding-actions.test.ts +265 -0
- package/src/actions/__tests__/project-actions.test.ts +179 -0
- package/src/actions/__tests__/prompt-actions.test.ts +213 -0
- package/src/actions/__tests__/report-actions.test.ts +246 -0
- package/src/actions/__tests__/search-code-actions.test.ts +308 -0
- package/src/actions/__tests__/task-actions-overview.test.ts +58 -0
- package/src/actions/__tests__/task-actions-pin.test.ts +79 -0
- package/src/actions/__tests__/workspace-actions.test.ts +256 -0
- package/src/components/layout/__tests__/top-bar-username.test.tsx +24 -0
- package/src/components/onboarding/__tests__/onboarding-wizard.test.tsx +185 -0
- package/src/hooks/__tests__/sse-event-reducer.test.ts +263 -0
- package/src/hooks/__tests__/use-assistant-chat.test.ts +34 -0
- package/src/hooks/__tests__/use-image-upload.test.ts +443 -0
- package/src/lib/__tests__/assistant-message-converter.test.ts +162 -0
- package/src/lib/__tests__/assistant-sessions.test.ts +253 -0
- package/src/lib/__tests__/build-multimodal-prompt.test.ts +173 -0
- package/src/lib/__tests__/config-reader.test.ts +75 -0
- package/src/lib/__tests__/diff-parser.test.ts +212 -0
- package/src/lib/__tests__/execution-summary.test.ts +237 -0
- package/src/lib/__tests__/file-serve.test.ts +178 -0
- package/src/lib/__tests__/file-utils.test.ts +177 -0
- package/src/lib/__tests__/internal-api-guard.test.ts +151 -0
- package/src/lib/__tests__/logger.test.ts +181 -0
- package/src/lib/__tests__/platform.test.ts +566 -0
- package/src/lib/__tests__/reveal-route-security.test.ts +65 -0
- package/src/lib/__tests__/schemas.test.ts +377 -0
- package/src/lib/__tests__/terminal-link-provider.test.ts +160 -0
- package/src/lib/__tests__/upload-route-security.test.ts +120 -0
- package/src/lib/ai/__tests__/capability-resolver.test.ts +71 -0
- package/src/lib/ai/__tests__/claude-cli-adapter.test.ts +103 -0
- package/src/lib/ai/__tests__/provider-registry.test.ts +74 -0
- package/src/lib/pty/__tests__/ws-server-assistant.test.ts +7 -0
- package/.next/standalone/tower/.claude/rules/process-lifecycle.md +0 -31
- package/.next/standalone/tower/.claude/rules/security.md +0 -29
- package/.next/standalone/tower/.claude/rules/ui.md +0 -105
- package/.next/standalone/tower/AGENTS.md +0 -325
- package/.next/standalone/tower/CHANGELOG.md +0 -63
- package/.next/standalone/tower/CLAUDE.md +0 -33
- package/.next/standalone/tower/LICENSE +0 -21
- package/.next/standalone/tower/README.md +0 -214
- package/.next/standalone/tower/README.zh.md +0 -212
- package/.next/standalone/tower/bin/tower.mjs +0 -180
- package/.next/standalone/tower/docs/README.md +0 -51
- package/.next/standalone/tower/docs/ai/README.md +0 -91
- package/.next/standalone/tower/docs/ai/cli-abstraction-design.md +0 -398
- package/.next/standalone/tower/docs/ai/cli-abstraction-plan.md +0 -1345
- package/.next/standalone/tower/docs/assets-notes/README.md +0 -41
- package/.next/standalone/tower/docs/assistant/README.md +0 -48
- package/.next/standalone/tower/docs/board/README.md +0 -36
- package/.next/standalone/tower/docs/diagrams/tower-ai-architecture-en.html +0 -259
- package/.next/standalone/tower/docs/diagrams/tower-ai-architecture.html +0 -259
- package/.next/standalone/tower/docs/diagrams/tower-data-model-en.html +0 -344
- package/.next/standalone/tower/docs/diagrams/tower-data-model.html +0 -344
- package/.next/standalone/tower/docs/diagrams/tower-module-map-en.html +0 -176
- package/.next/standalone/tower/docs/diagrams/tower-module-map.html +0 -176
- package/.next/standalone/tower/docs/diagrams/tower-system-architecture-en.html +0 -336
- package/.next/standalone/tower/docs/diagrams/tower-system-architecture.html +0 -336
- package/.next/standalone/tower/docs/diagrams/tower-task-lifecycle-en.html +0 -251
- package/.next/standalone/tower/docs/diagrams/tower-task-lifecycle.html +0 -251
- package/.next/standalone/tower/docs/en/guide/architecture.md +0 -79
- package/.next/standalone/tower/docs/en/guide/diagrams.md +0 -24
- package/.next/standalone/tower/docs/en/guide/getting-started.md +0 -80
- package/.next/standalone/tower/docs/en/guide/introduction.md +0 -84
- package/.next/standalone/tower/docs/en/index.md +0 -36
- package/.next/standalone/tower/docs/en/modules/ai.md +0 -110
- package/.next/standalone/tower/docs/en/modules/assets-notes.md +0 -56
- package/.next/standalone/tower/docs/en/modules/assistant.md +0 -63
- package/.next/standalone/tower/docs/en/modules/board.md +0 -44
- package/.next/standalone/tower/docs/en/modules/git.md +0 -55
- package/.next/standalone/tower/docs/en/modules/i18n.md +0 -35
- package/.next/standalone/tower/docs/en/modules/mcp.md +0 -62
- package/.next/standalone/tower/docs/en/modules/missions.md +0 -47
- package/.next/standalone/tower/docs/en/modules/project.md +0 -57
- package/.next/standalone/tower/docs/en/modules/search.md +0 -49
- package/.next/standalone/tower/docs/en/modules/settings.md +0 -63
- package/.next/standalone/tower/docs/en/modules/task.md +0 -82
- package/.next/standalone/tower/docs/en/modules/terminal.md +0 -73
- package/.next/standalone/tower/docs/en/modules/workspace.md +0 -61
- package/.next/standalone/tower/docs/git/README.md +0 -42
- package/.next/standalone/tower/docs/guide/architecture.md +0 -29
- package/.next/standalone/tower/docs/guide/diagrams.md +0 -24
- package/.next/standalone/tower/docs/guide/getting-started.md +0 -80
- package/.next/standalone/tower/docs/guide/introduction.md +0 -84
- package/.next/standalone/tower/docs/i18n/README.md +0 -23
- package/.next/standalone/tower/docs/index.md +0 -36
- package/.next/standalone/tower/docs/mcp/README.md +0 -50
- package/.next/standalone/tower/docs/missions/README.md +0 -40
- package/.next/standalone/tower/docs/modules/ai.md +0 -104
- package/.next/standalone/tower/docs/modules/assets-notes.md +0 -68
- package/.next/standalone/tower/docs/modules/assistant.md +0 -74
- package/.next/standalone/tower/docs/modules/board.md +0 -56
- package/.next/standalone/tower/docs/modules/git.md +0 -61
- package/.next/standalone/tower/docs/modules/i18n.md +0 -38
- package/.next/standalone/tower/docs/modules/mcp.md +0 -68
- package/.next/standalone/tower/docs/modules/missions.md +0 -54
- package/.next/standalone/tower/docs/modules/project.md +0 -65
- package/.next/standalone/tower/docs/modules/search.md +0 -57
- package/.next/standalone/tower/docs/modules/settings.md +0 -72
- package/.next/standalone/tower/docs/modules/task.md +0 -82
- package/.next/standalone/tower/docs/modules/terminal.md +0 -70
- package/.next/standalone/tower/docs/modules/workspace.md +0 -68
- package/.next/standalone/tower/docs/package.json +0 -11
- package/.next/standalone/tower/docs/pnpm-lock.yaml +0 -1620
- package/.next/standalone/tower/docs/postcss.config.mjs +0 -2
- package/.next/standalone/tower/docs/project/README.md +0 -45
- package/.next/standalone/tower/docs/public/banner.png +0 -0
- package/.next/standalone/tower/docs/public/diagrams/tower-ai-architecture-en.html +0 -259
- package/.next/standalone/tower/docs/public/diagrams/tower-ai-architecture.html +0 -259
- package/.next/standalone/tower/docs/public/diagrams/tower-data-model-en.html +0 -344
- package/.next/standalone/tower/docs/public/diagrams/tower-data-model.html +0 -344
- package/.next/standalone/tower/docs/public/diagrams/tower-module-map-en.html +0 -176
- package/.next/standalone/tower/docs/public/diagrams/tower-module-map.html +0 -176
- package/.next/standalone/tower/docs/public/diagrams/tower-system-architecture-en.html +0 -336
- package/.next/standalone/tower/docs/public/diagrams/tower-system-architecture.html +0 -336
- package/.next/standalone/tower/docs/public/diagrams/tower-task-lifecycle-en.html +0 -251
- package/.next/standalone/tower/docs/public/diagrams/tower-task-lifecycle.html +0 -251
- package/.next/standalone/tower/docs/search/README.md +0 -37
- package/.next/standalone/tower/docs/settings/README.md +0 -43
- package/.next/standalone/tower/docs/task/README.md +0 -67
- package/.next/standalone/tower/docs/terminal/README.md +0 -58
- package/.next/standalone/tower/docs/workspace/README.md +0 -50
- package/.next/standalone/tower/docs/zh/guide/architecture.md +0 -29
- package/.next/standalone/tower/docs/zh/guide/diagrams.md +0 -24
- package/.next/standalone/tower/docs/zh/guide/getting-started.md +0 -80
- package/.next/standalone/tower/docs/zh/guide/introduction.md +0 -66
- package/.next/standalone/tower/docs/zh/index.md +0 -23
- package/.next/standalone/tower/docs/zh/modules/ai.md +0 -104
- package/.next/standalone/tower/docs/zh/modules/assets-notes.md +0 -68
- package/.next/standalone/tower/docs/zh/modules/assistant.md +0 -74
- package/.next/standalone/tower/docs/zh/modules/board.md +0 -56
- package/.next/standalone/tower/docs/zh/modules/git.md +0 -61
- package/.next/standalone/tower/docs/zh/modules/i18n.md +0 -38
- package/.next/standalone/tower/docs/zh/modules/mcp.md +0 -68
- package/.next/standalone/tower/docs/zh/modules/missions.md +0 -54
- package/.next/standalone/tower/docs/zh/modules/project.md +0 -65
- package/.next/standalone/tower/docs/zh/modules/search.md +0 -57
- package/.next/standalone/tower/docs/zh/modules/settings.md +0 -72
- package/.next/standalone/tower/docs/zh/modules/task.md +0 -82
- package/.next/standalone/tower/docs/zh/modules/terminal.md +0 -70
- package/.next/standalone/tower/docs/zh/modules/workspace.md +0 -68
- package/.next/standalone/tower/eslint.config.mjs +0 -18
- package/.next/standalone/tower/next.config.ts +0 -15
- package/.next/standalone/tower/package.json +0 -117
- package/.next/standalone/tower/playwright.config.ts +0 -28
- package/.next/standalone/tower/pnpm-lock.yaml +0 -10524
- package/.next/standalone/tower/pnpm-workspace.yaml +0 -6
- package/.next/standalone/tower/prisma/init-fts.ts +0 -23
- package/.next/standalone/tower/prisma/schema.prisma +0 -290
- package/.next/standalone/tower/prompts/backend-developer.md +0 -20
- package/.next/standalone/tower/prompts/code-reviewer.md +0 -19
- package/.next/standalone/tower/prompts/frontend-developer.md +0 -20
- package/.next/standalone/tower/prompts/product-manager.md +0 -16
- package/.next/standalone/tower/public/banner.jpg +0 -0
- package/.next/standalone/tower/public/logo.png +0 -0
- package/.next/standalone/tower/scripts/copy-monaco.js +0 -27
- package/.next/standalone/tower/scripts/init-db.ts +0 -74
- package/.next/standalone/tower/scripts/migrate-data.ts +0 -102
- package/.next/standalone/tower/server.js +0 -38
- package/.next/standalone/tower/src/app/favicon.ico +0 -0
- package/.next/standalone/tower/src/mcp/db.ts +0 -11
- package/.next/standalone/tower/src/mcp/index.ts +0 -15
- package/.next/standalone/tower/src/mcp/server.ts +0 -52
- package/.next/standalone/tower/src/mcp/tools/knowledge-tools.ts +0 -100
- package/.next/standalone/tower/src/mcp/tools/label-tools.ts +0 -70
- package/.next/standalone/tower/src/mcp/tools/note-asset-tools.ts +0 -271
- package/.next/standalone/tower/src/mcp/tools/project-tools.ts +0 -79
- package/.next/standalone/tower/src/mcp/tools/report-tools.ts +0 -214
- package/.next/standalone/tower/src/mcp/tools/search-tools.ts +0 -32
- package/.next/standalone/tower/src/mcp/tools/task-tools.ts +0 -250
- package/.next/standalone/tower/src/mcp/tools/terminal-tools.ts +0 -154
- package/.next/standalone/tower/src/mcp/tools/workspace-tools.ts +0 -73
- package/.next/standalone/tower/tests/e2e/chat-flow.spec.ts +0 -249
- package/.next/standalone/tower/tests/e2e/notes-assets.spec.ts +0 -287
- package/.next/standalone/tower/tests/e2e/search.spec.ts +0 -186
- package/.next/standalone/tower/tests/e2e/settings-flow.spec.ts +0 -250
- package/.next/standalone/tower/tests/e2e/settings.spec.ts +0 -261
- package/.next/standalone/tower/tests/e2e/smoke.spec.ts +0 -317
- package/.next/standalone/tower/tests/e2e/task-flow.spec.ts +0 -287
- package/.next/standalone/tower/tests/e2e/workbench.spec.ts +0 -307
- package/.next/standalone/tower/tests/setup.ts +0 -15
- package/.next/standalone/tower/tests/unit/actions/agent-actions.test.ts +0 -157
- package/.next/standalone/tower/tests/unit/actions/config-actions.test.ts +0 -170
- package/.next/standalone/tower/tests/unit/actions/file-actions.test.ts +0 -283
- package/.next/standalone/tower/tests/unit/actions/git-actions.test.ts +0 -34
- package/.next/standalone/tower/tests/unit/actions/preview-actions.test.ts +0 -177
- package/.next/standalone/tower/tests/unit/actions/search-actions.test.ts +0 -358
- package/.next/standalone/tower/tests/unit/actions/task-actions.test.ts +0 -173
- package/.next/standalone/tower/tests/unit/api/diff-route.test.ts +0 -9
- package/.next/standalone/tower/tests/unit/api/file-serving.test.ts +0 -88
- package/.next/standalone/tower/tests/unit/api/merge-route.test.ts +0 -9
- package/.next/standalone/tower/tests/unit/api/stream-persist-result.test.ts +0 -7
- package/.next/standalone/tower/tests/unit/api/stream-send-back.test.ts +0 -7
- package/.next/standalone/tower/tests/unit/components/asset-item.test.tsx +0 -105
- package/.next/standalone/tower/tests/unit/components/asset-list.test.tsx +0 -51
- package/.next/standalone/tower/tests/unit/components/assets/asset-upload.test.tsx +0 -70
- package/.next/standalone/tower/tests/unit/components/board-stats.test.tsx +0 -32
- package/.next/standalone/tower/tests/unit/components/category-filter.test.tsx +0 -58
- package/.next/standalone/tower/tests/unit/components/cli-adapter-tester.test.tsx +0 -160
- package/.next/standalone/tower/tests/unit/components/create-task-dialog.test.tsx +0 -162
- package/.next/standalone/tower/tests/unit/components/file-tree.test.tsx +0 -172
- package/.next/standalone/tower/tests/unit/components/note-card.test.tsx +0 -71
- package/.next/standalone/tower/tests/unit/components/note-editor.test.tsx +0 -39
- package/.next/standalone/tower/tests/unit/components/prompts-config.test.tsx +0 -200
- package/.next/standalone/tower/tests/unit/components/search-dialog.test.tsx +0 -223
- package/.next/standalone/tower/tests/unit/components/system-config.test.tsx +0 -32
- package/.next/standalone/tower/tests/unit/hooks/hook-registration.test.ts +0 -89
- package/.next/standalone/tower/tests/unit/hooks/stop-hook.test.ts +0 -108
- package/.next/standalone/tower/tests/unit/lib/asset-actions.test.ts +0 -257
- package/.next/standalone/tower/tests/unit/lib/file-utils.test.ts +0 -102
- package/.next/standalone/tower/tests/unit/lib/fs-security.test.ts +0 -34
- package/.next/standalone/tower/tests/unit/lib/fts.test.ts +0 -214
- package/.next/standalone/tower/tests/unit/lib/git-url.test.ts +0 -258
- package/.next/standalone/tower/tests/unit/lib/instrumentation.test.ts +0 -86
- package/.next/standalone/tower/tests/unit/lib/local-path-to-api-url.test.ts +0 -40
- package/.next/standalone/tower/tests/unit/lib/mime-magic.test.ts +0 -95
- package/.next/standalone/tower/tests/unit/lib/note-actions.test.ts +0 -296
- package/.next/standalone/tower/tests/unit/lib/preview-process-manager.test.ts +0 -107
- package/.next/standalone/tower/tests/unit/lib/process-manager.test.ts +0 -10
- package/.next/standalone/tower/tests/unit/lib/pty-session.test.ts +0 -171
- package/.next/standalone/tower/tests/unit/lib/search.test.ts +0 -289
- package/.next/standalone/tower/tests/unit/lib/session-store.test.ts +0 -111
- package/.next/standalone/tower/tests/unit/lib/utils.test.ts +0 -33
- package/.next/standalone/tower/tests/unit/lib/worktree.test.ts +0 -190
- package/.next/standalone/tower/tests/unit/mcp/identify-project.test.ts +0 -217
- package/.next/standalone/tower/tests/unit/mcp/manage-assets.test.ts +0 -199
- package/.next/standalone/tower/tests/unit/mcp/manage-notes.test.ts +0 -304
- package/.next/standalone/tower/tests/unit/mcp/search-tools.test.ts +0 -186
- package/.next/standalone/tower/tests/unit/missions-merge.test.ts +0 -43
- package/.next/standalone/tower/tower-studio-0.1.1.tgz +0 -0
- package/.next/standalone/tower/tsconfig.json +0 -34
- package/.next/standalone/tower/vitest.config.ts +0 -17
- package/.next/static/a6HR9cTK7s4aKfE5dWzjz/_buildManifest.js +0 -11
- package/.next/static/a6HR9cTK7s4aKfE5dWzjz/_clientMiddlewareManifest.js +0 -1
- package/.next/static/a6HR9cTK7s4aKfE5dWzjz/_ssgManifest.js +0 -1
- package/.next/static/chunks/00z-g3x93ngvn.js +0 -1
- package/.next/static/chunks/024pdsc27tjdd.js +0 -5
- package/.next/static/chunks/02dd83gbiv778.js +0 -1
- package/.next/static/chunks/03e.4ymu.j5wl.js +0 -1
- package/.next/static/chunks/03~yq9q893hmn.js +0 -1
- package/.next/static/chunks/05-b9qqm3av9~.js +0 -1
- package/.next/static/chunks/05~v02mkan5z..js +0 -1
- package/.next/static/chunks/0abtpeymj-58i.js +0 -1
- package/.next/static/chunks/0b6us7uq72u-d.js +0 -1
- package/.next/static/chunks/0drgc-oztq6o-.css +0 -1
- package/.next/static/chunks/0eaa2lmymh2fx.js +0 -1
- package/.next/static/chunks/0gb82g.6g90mn.js +0 -1
- package/.next/static/chunks/0gnm22yv~f54b.js +0 -1
- package/.next/static/chunks/0j9qriqni_r1..js +0 -2
- package/.next/static/chunks/0k.u8sxy~e469.js +0 -4
- package/.next/static/chunks/0lnhjf2a~jaco.js +0 -83
- package/.next/static/chunks/0lvd52mjiit6s.js +0 -1
- package/.next/static/chunks/0mq0uqbbbb1~2.js +0 -1
- package/.next/static/chunks/0neevhl_o1ozu.css +0 -2
- package/.next/static/chunks/0omj~p3uxkic-.js +0 -1
- package/.next/static/chunks/0t-gr6j-c65qb.js +0 -1
- package/.next/static/chunks/0t16ai99uv4j3.js +0 -1
- package/.next/static/chunks/0tcl81ybuob5i.js +0 -1
- package/.next/static/chunks/0uqimvsni_op~.js +0 -1
- package/.next/static/chunks/0wt3kws~_yr8z.js +0 -1
- package/.next/static/chunks/0xzdu87n_for1.js +0 -5
- package/.next/static/chunks/0y0tdl.rl6v1u.js +0 -1
- package/.next/static/chunks/0z2bzovqhl2f5.js +0 -1
- package/.next/static/chunks/0z4y0x1ifgy.e.js +0 -1
- package/.next/static/chunks/0z7bwntvfhxzi.js +0 -12
- package/.next/static/chunks/102ijqpvi0z-d.js +0 -1
- package/.next/static/chunks/10n23t.1hpb-1.js +0 -1
- package/.next/static/chunks/11_e3-j5gzbj4.js +0 -1
- package/.next/static/chunks/14.ims4y7osot.js +0 -1
- package/.next/static/chunks/14xzmrt5ly6gq.js +0 -31
- package/.next/static/chunks/151wr~6x8aclx.js +0 -1
- package/.next/static/chunks/169po6_~f3-d5.js +0 -1
- package/.next/static/chunks/16w-ap~msrwpj.js +0 -1
- package/.next/static/chunks/176n7f13ve~a9.js +0 -1
- package/.next/static/chunks/17oc2l.ekcs8b.css +0 -1
- package/.next/static/chunks/turbopack-0wjmrsi.z32s0.js +0 -1
- package/.next/static/media/4fa387ec64143e14-s.0q3udbd2bu5yp.woff2 +0 -0
- package/.next/static/media/7178b3e590c64307-s.11.cyxs5p-0z~.woff2 +0 -0
- package/.next/static/media/797e433ab948586e-s.p.0.q-h669a_dqa.woff2 +0 -0
- package/.next/static/media/8a480f0b521d4e75-s.06d3mdzz5bre_.woff2 +0 -0
- package/.next/static/media/apple-icon.16aocl-s-v2qz.png +0 -0
- package/.next/static/media/bbc41e54d2fcbd21-s.0gw~uztddq1df.woff2 +0 -0
- package/.next/static/media/caa3a2e1cccd8315-s.p.16t1db8_9y2o~.woff2 +0 -0
- package/.next/static/media/favicon.0y2d6j9cou~8p.ico +0 -0
- package/.next/static/media/icon0.0a6mkq6meyird.svg +0 -1
- package/.next/static/media/icon1.04ux133882seb.png +0 -0
- /package/{.next/standalone/tower/components.json → components.json} +0 -0
- /package/{.next/standalone/tower/postcss.config.mjs → postcss.config.mjs} +0 -0
- /package/{.next/standalone/tower/prisma → prisma}/prisma/dev.db +0 -0
- /package/{.next/standalone/tower/prisma → prisma}/seed.ts +0 -0
- /package/{.next/standalone/tower/docs/public → public}/banner.jpg +0 -0
- /package/{.next/standalone/tower/docs/public → public}/logo.png +0 -0
- /package/{.next/standalone/tower/public → public}/web-app-manifest-192x192.png +0 -0
- /package/{.next/standalone/tower/public → public}/web-app-manifest-512x512.png +0 -0
- /package/{.next/standalone/tower/scripts → scripts}/init-tower.ts +0 -0
- /package/{.next/standalone/tower/scripts → scripts}/post-tool-hook.js +0 -0
- /package/{.next/standalone/tower/scripts → scripts}/session-start-hook.js +0 -0
- /package/{.next/standalone/tower/scripts → scripts}/stop-hook.js +0 -0
- /package/{.next/standalone/tower/skills → skills}/tower/SKILL.md +0 -0
- /package/{.next/standalone/tower/src → src}/actions/agent-actions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/actions/agent-config-actions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/actions/ai-config-actions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/actions/asset-actions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/actions/assistant-actions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/actions/cli-profile-actions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/actions/config-actions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/actions/file-actions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/actions/git-actions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/actions/label-actions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/actions/note-actions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/actions/onboarding-actions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/actions/preview-actions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/actions/project-actions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/actions/prompt-actions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/actions/report-actions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/actions/search-actions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/actions/search-code-actions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/actions/task-actions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/actions/workspace-actions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/api/adapters/test/route.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/api/browse-fs/route.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/api/files/assets/[projectId]/[filename]/route.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/api/git/route.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/api/internal/assets/[projectId]/[filename]/route.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/api/internal/assets/reveal/route.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/api/internal/assistant/chat/route.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/api/internal/assistant/images/route.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/api/internal/assistant/route.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/api/internal/assistant/sessions/route.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/api/internal/cache/[...segments]/route.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/api/internal/hooks/install/route.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/api/internal/hooks/session/route.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/api/internal/hooks/stop/route.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/api/internal/hooks/upload/route.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/api/internal/notifications/pending/route.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/api/internal/terminal/[taskId]/buffer/route.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/api/internal/terminal/[taskId]/input/route.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/api/internal/terminal/[taskId]/start/route.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/api/tasks/[taskId]/diff/route.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/api/tasks/[taskId]/merge/route.ts +0 -0
- /package/{.next/standalone/tower/src → src}/app/apple-icon.png +0 -0
- /package/{.next/standalone/tower/docs/public → src/app}/favicon.ico +0 -0
- /package/{.next/standalone/tower/src → src}/app/globals.css +0 -0
- /package/{.next/standalone/tower/src → src}/app/icon0.svg +0 -0
- /package/{.next/standalone/tower/src → src}/app/icon1.png +0 -0
- /package/{.next/standalone/tower/src → src}/app/layout.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/app/manifest.json +0 -0
- /package/{.next/standalone/tower/src → src}/app/missions/missions-client.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/app/missions/page.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/app/onboarding/page.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/app/page.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/app/settings/page.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/app/workspaces/[workspaceId]/archive/archive-page-client.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/app/workspaces/[workspaceId]/archive/page.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/app/workspaces/[workspaceId]/assets/assets-page-client.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/app/workspaces/[workspaceId]/assets/page.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/app/workspaces/[workspaceId]/board-page-client.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/app/workspaces/[workspaceId]/notes/notes-page-client.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/app/workspaces/[workspaceId]/notes/page.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/app/workspaces/[workspaceId]/page.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/app/workspaces/[workspaceId]/projects/[projectId]/page.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/app/workspaces/[workspaceId]/tasks/[taskId]/page.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/app/workspaces/[workspaceId]/tasks/[taskId]/task-page-client.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/app/workspaces/page.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/assets/asset-item.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/assets/asset-list.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/assets/asset-upload.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/assets/image-lightbox.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/assets/text-preview-dialog.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/assistant/assistant-chat-bubble.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/assistant/assistant-chat.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/assistant/assistant-panel.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/assistant/assistant-provider.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/assistant/image-preview-modal.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/assistant/image-thumbnail-strip.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/board/board-column.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/board/board-filters.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/board/board-stats.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/board/column-tasks-dialog.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/board/create-task-dialog.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/board/kanban-board.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/board/project-tabs.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/board/task-card-context-menu.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/board/task-card.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/layout/app-sidebar.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/layout/folder-browser-dialog.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/layout/layout-client.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/layout/search-dialog.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/layout/sub-page-nav.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/layout/top-bar.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/missions/grid-layout-presets.ts +0 -0
- /package/{.next/standalone/tower/src → src}/components/missions/grid-preset-picker.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/missions/merge-missions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/components/missions/mission-card.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/missions/task-picker-dialog.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/notes/category-filter.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/notes/note-card.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/notes/note-editor.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/notes/note-list.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/notifications/notification-permission-banner.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/notifications/use-notification-listener.ts +0 -0
- /package/{.next/standalone/tower/src → src}/components/onboarding/guided-tour.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/onboarding/onboarding-wizard.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/onboarding/wizard-step-cli.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/onboarding/wizard-step-username.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/project/create-project-dialog.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/project/import-project-dialog.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/providers/theme-provider.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/repository/create-branch-dialog.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/repository/git-changes-panel.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/repository/git-log-panel.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/repository/git-stash-panel.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/repository/repo-sidebar.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/settings/cli-adapter-tester.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/settings/settings-page.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/task/code-editor.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/task/code-search.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/task/diff-editor.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/task/editor-git-panel.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/task/editor-tabs.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/task/execution-timeline.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/task/file-tree-context-menu.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/task/file-tree-node.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/task/file-tree.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/task/preview-panel.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/task/task-detail-panel.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/task/task-diff-view.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/task/task-file-changes.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/task/task-merge-confirm-dialog.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/task/task-metadata.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/task/task-notes-panel.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/task/task-overview-drawer.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/task/task-terminal.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/task/terminal-portal.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/task/types.ts +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/avatar.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/badge.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/button.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/card.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/command.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/dialog.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/dropdown-menu.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/empty-state.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/error-boundary.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/input-group.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/input.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/label.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/popover.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/scroll-area.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/segmented-control.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/select.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/separator.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/sheet.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/sonner.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/switch.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/tabs.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/textarea.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/toast.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/components/ui/tooltip.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/hooks/sse-event-reducer.ts +0 -0
- /package/{.next/standalone/tower/src → src}/hooks/use-assistant-chat.ts +0 -0
- /package/{.next/standalone/tower/src → src}/hooks/use-image-upload.ts +0 -0
- /package/{.next/standalone/tower/src → src}/instrumentation.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/ai/adapters/cli/claude-cli-adapter.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/ai/capability-resolver.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/ai/provider-registry.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/ai/providers/claude.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/ai/providers/index.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/ai/types.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/assistant-constants.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/assistant-message-converter.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/assistant-sessions.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/build-multimodal-prompt.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/claude-session.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/cli-test.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/config-defaults.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/config-reader.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/constants.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/db.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/diff-parser.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/execution-summary.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/file-serve-client.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/file-serve.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/file-utils.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/fs-security.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/fts.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/git-api.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/git-url.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/i18n/en.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/i18n/types.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/i18n/zh.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/i18n.tsx +0 -0
- /package/{.next/standalone/tower/src → src}/lib/init-tower.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/instrumentation-tasks.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/internal-api-guard.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/logger.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/mime-magic.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/platform.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/preview-process.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/pty/pty-session.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/pty/session-store.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/pty/ws-server.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/schemas.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/search.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/terminal-link-provider.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/tower-dir.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/utils.ts +0 -0
- /package/{.next/standalone/tower/src → src}/lib/worktree.ts +0 -0
- /package/{.next/standalone/tower/src → src}/stores/board-store.ts +0 -0
- /package/{.next/standalone/tower/src → src}/stores/task-execution-store.ts +0 -0
- /package/{.next/standalone/tower/src → src}/types/index.ts +0 -0
|
@@ -1,287 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* E2E-01: Task Lifecycle Flow
|
|
3
|
-
*
|
|
4
|
-
* Covers the full task lifecycle: create task → change status to IN_PROGRESS → mark DONE.
|
|
5
|
-
* Uses serial execution to maintain shared page state across steps.
|
|
6
|
-
*/
|
|
7
|
-
import { test, expect } from "@playwright/test";
|
|
8
|
-
|
|
9
|
-
const TASK_TITLE = `E2E Task Lifecycle ${Date.now()}`;
|
|
10
|
-
|
|
11
|
-
/** Navigate to the first available workspace kanban board. Returns false if no workspace exists. */
|
|
12
|
-
async function navigateToFirstWorkspace(page: import("@playwright/test").Page): Promise<boolean> {
|
|
13
|
-
await page.goto("/workspaces");
|
|
14
|
-
await page.waitForLoadState("domcontentloaded");
|
|
15
|
-
await page.waitForTimeout(800);
|
|
16
|
-
|
|
17
|
-
// If already on a workspace board page, board is already rendered
|
|
18
|
-
const currentUrl = page.url();
|
|
19
|
-
if (currentUrl.match(/\/workspaces\/[a-z0-9]{20,}/)) {
|
|
20
|
-
await page.waitForTimeout(500);
|
|
21
|
-
return true;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Find workspace buttons in the sidebar.
|
|
25
|
-
// The AppSidebar renders workspace buttons with workspace name + relative time (e.g. "EBG\n6d ago").
|
|
26
|
-
// Time format from formatTime(): "Xm ago", "Xh ago", or "Xd ago".
|
|
27
|
-
const sidebar = page.locator("aside");
|
|
28
|
-
await sidebar.waitFor({ state: "visible", timeout: 5000 }).catch(() => {});
|
|
29
|
-
await page.waitForTimeout(300);
|
|
30
|
-
|
|
31
|
-
const allSidebarBtns = sidebar.locator("button");
|
|
32
|
-
const count = await allSidebarBtns.count();
|
|
33
|
-
|
|
34
|
-
for (let i = 0; i < count; i++) {
|
|
35
|
-
const btn = allSidebarBtns.nth(i);
|
|
36
|
-
const title = await btn.getAttribute("title");
|
|
37
|
-
const text = await btn.textContent();
|
|
38
|
-
|
|
39
|
-
// Skip control/icon-only buttons
|
|
40
|
-
if (title?.includes("新建") || title?.includes("折叠") || title?.includes("collapse")) continue;
|
|
41
|
-
if (!text || text.trim().length < 4) continue;
|
|
42
|
-
|
|
43
|
-
// Workspace buttons contain name + time (formatTime gives "Xm ago", "Xh ago", "Xd ago")
|
|
44
|
-
const hasTimePattern = /\d+[mhd]\s+ago/.test(text);
|
|
45
|
-
// Exclude known nav items to avoid clicking settings/missions links
|
|
46
|
-
const isNavItem = /工作空间|控制台|设置|Settings|Workspace|Control|归档|Archive|Notes|Assets/.test(text);
|
|
47
|
-
|
|
48
|
-
if (hasTimePattern || (!isNavItem && text.trim().length >= 4)) {
|
|
49
|
-
try {
|
|
50
|
-
await btn.click();
|
|
51
|
-
await page.waitForURL(/\/workspaces\/[a-z0-9]{20,}/, { timeout: 6000 });
|
|
52
|
-
await page.waitForTimeout(800);
|
|
53
|
-
return true;
|
|
54
|
-
} catch {
|
|
55
|
-
// URL didn't change — try next button
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
test.describe.serial("Task Lifecycle Flow", () => {
|
|
64
|
-
test("1. Navigate to workspace board", async ({ page }) => {
|
|
65
|
-
const ok = await navigateToFirstWorkspace(page);
|
|
66
|
-
if (!ok) {
|
|
67
|
-
// No workspace exists yet — that's fine, subsequent tests will skip
|
|
68
|
-
test.skip();
|
|
69
|
-
}
|
|
70
|
-
await expect(page).toHaveURL(/\/workspaces\/\w/);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
test("2. Create a new task in the kanban board", async ({ page }) => {
|
|
74
|
-
const ok = await navigateToFirstWorkspace(page);
|
|
75
|
-
if (!ok) {
|
|
76
|
-
test.skip();
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Wait for the kanban board to fully render
|
|
81
|
-
await page.waitForSelector("header, main", { timeout: 5000 }).catch(() => {});
|
|
82
|
-
await page.waitForTimeout(1000);
|
|
83
|
-
|
|
84
|
-
// Find the "新建任务" / "New Task" button (BoardFilters component, t("board.newTask"))
|
|
85
|
-
let clicked = false;
|
|
86
|
-
|
|
87
|
-
const newTaskBtn = page.locator("button").filter({ hasText: /新建任务|New Task/ });
|
|
88
|
-
if (await newTaskBtn.count() > 0 && await newTaskBtn.first().isVisible({ timeout: 3000 }).catch(() => false)) {
|
|
89
|
-
await newTaskBtn.first().click();
|
|
90
|
-
clicked = true;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (!clicked) {
|
|
94
|
-
// Fallback: scan all buttons
|
|
95
|
-
const allBtns = page.locator("button");
|
|
96
|
-
const count = await allBtns.count();
|
|
97
|
-
for (let i = 0; i < count; i++) {
|
|
98
|
-
const text = await allBtns.nth(i).textContent();
|
|
99
|
-
if (text?.includes("新建任务") || text?.includes("New Task")) {
|
|
100
|
-
await allBtns.nth(i).click();
|
|
101
|
-
clicked = true;
|
|
102
|
-
break;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (!clicked) {
|
|
108
|
-
test.skip();
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const dialog = page.getByRole("dialog");
|
|
113
|
-
await expect(dialog).toBeVisible({ timeout: 5000 });
|
|
114
|
-
|
|
115
|
-
// Fill in the task title
|
|
116
|
-
const titleInput = dialog.locator("input").first();
|
|
117
|
-
await titleInput.fill(TASK_TITLE);
|
|
118
|
-
|
|
119
|
-
// Fill description if textarea exists
|
|
120
|
-
const textarea = dialog.locator("textarea");
|
|
121
|
-
if (await textarea.isVisible({ timeout: 1000 }).catch(() => false)) {
|
|
122
|
-
await textarea.fill("Automated E2E lifecycle test");
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Click the create/submit button
|
|
126
|
-
const dlgBtns = dialog.locator("button");
|
|
127
|
-
const dlgCount = await dlgBtns.count();
|
|
128
|
-
for (let i = 0; i < dlgCount; i++) {
|
|
129
|
-
const text = await dlgBtns.nth(i).textContent();
|
|
130
|
-
if (text?.includes("创建") || text?.includes("Create")) {
|
|
131
|
-
await dlgBtns.nth(i).click();
|
|
132
|
-
break;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
await expect(dialog).not.toBeVisible({ timeout: 8000 });
|
|
137
|
-
|
|
138
|
-
// Verify task appears in the board
|
|
139
|
-
await expect(page.getByText(TASK_TITLE)).toBeVisible({ timeout: 8000 });
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
test("3. Move task to IN_PROGRESS via context menu", async ({ page }) => {
|
|
143
|
-
const ok = await navigateToFirstWorkspace(page);
|
|
144
|
-
if (!ok) {
|
|
145
|
-
test.skip();
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
await page.waitForTimeout(500);
|
|
150
|
-
|
|
151
|
-
// Find the task card by title
|
|
152
|
-
const taskCard = page.locator("[data-testid='task-card']").filter({ hasText: TASK_TITLE });
|
|
153
|
-
const taskText = page.getByText(TASK_TITLE);
|
|
154
|
-
|
|
155
|
-
const cardVisible = await taskCard.isVisible({ timeout: 8000 }).catch(() => false);
|
|
156
|
-
const textVisible = await taskText.first().isVisible({ timeout: 3000 }).catch(() => false);
|
|
157
|
-
|
|
158
|
-
if (!cardVisible && !textVisible) {
|
|
159
|
-
test.skip();
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// Right-click to open the custom context menu (TaskCardContextMenu via createPortal)
|
|
164
|
-
if (cardVisible) {
|
|
165
|
-
await taskCard.first().click({ button: "right" });
|
|
166
|
-
} else {
|
|
167
|
-
await taskText.first().click({ button: "right" });
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// TaskCardContextMenu renders via createPortal into document.body at z-index: 9999.
|
|
171
|
-
// Menu items are plain <button> elements (no role="menuitem").
|
|
172
|
-
await page.waitForSelector("[style*='z-index: 9999']", { timeout: 3000 }).catch(() => {});
|
|
173
|
-
await page.waitForTimeout(200);
|
|
174
|
-
|
|
175
|
-
const contextMenu = page.locator("[style*='z-index: 9999']").last();
|
|
176
|
-
let statusChanged = false;
|
|
177
|
-
|
|
178
|
-
if (await contextMenu.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
179
|
-
const menuBtns = contextMenu.locator("button");
|
|
180
|
-
const count = await menuBtns.count();
|
|
181
|
-
for (let i = 0; i < count; i++) {
|
|
182
|
-
const text = await menuBtns.nth(i).textContent();
|
|
183
|
-
if (text?.includes("In Progress") || text?.includes("进行中")) {
|
|
184
|
-
await menuBtns.nth(i).click();
|
|
185
|
-
statusChanged = true;
|
|
186
|
-
break;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (!statusChanged) {
|
|
192
|
-
// Fallback: scan all buttons
|
|
193
|
-
const allBtns = page.locator("button");
|
|
194
|
-
const count = await allBtns.count();
|
|
195
|
-
for (let i = 0; i < count; i++) {
|
|
196
|
-
const text = await allBtns.nth(i).textContent();
|
|
197
|
-
if (text?.includes("In Progress") || text?.includes("进行中")) {
|
|
198
|
-
await allBtns.nth(i).click();
|
|
199
|
-
statusChanged = true;
|
|
200
|
-
break;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (!statusChanged) {
|
|
206
|
-
test.skip();
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
await page.waitForTimeout(500);
|
|
211
|
-
// Verify task is still visible after status change
|
|
212
|
-
await expect(page.getByText(TASK_TITLE)).toBeVisible({ timeout: 5000 });
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
test("4. Mark task as DONE via context menu", async ({ page }) => {
|
|
216
|
-
const ok = await navigateToFirstWorkspace(page);
|
|
217
|
-
if (!ok) {
|
|
218
|
-
test.skip();
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
await page.waitForTimeout(500);
|
|
223
|
-
|
|
224
|
-
// Find task card — it may now be in IN_PROGRESS column
|
|
225
|
-
const taskCard = page.locator("[data-testid='task-card']").filter({ hasText: TASK_TITLE });
|
|
226
|
-
const taskText = page.getByText(TASK_TITLE);
|
|
227
|
-
|
|
228
|
-
const cardVisible = await taskCard.isVisible({ timeout: 8000 }).catch(() => false);
|
|
229
|
-
const textVisible = await taskText.first().isVisible({ timeout: 3000 }).catch(() => false);
|
|
230
|
-
|
|
231
|
-
if (!cardVisible && !textVisible) {
|
|
232
|
-
test.skip();
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// Right-click to open the custom context menu
|
|
237
|
-
if (cardVisible) {
|
|
238
|
-
await taskCard.first().click({ button: "right" });
|
|
239
|
-
} else {
|
|
240
|
-
await taskText.first().click({ button: "right" });
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// Wait for context menu portal (same structure as test 3)
|
|
244
|
-
await page.waitForSelector("[style*='z-index: 9999']", { timeout: 3000 }).catch(() => {});
|
|
245
|
-
await page.waitForTimeout(200);
|
|
246
|
-
|
|
247
|
-
const contextMenu = page.locator("[style*='z-index: 9999']").last();
|
|
248
|
-
let statusChanged = false;
|
|
249
|
-
|
|
250
|
-
if (await contextMenu.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
251
|
-
const menuBtns = contextMenu.locator("button");
|
|
252
|
-
const count = await menuBtns.count();
|
|
253
|
-
for (let i = 0; i < count; i++) {
|
|
254
|
-
const text = await menuBtns.nth(i).textContent();
|
|
255
|
-
// "Done" is the BOARD_COLUMNS label (BOARD_COLUMNS in constants.ts)
|
|
256
|
-
if (text?.includes("Done") || text?.includes("完成") || text?.includes("已完成")) {
|
|
257
|
-
await menuBtns.nth(i).click();
|
|
258
|
-
statusChanged = true;
|
|
259
|
-
break;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
if (!statusChanged) {
|
|
265
|
-
// Fallback: scan all buttons
|
|
266
|
-
const allBtns = page.locator("button");
|
|
267
|
-
const count = await allBtns.count();
|
|
268
|
-
for (let i = 0; i < count; i++) {
|
|
269
|
-
const text = await allBtns.nth(i).textContent();
|
|
270
|
-
if (text?.trim() === "Done" || text?.includes("完成") || text?.includes("已完成")) {
|
|
271
|
-
await allBtns.nth(i).click();
|
|
272
|
-
statusChanged = true;
|
|
273
|
-
break;
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
if (!statusChanged) {
|
|
279
|
-
test.skip();
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
await page.waitForTimeout(500);
|
|
284
|
-
// Verify task is still visible after moving to DONE
|
|
285
|
-
await expect(page.getByText(TASK_TITLE)).toBeVisible({ timeout: 5000 });
|
|
286
|
-
});
|
|
287
|
-
});
|
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
import { test, expect, type Page } from "@playwright/test";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* E2E tests for the Task Development Workbench (v0.6)
|
|
5
|
-
*
|
|
6
|
-
* Prerequisites:
|
|
7
|
-
* - At least one workspace with a project and tasks
|
|
8
|
-
* - Ideally a task that has been executed (worktree exists)
|
|
9
|
-
* - Tests skip gracefully if preconditions are not met
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
// ---------- helpers ----------
|
|
13
|
-
|
|
14
|
-
async function goToWorkspace(page: Page): Promise<boolean> {
|
|
15
|
-
await page.goto("/workspaces");
|
|
16
|
-
const sidebar = page.locator("aside");
|
|
17
|
-
const wsBtn = sidebar.locator("button").filter({ hasText: /测试|Test|E2E/ }).first();
|
|
18
|
-
if (await wsBtn.isVisible({ timeout: 3000 }).catch(() => false)) {
|
|
19
|
-
await wsBtn.click();
|
|
20
|
-
} else {
|
|
21
|
-
const anyWs = sidebar.locator("button").filter({ hasText: /.{2,}/ }).first();
|
|
22
|
-
if (await anyWs.isVisible({ timeout: 3000 }).catch(() => false)) {
|
|
23
|
-
await anyWs.click();
|
|
24
|
-
} else {
|
|
25
|
-
return false;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
await page.waitForURL(/\/workspaces\//, { timeout: 5000 }).catch(() => {});
|
|
29
|
-
await page.waitForTimeout(500);
|
|
30
|
-
return page.url().includes("/workspaces/");
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async function openFirstTaskDrawer(page: Page): Promise<boolean> {
|
|
34
|
-
const card = page.locator("[data-testid='task-card']").first();
|
|
35
|
-
if (!(await card.isVisible({ timeout: 5000 }).catch(() => false))) {
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
await card.click();
|
|
39
|
-
await page.waitForTimeout(500);
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async function navigateToWorkbench(page: Page): Promise<boolean> {
|
|
44
|
-
const hasTask = await openFirstTaskDrawer(page);
|
|
45
|
-
if (!hasTask) return false;
|
|
46
|
-
|
|
47
|
-
const panel = page.locator("[data-testid='task-detail-panel']");
|
|
48
|
-
if (!(await panel.isVisible({ timeout: 3000 }).catch(() => false))) return false;
|
|
49
|
-
|
|
50
|
-
const viewBtn = panel
|
|
51
|
-
.locator("button, a")
|
|
52
|
-
.filter({ hasText: /查看详情|View Details/ })
|
|
53
|
-
.first();
|
|
54
|
-
if (!(await viewBtn.isVisible({ timeout: 3000 }).catch(() => false))) return false;
|
|
55
|
-
|
|
56
|
-
await viewBtn.click();
|
|
57
|
-
await page.waitForURL(/\/tasks\//, { timeout: 10000 }).catch(() => {});
|
|
58
|
-
await page.waitForTimeout(1000);
|
|
59
|
-
return page.url().includes("/tasks/");
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const SKIP_NO_WORKSPACE = "No workspace with projects available";
|
|
63
|
-
const SKIP_NO_TASK = "No task cards found in workspace";
|
|
64
|
-
const SKIP_NO_WORKBENCH = "Could not navigate to workbench";
|
|
65
|
-
const SKIP_NO_WORKTREE = "No worktree available — file tree shows empty state";
|
|
66
|
-
|
|
67
|
-
// =====================================================================
|
|
68
|
-
// Phase 19: Workbench Entry & Layout
|
|
69
|
-
// =====================================================================
|
|
70
|
-
|
|
71
|
-
test.describe.serial("Phase 19 — Workbench Entry & Layout", () => {
|
|
72
|
-
test("19-1. 查看详情按钮跳转到任务工作台 (WB-01)", async ({ page }) => {
|
|
73
|
-
if (!(await goToWorkspace(page))) { test.skip(true, SKIP_NO_WORKSPACE); return; }
|
|
74
|
-
if (!(await openFirstTaskDrawer(page))) { test.skip(true, SKIP_NO_TASK); return; }
|
|
75
|
-
|
|
76
|
-
const panel = page.locator("[data-testid='task-detail-panel']");
|
|
77
|
-
await expect(panel).toBeVisible({ timeout: 3000 });
|
|
78
|
-
|
|
79
|
-
const viewBtn = panel
|
|
80
|
-
.locator("button, a")
|
|
81
|
-
.filter({ hasText: /查看详情|View Details/ })
|
|
82
|
-
.first();
|
|
83
|
-
await expect(viewBtn).toBeVisible({ timeout: 3000 });
|
|
84
|
-
await viewBtn.click();
|
|
85
|
-
|
|
86
|
-
await expect(page).toHaveURL(/\/tasks\//, { timeout: 10000 });
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
test("19-2. 工作台布局:左侧聊天 + 右侧三标签 (WB-02)", async ({ page }) => {
|
|
90
|
-
if (!(await goToWorkspace(page))) { test.skip(true, SKIP_NO_WORKSPACE); return; }
|
|
91
|
-
if (!(await navigateToWorkbench(page))) { test.skip(true, SKIP_NO_WORKBENCH); return; }
|
|
92
|
-
|
|
93
|
-
const chatPanel = page.locator("textarea, input[type='text']").first();
|
|
94
|
-
await expect(chatPanel).toBeVisible({ timeout: 5000 });
|
|
95
|
-
|
|
96
|
-
const filesTab = page.locator("button, [role='tab']").filter({ hasText: /文件|Files/ }).first();
|
|
97
|
-
const changesTab = page.locator("button, [role='tab']").filter({ hasText: /变更|Changes/ }).first();
|
|
98
|
-
|
|
99
|
-
await expect(filesTab).toBeVisible({ timeout: 3000 });
|
|
100
|
-
await expect(changesTab).toBeVisible({ timeout: 3000 });
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
test("19-3. 标签切换不丢失聊天状态 (WB-02)", async ({ page }) => {
|
|
104
|
-
if (!(await goToWorkspace(page))) { test.skip(true, SKIP_NO_WORKSPACE); return; }
|
|
105
|
-
if (!(await navigateToWorkbench(page))) { test.skip(true, SKIP_NO_WORKBENCH); return; }
|
|
106
|
-
|
|
107
|
-
const changesTab = page.locator("button, [role='tab']").filter({ hasText: /变更|Changes/ }).first();
|
|
108
|
-
if (await changesTab.isVisible({ timeout: 3000 }).catch(() => false)) {
|
|
109
|
-
await changesTab.click();
|
|
110
|
-
await page.waitForTimeout(300);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const filesTab = page.locator("button, [role='tab']").filter({ hasText: /文件|Files/ }).first();
|
|
114
|
-
if (await filesTab.isVisible({ timeout: 3000 }).catch(() => false)) {
|
|
115
|
-
await filesTab.click();
|
|
116
|
-
await page.waitForTimeout(300);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const chatArea = page.locator("textarea, input[type='text']").first();
|
|
120
|
-
await expect(chatArea).toBeVisible({ timeout: 3000 });
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
// =====================================================================
|
|
125
|
-
// Phase 20: File Tree Browser
|
|
126
|
-
// =====================================================================
|
|
127
|
-
|
|
128
|
-
test.describe.serial("Phase 20 — File Tree Browser", () => {
|
|
129
|
-
test("20-1. 文件树展示 worktree 目录或空状态 (FT-01)", async ({ page }) => {
|
|
130
|
-
if (!(await goToWorkspace(page))) { test.skip(true, SKIP_NO_WORKSPACE); return; }
|
|
131
|
-
if (!(await navigateToWorkbench(page))) { test.skip(true, SKIP_NO_WORKBENCH); return; }
|
|
132
|
-
|
|
133
|
-
const filesTab = page.locator("button, [role='tab']").filter({ hasText: /文件|Files/ }).first();
|
|
134
|
-
if (await filesTab.isVisible({ timeout: 3000 }).catch(() => false)) {
|
|
135
|
-
await filesTab.click();
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// File tree OR empty state should be visible
|
|
139
|
-
const treeOrEmpty = page
|
|
140
|
-
.locator("div")
|
|
141
|
-
.filter({ hasText: /src|package\.json|文件树暂不可用|File tree unavailable|选择文件|Select a file/ })
|
|
142
|
-
.first();
|
|
143
|
-
await expect(treeOrEmpty).toBeVisible({ timeout: 5000 });
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
test("20-2. 展开文件夹显示子目录 (FT-01)", async ({ page }) => {
|
|
147
|
-
if (!(await goToWorkspace(page))) { test.skip(true, SKIP_NO_WORKSPACE); return; }
|
|
148
|
-
if (!(await navigateToWorkbench(page))) { test.skip(true, SKIP_NO_WORKBENCH); return; }
|
|
149
|
-
|
|
150
|
-
const folder = page.locator("div").filter({ hasText: /^src$/ }).first();
|
|
151
|
-
if (!(await folder.isVisible({ timeout: 3000 }).catch(() => false))) {
|
|
152
|
-
test.skip(true, SKIP_NO_WORKTREE);
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
await folder.click();
|
|
157
|
-
await page.waitForTimeout(500);
|
|
158
|
-
|
|
159
|
-
const children = page.locator("div").filter({ hasText: /\.ts|\.tsx|components|lib|actions/ });
|
|
160
|
-
const childCount = await children.count();
|
|
161
|
-
expect(childCount).toBeGreaterThan(0);
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
test("20-3. 右键菜单显示操作选项 (FT-05)", async ({ page }) => {
|
|
165
|
-
if (!(await goToWorkspace(page))) { test.skip(true, SKIP_NO_WORKSPACE); return; }
|
|
166
|
-
if (!(await navigateToWorkbench(page))) { test.skip(true, SKIP_NO_WORKBENCH); return; }
|
|
167
|
-
|
|
168
|
-
const treeNode = page.locator("div").filter({ hasText: /package\.json|src|README/ }).first();
|
|
169
|
-
if (!(await treeNode.isVisible({ timeout: 3000 }).catch(() => false))) {
|
|
170
|
-
test.skip(true, SKIP_NO_WORKTREE);
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
await treeNode.click({ button: "right" });
|
|
175
|
-
await page.waitForTimeout(300);
|
|
176
|
-
|
|
177
|
-
const menu = page.locator("div").filter({ hasText: /新建文件|New File|重命名|Rename/ }).first();
|
|
178
|
-
await expect(menu).toBeVisible({ timeout: 3000 });
|
|
179
|
-
|
|
180
|
-
await page.mouse.click(0, 0);
|
|
181
|
-
await page.waitForTimeout(300);
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
// =====================================================================
|
|
186
|
-
// Phase 21: Code Editor (Monaco)
|
|
187
|
-
// =====================================================================
|
|
188
|
-
|
|
189
|
-
test.describe.serial("Phase 21 — Code Editor (Monaco)", () => {
|
|
190
|
-
test("21-1. 点击文件打开 Monaco 编辑器 (ED-01)", async ({ page }) => {
|
|
191
|
-
if (!(await goToWorkspace(page))) { test.skip(true, SKIP_NO_WORKSPACE); return; }
|
|
192
|
-
if (!(await navigateToWorkbench(page))) { test.skip(true, SKIP_NO_WORKBENCH); return; }
|
|
193
|
-
|
|
194
|
-
const srcFolder = page.locator("div").filter({ hasText: /^src$/ }).first();
|
|
195
|
-
if (!(await srcFolder.isVisible({ timeout: 3000 }).catch(() => false))) {
|
|
196
|
-
test.skip(true, SKIP_NO_WORKTREE);
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
await srcFolder.click();
|
|
201
|
-
await page.waitForTimeout(500);
|
|
202
|
-
|
|
203
|
-
const tsFile = page.locator("div").filter({ hasText: /\.ts$|\.tsx$/ }).first();
|
|
204
|
-
if (!(await tsFile.isVisible({ timeout: 3000 }).catch(() => false))) {
|
|
205
|
-
test.skip(true, "No TypeScript files visible in file tree");
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
await tsFile.click();
|
|
210
|
-
await page.waitForTimeout(2000);
|
|
211
|
-
|
|
212
|
-
const monacoContainer = page.locator(".monaco-editor, [data-keybinding-context]");
|
|
213
|
-
await expect(monacoContainer.first()).toBeVisible({ timeout: 10000 });
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
test("21-2. 编辑器主题跟随 dark/light 设置 (ED-05)", async ({ page }) => {
|
|
217
|
-
if (!(await goToWorkspace(page))) { test.skip(true, SKIP_NO_WORKSPACE); return; }
|
|
218
|
-
if (!(await navigateToWorkbench(page))) { test.skip(true, SKIP_NO_WORKBENCH); return; }
|
|
219
|
-
|
|
220
|
-
const monacoContainer = page.locator(".monaco-editor").first();
|
|
221
|
-
if (!(await monacoContainer.isVisible({ timeout: 5000 }).catch(() => false))) {
|
|
222
|
-
test.skip(true, "Monaco editor not loaded — skip theme test");
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
const html = page.locator("html");
|
|
227
|
-
const currentTheme = await html.getAttribute("class");
|
|
228
|
-
|
|
229
|
-
if (currentTheme?.includes("dark")) {
|
|
230
|
-
await expect(monacoContainer).toHaveClass(/vs-dark/);
|
|
231
|
-
} else {
|
|
232
|
-
const classes = await monacoContainer.getAttribute("class");
|
|
233
|
-
expect(classes).not.toContain("vs-dark");
|
|
234
|
-
}
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
// =====================================================================
|
|
239
|
-
// Phase 22: Diff View Integration
|
|
240
|
-
// =====================================================================
|
|
241
|
-
|
|
242
|
-
test.describe.serial("Phase 22 — Diff View Integration", () => {
|
|
243
|
-
test("22-1. 变更标签页显示 diff 或空状态 (DF-01)", async ({ page }) => {
|
|
244
|
-
if (!(await goToWorkspace(page))) { test.skip(true, SKIP_NO_WORKSPACE); return; }
|
|
245
|
-
if (!(await navigateToWorkbench(page))) { test.skip(true, SKIP_NO_WORKBENCH); return; }
|
|
246
|
-
|
|
247
|
-
const changesTab = page.locator("button, [role='tab']").filter({ hasText: /变更|Changes/ }).first();
|
|
248
|
-
await expect(changesTab).toBeVisible({ timeout: 3000 });
|
|
249
|
-
await changesTab.click();
|
|
250
|
-
await page.waitForTimeout(1000);
|
|
251
|
-
|
|
252
|
-
const diffOrMessage = page
|
|
253
|
-
.locator("div")
|
|
254
|
-
.filter({ hasText: /\+|\-|暂无变更|No changes|启动执行|Start|加载/ })
|
|
255
|
-
.first();
|
|
256
|
-
await expect(diffOrMessage).toBeVisible({ timeout: 5000 });
|
|
257
|
-
});
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
// =====================================================================
|
|
261
|
-
// Phase 23: Preview Panel
|
|
262
|
-
// =====================================================================
|
|
263
|
-
|
|
264
|
-
test.describe.serial("Phase 23 — Preview Panel", () => {
|
|
265
|
-
test("23-1. 前端项目显示预览标签页 (PV-01)", async ({ page }) => {
|
|
266
|
-
if (!(await goToWorkspace(page))) { test.skip(true, SKIP_NO_WORKSPACE); return; }
|
|
267
|
-
if (!(await navigateToWorkbench(page))) { test.skip(true, SKIP_NO_WORKBENCH); return; }
|
|
268
|
-
|
|
269
|
-
// Preview tab should be visible for FRONTEND projects (default)
|
|
270
|
-
const previewTab = page.locator("button, [role='tab']").filter({ hasText: /预览|Preview/ }).first();
|
|
271
|
-
const isVisible = await previewTab.isVisible({ timeout: 3000 }).catch(() => false);
|
|
272
|
-
expect(typeof isVisible).toBe("boolean");
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
test("23-2. 预览面板有控制区域 (PV-02, PV-03)", async ({ page }) => {
|
|
276
|
-
if (!(await goToWorkspace(page))) { test.skip(true, SKIP_NO_WORKSPACE); return; }
|
|
277
|
-
if (!(await navigateToWorkbench(page))) { test.skip(true, SKIP_NO_WORKBENCH); return; }
|
|
278
|
-
|
|
279
|
-
const previewTab = page.locator("button, [role='tab']").filter({ hasText: /预览|Preview/ }).first();
|
|
280
|
-
if (!(await previewTab.isVisible({ timeout: 3000 }).catch(() => false))) {
|
|
281
|
-
test.skip(true, "Preview tab not visible — project may be BACKEND type");
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
await previewTab.click();
|
|
286
|
-
await page.waitForTimeout(500);
|
|
287
|
-
|
|
288
|
-
const previewArea = page.locator("div").filter({
|
|
289
|
-
hasText: /http|localhost|地址|URL|预览|Preview|启动|Run|运行|停止|Stop/,
|
|
290
|
-
});
|
|
291
|
-
await expect(previewArea.first()).toBeVisible({ timeout: 5000 });
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
test("23-3. 设置页有终端应用配置 (PV-05)", async ({ page }) => {
|
|
295
|
-
await page.goto("/settings");
|
|
296
|
-
await page.waitForTimeout(500);
|
|
297
|
-
|
|
298
|
-
const generalTab = page.locator("button, a").filter({ hasText: /通用|General/ }).first();
|
|
299
|
-
if (await generalTab.isVisible({ timeout: 3000 }).catch(() => false)) {
|
|
300
|
-
await generalTab.click();
|
|
301
|
-
await page.waitForTimeout(500);
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
const terminalLabel = page.locator("label, div").filter({ hasText: /终端|Terminal/ }).first();
|
|
305
|
-
await expect(terminalLabel).toBeVisible({ timeout: 5000 });
|
|
306
|
-
});
|
|
307
|
-
});
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import "@testing-library/jest-dom/vitest";
|
|
2
|
-
|
|
3
|
-
// Polyfill ResizeObserver for jsdom (used by cmdk/Popover components)
|
|
4
|
-
if (typeof globalThis.ResizeObserver === "undefined") {
|
|
5
|
-
globalThis.ResizeObserver = class ResizeObserver {
|
|
6
|
-
observe() {}
|
|
7
|
-
unobserve() {}
|
|
8
|
-
disconnect() {}
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// Polyfill scrollIntoView for jsdom (used by cmdk Command component)
|
|
13
|
-
if (typeof window !== "undefined" && !window.HTMLElement.prototype.scrollIntoView) {
|
|
14
|
-
window.HTMLElement.prototype.scrollIntoView = function () {};
|
|
15
|
-
}
|