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,261 +0,0 @@
|
|
|
1
|
-
import { test, expect } from "@playwright/test";
|
|
2
|
-
|
|
3
|
-
test.describe("Phase 1: Theme + General Settings", () => {
|
|
4
|
-
test("1.1 Settings defaults to General section with correct nav items", async ({
|
|
5
|
-
page,
|
|
6
|
-
}) => {
|
|
7
|
-
await page.goto("/settings");
|
|
8
|
-
const nav = page.locator("nav");
|
|
9
|
-
await expect(nav.getByText("General")).toBeVisible();
|
|
10
|
-
await expect(nav.getByText("AI Tools")).toBeVisible();
|
|
11
|
-
await expect(nav.getByText("Prompts")).toBeVisible();
|
|
12
|
-
// General section should be active (has accent bg)
|
|
13
|
-
const generalBtn = nav.locator("button").filter({ hasText: "General" });
|
|
14
|
-
await expect(generalBtn).toHaveClass(/bg-accent/);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
test("1.2 Theme segmented control renders with Light/Dark/System options", async ({
|
|
18
|
-
page,
|
|
19
|
-
}) => {
|
|
20
|
-
await page.goto("/settings");
|
|
21
|
-
await page.waitForTimeout(500);
|
|
22
|
-
const themeButtons = page
|
|
23
|
-
.locator("button")
|
|
24
|
-
.filter({ hasText: /^(Light|Dark|System|浅色|深色|跟随系统)$/ });
|
|
25
|
-
await expect(themeButtons.first()).toBeVisible();
|
|
26
|
-
const count = await themeButtons.count();
|
|
27
|
-
expect(count).toBeGreaterThanOrEqual(3);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
test("1.3 Clicking Dark theme switches UI to dark mode", async ({
|
|
31
|
-
page,
|
|
32
|
-
}) => {
|
|
33
|
-
await page.goto("/settings");
|
|
34
|
-
await page.waitForTimeout(500);
|
|
35
|
-
const darkBtn = page
|
|
36
|
-
.locator("button")
|
|
37
|
-
.filter({ hasText: /^(Dark|深色)$/ });
|
|
38
|
-
await darkBtn.click();
|
|
39
|
-
await page.waitForTimeout(300);
|
|
40
|
-
const htmlClass = await page.locator("html").getAttribute("class");
|
|
41
|
-
expect(htmlClass).toContain("dark");
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test("1.4 Clicking Light theme switches UI to light mode", async ({
|
|
45
|
-
page,
|
|
46
|
-
}) => {
|
|
47
|
-
await page.goto("/settings");
|
|
48
|
-
await page.waitForTimeout(500);
|
|
49
|
-
const darkBtn = page
|
|
50
|
-
.locator("button")
|
|
51
|
-
.filter({ hasText: /^(Dark|深色)$/ });
|
|
52
|
-
await darkBtn.click();
|
|
53
|
-
await page.waitForTimeout(300);
|
|
54
|
-
const lightBtn = page
|
|
55
|
-
.locator("button")
|
|
56
|
-
.filter({ hasText: /^(Light|浅色)$/ });
|
|
57
|
-
await lightBtn.click();
|
|
58
|
-
await page.waitForTimeout(300);
|
|
59
|
-
const htmlClass = await page.locator("html").getAttribute("class");
|
|
60
|
-
expect(htmlClass).not.toContain("dark");
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
test("1.5 Theme persists after page reload", async ({ page }) => {
|
|
64
|
-
await page.goto("/settings");
|
|
65
|
-
await page.waitForTimeout(500);
|
|
66
|
-
const darkBtn = page
|
|
67
|
-
.locator("button")
|
|
68
|
-
.filter({ hasText: /^(Dark|深色)$/ });
|
|
69
|
-
await darkBtn.click();
|
|
70
|
-
await page.waitForTimeout(300);
|
|
71
|
-
await page.reload();
|
|
72
|
-
await page.waitForTimeout(500);
|
|
73
|
-
const htmlClass = await page.locator("html").getAttribute("class");
|
|
74
|
-
expect(htmlClass).toContain("dark");
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
test("1.6 Language toggle switches between Chinese and English", async ({
|
|
78
|
-
page,
|
|
79
|
-
}) => {
|
|
80
|
-
await page.goto("/settings");
|
|
81
|
-
await page.waitForTimeout(500);
|
|
82
|
-
// Click English button
|
|
83
|
-
const enBtn = page.locator("button").filter({ hasText: "English" });
|
|
84
|
-
await enBtn.click();
|
|
85
|
-
await page.waitForTimeout(300);
|
|
86
|
-
// Use heading role to avoid strict mode violation
|
|
87
|
-
await expect(page.getByRole("heading", { name: "Theme" })).toBeVisible();
|
|
88
|
-
// Switch to Chinese
|
|
89
|
-
const zhBtn = page.locator("button").filter({ hasText: "中文" });
|
|
90
|
-
await zhBtn.click();
|
|
91
|
-
await page.waitForTimeout(300);
|
|
92
|
-
await expect(page.getByRole("heading", { name: "主题" })).toBeVisible();
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
test.describe("Phase 2: CLI Adapter Verification", () => {
|
|
97
|
-
test("2.1 AI Tools shows adapter card with test button and default badge", async ({
|
|
98
|
-
page,
|
|
99
|
-
}) => {
|
|
100
|
-
await page.goto("/settings");
|
|
101
|
-
const nav = page.locator("nav");
|
|
102
|
-
await nav.getByText("AI Tools").click();
|
|
103
|
-
await page.waitForTimeout(500);
|
|
104
|
-
// Claude Code adapter should be visible
|
|
105
|
-
await expect(page.getByText("Claude Code")).toBeVisible();
|
|
106
|
-
// Test Connection button should be visible
|
|
107
|
-
const testBtn = page
|
|
108
|
-
.locator("button")
|
|
109
|
-
.filter({ hasText: /测试连接|Test Connection/ });
|
|
110
|
-
await expect(testBtn).toBeVisible();
|
|
111
|
-
// Default badge should be visible (Claude Code is default)
|
|
112
|
-
await expect(page.locator("text=/默认|Default/i")).toBeVisible();
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
test("2.2 Test Connection button works and shows results", async ({
|
|
116
|
-
page,
|
|
117
|
-
}) => {
|
|
118
|
-
test.setTimeout(60000); // CLI test can take a while
|
|
119
|
-
await page.goto("/settings");
|
|
120
|
-
const nav = page.locator("nav");
|
|
121
|
-
await nav.getByText("AI Tools").click();
|
|
122
|
-
await page.waitForTimeout(500);
|
|
123
|
-
// Click test connection
|
|
124
|
-
const testBtn = page
|
|
125
|
-
.locator("button")
|
|
126
|
-
.filter({ hasText: /测试连接|Test Connection/ });
|
|
127
|
-
await testBtn.click();
|
|
128
|
-
// Wait for results — look for pass/fail icons (CheckCircle2 or XCircle)
|
|
129
|
-
await expect(
|
|
130
|
-
page.locator("text=/检测通过|部分检测未通过|All checks passed|Some checks failed/")
|
|
131
|
-
).toBeVisible({ timeout: 50000 });
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
test("2.3 Button disabled during test (no double-trigger)", async ({
|
|
135
|
-
page,
|
|
136
|
-
}) => {
|
|
137
|
-
await page.goto("/settings");
|
|
138
|
-
const nav = page.locator("nav");
|
|
139
|
-
await nav.getByText("AI Tools").click();
|
|
140
|
-
await page.waitForTimeout(500);
|
|
141
|
-
const testBtn = page
|
|
142
|
-
.locator("button")
|
|
143
|
-
.filter({ hasText: /测试连接|Test Connection/ });
|
|
144
|
-
await testBtn.click();
|
|
145
|
-
const loadingBtn = page
|
|
146
|
-
.locator("button")
|
|
147
|
-
.filter({ hasText: /测试中|Testing/ });
|
|
148
|
-
await expect(loadingBtn).toBeDisabled({ timeout: 2000 });
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
test.describe.serial("Phase 3: Agent Prompt Management", () => {
|
|
153
|
-
test("3.1 Prompts section shows create button", async ({ page }) => {
|
|
154
|
-
await page.goto("/settings");
|
|
155
|
-
const nav = page.locator("nav");
|
|
156
|
-
await nav.getByText("Prompts").click();
|
|
157
|
-
await page.waitForTimeout(500);
|
|
158
|
-
await expect(page.locator("h2")).toBeVisible();
|
|
159
|
-
// Use specific button text for prompts
|
|
160
|
-
await expect(
|
|
161
|
-
page.getByRole("button", { name: /新建提示词|New Prompt/ })
|
|
162
|
-
).toBeVisible();
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
test("3.2 Create new prompt via dialog", async ({ page }) => {
|
|
166
|
-
await page.goto("/settings");
|
|
167
|
-
const nav = page.locator("nav");
|
|
168
|
-
await nav.getByText("Prompts").click();
|
|
169
|
-
await page.waitForTimeout(500);
|
|
170
|
-
// Click create button using specific text
|
|
171
|
-
await page.getByRole("button", { name: /新建提示词|New Prompt/ }).click();
|
|
172
|
-
const dialog = page.getByRole("dialog");
|
|
173
|
-
await expect(dialog).toBeVisible({ timeout: 3000 });
|
|
174
|
-
// Fill form
|
|
175
|
-
await dialog.locator("#prompt-name").fill("E2E Test Prompt");
|
|
176
|
-
await dialog.locator("#prompt-description").fill("Test description");
|
|
177
|
-
await dialog
|
|
178
|
-
.locator("#prompt-content")
|
|
179
|
-
.fill("You are a helpful assistant.");
|
|
180
|
-
// Click save
|
|
181
|
-
const saveBtn = dialog
|
|
182
|
-
.locator("button")
|
|
183
|
-
.filter({ hasText: /保存|Save/ });
|
|
184
|
-
await saveBtn.click();
|
|
185
|
-
await expect(dialog).not.toBeVisible({ timeout: 5000 });
|
|
186
|
-
await expect(page.getByText("E2E Test Prompt")).toBeVisible({
|
|
187
|
-
timeout: 5000,
|
|
188
|
-
});
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
test("3.3 Edit existing prompt", async ({ page }) => {
|
|
192
|
-
await page.goto("/settings");
|
|
193
|
-
const nav = page.locator("nav");
|
|
194
|
-
await nav.getByText("Prompts").click();
|
|
195
|
-
await page.waitForTimeout(1000);
|
|
196
|
-
// Find the prompt card and its edit button (Edit icon)
|
|
197
|
-
const promptText = page.getByText("E2E Test Prompt");
|
|
198
|
-
await expect(promptText).toBeVisible({ timeout: 5000 });
|
|
199
|
-
// The card structure: CardContent > div(flex) > div(text) + div(buttons)
|
|
200
|
-
// Edit button has Edit (pencil) icon - it's the second action button
|
|
201
|
-
const card = promptText.locator("xpath=ancestor::div[contains(@class, 'p-4')]");
|
|
202
|
-
const buttons = card.locator("button");
|
|
203
|
-
// Buttons order: Star, Edit, Delete
|
|
204
|
-
await buttons.nth(1).click();
|
|
205
|
-
const dialog = page.getByRole("dialog");
|
|
206
|
-
await expect(dialog).toBeVisible({ timeout: 3000 });
|
|
207
|
-
const nameInput = dialog.locator("#prompt-name");
|
|
208
|
-
await expect(nameInput).toHaveValue("E2E Test Prompt");
|
|
209
|
-
await nameInput.clear();
|
|
210
|
-
await nameInput.fill("E2E Updated Prompt");
|
|
211
|
-
const saveBtn = dialog
|
|
212
|
-
.locator("button")
|
|
213
|
-
.filter({ hasText: /保存|Save/ });
|
|
214
|
-
await saveBtn.click();
|
|
215
|
-
await expect(dialog).not.toBeVisible({ timeout: 5000 });
|
|
216
|
-
await expect(page.getByText("E2E Updated Prompt")).toBeVisible({
|
|
217
|
-
timeout: 5000,
|
|
218
|
-
});
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
test("3.4 Set prompt as default", async ({ page }) => {
|
|
222
|
-
await page.goto("/settings");
|
|
223
|
-
const nav = page.locator("nav");
|
|
224
|
-
await nav.getByText("Prompts").click();
|
|
225
|
-
await page.waitForTimeout(1000);
|
|
226
|
-
const promptText = page.getByText("E2E Updated Prompt");
|
|
227
|
-
await expect(promptText).toBeVisible({ timeout: 5000 });
|
|
228
|
-
const card = promptText.locator("xpath=ancestor::div[contains(@class, 'p-4')]");
|
|
229
|
-
const buttons = card.locator("button");
|
|
230
|
-
// Star button is first
|
|
231
|
-
await buttons.first().click();
|
|
232
|
-
await page.waitForTimeout(1000);
|
|
233
|
-
// Default badge should appear
|
|
234
|
-
await expect(
|
|
235
|
-
card.locator("text=/默认|Default/i")
|
|
236
|
-
).toBeVisible({ timeout: 5000 });
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
test("3.5 Delete prompt with confirmation", async ({ page }) => {
|
|
240
|
-
await page.goto("/settings");
|
|
241
|
-
const nav = page.locator("nav");
|
|
242
|
-
await nav.getByText("Prompts").click();
|
|
243
|
-
await page.waitForTimeout(1000);
|
|
244
|
-
const promptText = page.getByText("E2E Updated Prompt");
|
|
245
|
-
await expect(promptText).toBeVisible({ timeout: 5000 });
|
|
246
|
-
const card = promptText.locator("xpath=ancestor::div[contains(@class, 'p-4')]");
|
|
247
|
-
const buttons = card.locator("button");
|
|
248
|
-
// Delete button is last
|
|
249
|
-
await buttons.last().click();
|
|
250
|
-
// Confirmation dialog
|
|
251
|
-
const dialog = page.getByRole("dialog");
|
|
252
|
-
await expect(dialog).toBeVisible({ timeout: 3000 });
|
|
253
|
-
// Click the destructive delete button in the dialog
|
|
254
|
-
const deleteBtn = dialog.locator("button").filter({ hasText: /删除|Delete/ });
|
|
255
|
-
await deleteBtn.click();
|
|
256
|
-
await expect(dialog).not.toBeVisible({ timeout: 5000 });
|
|
257
|
-
await expect(page.getByText("E2E Updated Prompt")).not.toBeVisible({
|
|
258
|
-
timeout: 5000,
|
|
259
|
-
});
|
|
260
|
-
});
|
|
261
|
-
});
|
|
@@ -1,317 +0,0 @@
|
|
|
1
|
-
import { test, expect } from "@playwright/test";
|
|
2
|
-
|
|
3
|
-
test.describe.serial("Tower 可用性测试", () => {
|
|
4
|
-
|
|
5
|
-
// 1. 首页加载
|
|
6
|
-
test("1. 首页加载,侧边栏显示", async ({ page }) => {
|
|
7
|
-
await page.goto("/");
|
|
8
|
-
await page.waitForURL(/\/workspaces/);
|
|
9
|
-
await expect(page.locator("aside")).toBeVisible();
|
|
10
|
-
await expect(page.getByText("Tower", { exact: true })).toBeVisible();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
// 2. 新建工作空间(通过 Dialog)
|
|
14
|
-
test("2. 新建工作空间", async ({ page }) => {
|
|
15
|
-
await page.goto("/workspaces");
|
|
16
|
-
const sidebar = page.locator("aside");
|
|
17
|
-
// Click the "+" button — find it by Plus icon button in sidebar
|
|
18
|
-
const plusBtn = sidebar.locator("button").filter({ has: page.locator("svg") });
|
|
19
|
-
// The Plus button for creating workspace
|
|
20
|
-
for (let i = 0; i < await plusBtn.count(); i++) {
|
|
21
|
-
const btn = plusBtn.nth(i);
|
|
22
|
-
const title = await btn.getAttribute("title");
|
|
23
|
-
if (title && title.includes("工作空间")) {
|
|
24
|
-
await btn.click();
|
|
25
|
-
break;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
// If no title match, try clicking the Plus icon near workspace section
|
|
29
|
-
const dialog = page.getByRole("dialog");
|
|
30
|
-
if (!await dialog.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
31
|
-
// Fallback: click any Plus button in sidebar
|
|
32
|
-
await sidebar.locator("svg.lucide-plus").first().click({ force: true });
|
|
33
|
-
}
|
|
34
|
-
await expect(dialog).toBeVisible({ timeout: 3000 });
|
|
35
|
-
await dialog.locator("input").first().fill("E2E测试空间");
|
|
36
|
-
// Click the emoji grid first item if visible
|
|
37
|
-
const emojiBtn = dialog.locator("button").filter({ hasText: "🚀" });
|
|
38
|
-
if (await emojiBtn.isVisible().catch(() => false)) {
|
|
39
|
-
await emojiBtn.click();
|
|
40
|
-
}
|
|
41
|
-
// Click create button
|
|
42
|
-
const createBtns = dialog.locator("button");
|
|
43
|
-
for (let i = 0; i < await createBtns.count(); i++) {
|
|
44
|
-
const text = await createBtns.nth(i).textContent();
|
|
45
|
-
if (text?.includes("创建") || text?.includes("\u521b\u5efa")) {
|
|
46
|
-
await createBtns.nth(i).click();
|
|
47
|
-
break;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
await expect(dialog).not.toBeVisible({ timeout: 5000 });
|
|
51
|
-
await expect(page).toHaveURL(/\/workspaces\//);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
// 3. 点击工作空间导航
|
|
55
|
-
test("3. 点击工作空间导航到看板", async ({ page }) => {
|
|
56
|
-
await page.goto("/workspaces");
|
|
57
|
-
const sidebar = page.locator("aside");
|
|
58
|
-
const wsBtn = sidebar.locator("button").filter({ hasText: /测试|Test/ }).first();
|
|
59
|
-
if (await wsBtn.isVisible({ timeout: 3000 }).catch(() => false)) {
|
|
60
|
-
await wsBtn.click();
|
|
61
|
-
await expect(page).toHaveURL(/\/workspaces\//);
|
|
62
|
-
} else {
|
|
63
|
-
test.skip();
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
// 4. 新建项目
|
|
68
|
-
test("4. 通过顶栏新建项目", async ({ page }) => {
|
|
69
|
-
await page.goto("/workspaces");
|
|
70
|
-
const sidebar = page.locator("aside");
|
|
71
|
-
const wsBtn = sidebar.locator("button").filter({ hasText: "E2E" }).first();
|
|
72
|
-
if (await wsBtn.isVisible({ timeout: 3000 }).catch(() => false)) {
|
|
73
|
-
await wsBtn.click();
|
|
74
|
-
await page.waitForURL(/\/workspaces\//);
|
|
75
|
-
await page.waitForTimeout(500);
|
|
76
|
-
}
|
|
77
|
-
// Find and click new project button
|
|
78
|
-
const headerBtns = page.locator("header button, header a");
|
|
79
|
-
for (let i = 0; i < await headerBtns.count(); i++) {
|
|
80
|
-
const text = await headerBtns.nth(i).textContent();
|
|
81
|
-
if (text?.includes("新建项目") || text?.includes("\u65b0\u5efa\u9879\u76ee")) {
|
|
82
|
-
await headerBtns.nth(i).click();
|
|
83
|
-
break;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
const dialog = page.getByRole("dialog");
|
|
87
|
-
await expect(dialog).toBeVisible({ timeout: 3000 });
|
|
88
|
-
await dialog.locator("input").first().fill("E2E测试项目");
|
|
89
|
-
// Click the submit button — it's the last button in the dialog footer
|
|
90
|
-
await dialog.locator("button").last().click();
|
|
91
|
-
await page.waitForTimeout(3000);
|
|
92
|
-
// Dialog should close or page should navigate
|
|
93
|
-
const stillOpen = await dialog.isVisible().catch(() => false);
|
|
94
|
-
if (stillOpen) {
|
|
95
|
-
// Try pressing Enter as fallback
|
|
96
|
-
await dialog.locator("input").first().press("Enter");
|
|
97
|
-
await page.waitForTimeout(3000);
|
|
98
|
-
}
|
|
99
|
-
// Verify project was created by checking DB indirectly (page refreshed)
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
// 5. 新建任务
|
|
103
|
-
test("5. 新建任务", async ({ page }) => {
|
|
104
|
-
await page.goto("/workspaces");
|
|
105
|
-
const sidebar = page.locator("aside");
|
|
106
|
-
const wsBtn = sidebar.locator("button").filter({ hasText: /测试|Test/ }).first();
|
|
107
|
-
if (!await wsBtn.isVisible({ timeout: 3000 }).catch(() => false)) { test.skip(); return; }
|
|
108
|
-
await wsBtn.click();
|
|
109
|
-
await page.waitForURL(/\/workspaces\//);
|
|
110
|
-
await page.waitForTimeout(1000);
|
|
111
|
-
|
|
112
|
-
// Find new task button
|
|
113
|
-
const allBtns = page.locator("button");
|
|
114
|
-
let clicked = false;
|
|
115
|
-
for (let i = 0; i < await allBtns.count(); i++) {
|
|
116
|
-
const text = await allBtns.nth(i).textContent();
|
|
117
|
-
if (text?.includes("新建任务") || text?.includes("\u65b0\u5efa\u4efb\u52a1")) {
|
|
118
|
-
await allBtns.nth(i).click();
|
|
119
|
-
clicked = true;
|
|
120
|
-
break;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
if (!clicked) { test.skip(); return; }
|
|
124
|
-
|
|
125
|
-
const dialog = page.getByRole("dialog");
|
|
126
|
-
await expect(dialog).toBeVisible({ timeout: 3000 });
|
|
127
|
-
await dialog.locator("input").first().fill("E2E新建任务");
|
|
128
|
-
await dialog.locator("textarea").fill("自动化测试创建");
|
|
129
|
-
|
|
130
|
-
// Click create button
|
|
131
|
-
const createBtns = dialog.locator("button");
|
|
132
|
-
for (let i = 0; i < await createBtns.count(); i++) {
|
|
133
|
-
const text = await createBtns.nth(i).textContent();
|
|
134
|
-
if (text?.includes("创建") || text?.includes("\u521b\u5efa")) {
|
|
135
|
-
await createBtns.nth(i).click();
|
|
136
|
-
break;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
await expect(dialog).not.toBeVisible({ timeout: 5000 });
|
|
140
|
-
await expect(page.getByText("E2E新建任务")).toBeVisible({ timeout: 5000 });
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
// 6. 点击任务打开详情面板
|
|
144
|
-
test("6. 点击任务卡片打开详情面板", async ({ page }) => {
|
|
145
|
-
await page.goto("/workspaces");
|
|
146
|
-
const sidebar = page.locator("aside");
|
|
147
|
-
const wsBtn = sidebar.locator("button").filter({ hasText: /测试|Test/ }).first();
|
|
148
|
-
if (!await wsBtn.isVisible({ timeout: 3000 }).catch(() => false)) { test.skip(); return; }
|
|
149
|
-
await wsBtn.click();
|
|
150
|
-
await page.waitForURL(/\/workspaces\//);
|
|
151
|
-
await page.waitForTimeout(1000);
|
|
152
|
-
|
|
153
|
-
const taskCard = page.locator("[data-testid='task-card']").first();
|
|
154
|
-
if (!await taskCard.isVisible({ timeout: 3000 }).catch(() => false)) { test.skip(); return; }
|
|
155
|
-
await taskCard.click();
|
|
156
|
-
|
|
157
|
-
const panel = page.locator("[data-testid='task-detail-panel']");
|
|
158
|
-
await expect(panel).toBeVisible({ timeout: 3000 });
|
|
159
|
-
// Close panel
|
|
160
|
-
const backBtn = panel.locator("button").filter({ has: page.locator("svg.lucide-arrow-left") });
|
|
161
|
-
if (await backBtn.isVisible().catch(() => false)) {
|
|
162
|
-
await backBtn.click();
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
// 7. 发送消息
|
|
167
|
-
test("7. 在任务详情面板发送消息", async ({ page }) => {
|
|
168
|
-
await page.goto("/workspaces");
|
|
169
|
-
const sidebar = page.locator("aside");
|
|
170
|
-
const wsBtn = sidebar.locator("button").filter({ hasText: /测试|Test/ }).first();
|
|
171
|
-
if (!await wsBtn.isVisible({ timeout: 3000 }).catch(() => false)) { test.skip(); return; }
|
|
172
|
-
await wsBtn.click();
|
|
173
|
-
await page.waitForURL(/\/workspaces\//);
|
|
174
|
-
await page.waitForTimeout(1000);
|
|
175
|
-
|
|
176
|
-
const taskCard = page.locator("[data-testid='task-card']").first();
|
|
177
|
-
if (!await taskCard.isVisible({ timeout: 3000 }).catch(() => false)) { test.skip(); return; }
|
|
178
|
-
await taskCard.click();
|
|
179
|
-
|
|
180
|
-
const panel = page.locator("[data-testid='task-detail-panel']");
|
|
181
|
-
await expect(panel).toBeVisible({ timeout: 3000 });
|
|
182
|
-
|
|
183
|
-
await panel.locator("textarea").fill("E2E测试消息");
|
|
184
|
-
// Find send button
|
|
185
|
-
const panelBtns = panel.locator("button");
|
|
186
|
-
for (let i = 0; i < await panelBtns.count(); i++) {
|
|
187
|
-
const text = await panelBtns.nth(i).textContent();
|
|
188
|
-
if (text?.includes("发送") || text?.includes("\u53d1\u9001")) {
|
|
189
|
-
await panelBtns.nth(i).click();
|
|
190
|
-
break;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
await expect(panel.getByText("E2E测试消息")).toBeVisible({ timeout: 5000 });
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
// 8. 编辑任务
|
|
197
|
-
test("8. 编辑任务标题", async ({ page }) => {
|
|
198
|
-
await page.goto("/workspaces");
|
|
199
|
-
const sidebar = page.locator("aside");
|
|
200
|
-
const wsBtn = sidebar.locator("button").filter({ hasText: /测试|Test/ }).first();
|
|
201
|
-
if (!await wsBtn.isVisible({ timeout: 3000 }).catch(() => false)) { test.skip(); return; }
|
|
202
|
-
await wsBtn.click();
|
|
203
|
-
await page.waitForURL(/\/workspaces\//);
|
|
204
|
-
await page.waitForTimeout(1000);
|
|
205
|
-
|
|
206
|
-
const taskCard = page.locator("[data-testid='task-card']").first();
|
|
207
|
-
if (!await taskCard.isVisible({ timeout: 3000 }).catch(() => false)) { test.skip(); return; }
|
|
208
|
-
|
|
209
|
-
await taskCard.hover();
|
|
210
|
-
const menuBtn = taskCard.locator("button").first();
|
|
211
|
-
await menuBtn.click({ force: true });
|
|
212
|
-
await page.waitForTimeout(300);
|
|
213
|
-
|
|
214
|
-
// Find edit option
|
|
215
|
-
const menuItems = page.locator("[role='menuitem'], [data-slot='menu-item']");
|
|
216
|
-
for (let i = 0; i < await menuItems.count(); i++) {
|
|
217
|
-
const text = await menuItems.nth(i).textContent();
|
|
218
|
-
if (text?.includes("编辑") || text?.includes("\u7f16\u8f91")) {
|
|
219
|
-
await menuItems.nth(i).click();
|
|
220
|
-
break;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const dialog = page.getByRole("dialog");
|
|
225
|
-
if (!await dialog.isVisible({ timeout: 3000 }).catch(() => false)) { test.skip(); return; }
|
|
226
|
-
|
|
227
|
-
const titleInput = dialog.locator("input").first();
|
|
228
|
-
const val = await titleInput.inputValue();
|
|
229
|
-
expect(val.length).toBeGreaterThan(0);
|
|
230
|
-
|
|
231
|
-
await titleInput.clear();
|
|
232
|
-
await titleInput.fill("已编辑的任务");
|
|
233
|
-
// Find save button
|
|
234
|
-
const dlgBtns = dialog.locator("button");
|
|
235
|
-
for (let i = 0; i < await dlgBtns.count(); i++) {
|
|
236
|
-
const text = await dlgBtns.nth(i).textContent();
|
|
237
|
-
if (text?.includes("保存") || text?.includes("\u4fdd\u5b58")) {
|
|
238
|
-
await dlgBtns.nth(i).click();
|
|
239
|
-
break;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
await expect(dialog).not.toBeVisible({ timeout: 5000 });
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
// 9. 搜索 (Cmd+K dialog)
|
|
246
|
-
test("9. 搜索任务", async ({ page }) => {
|
|
247
|
-
await page.goto("/workspaces");
|
|
248
|
-
await page.waitForTimeout(500);
|
|
249
|
-
// Open search dialog via Cmd+K
|
|
250
|
-
await page.keyboard.press("Meta+k");
|
|
251
|
-
const dialog = page.getByRole("dialog");
|
|
252
|
-
await expect(dialog).toBeVisible({ timeout: 3000 });
|
|
253
|
-
// Type in search
|
|
254
|
-
await dialog.locator("input").fill("测试");
|
|
255
|
-
await page.waitForTimeout(500);
|
|
256
|
-
// Close dialog
|
|
257
|
-
await page.keyboard.press("Escape");
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
// 10. 筛选
|
|
261
|
-
test("10. 筛选任务", async ({ page }) => {
|
|
262
|
-
await page.goto("/workspaces");
|
|
263
|
-
const sidebar = page.locator("aside");
|
|
264
|
-
const wsBtn = sidebar.locator("button").filter({ hasText: /测试|Test/ }).first();
|
|
265
|
-
if (!await wsBtn.isVisible({ timeout: 3000 }).catch(() => false)) { test.skip(); return; }
|
|
266
|
-
await wsBtn.click();
|
|
267
|
-
await page.waitForURL(/\/workspaces\//);
|
|
268
|
-
await page.waitForTimeout(1000);
|
|
269
|
-
|
|
270
|
-
// Find filter buttons by looking for amber class pattern
|
|
271
|
-
const filterBtns = page.locator("button").filter({ hasText: /执行中|\u6267\u884c\u4e2d/ });
|
|
272
|
-
if (!await filterBtns.first().isVisible({ timeout: 3000 }).catch(() => false)) { test.skip(); return; }
|
|
273
|
-
await filterBtns.first().click();
|
|
274
|
-
await expect(filterBtns.first()).toHaveClass(/amber/);
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
// 11. 设置页
|
|
278
|
-
test("11. 打开设置页", async ({ page }) => {
|
|
279
|
-
await page.goto("/settings");
|
|
280
|
-
await page.waitForTimeout(1000);
|
|
281
|
-
// Just verify page loaded without errors
|
|
282
|
-
const heading = page.locator("h1, h2").first();
|
|
283
|
-
await expect(heading).toBeVisible({ timeout: 5000 });
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
// 12. 删除任务
|
|
287
|
-
test("12. 删除任务", async ({ page }) => {
|
|
288
|
-
await page.goto("/workspaces");
|
|
289
|
-
const sidebar = page.locator("aside");
|
|
290
|
-
const wsBtn = sidebar.locator("button").filter({ hasText: /测试|Test/ }).first();
|
|
291
|
-
if (!await wsBtn.isVisible({ timeout: 3000 }).catch(() => false)) { test.skip(); return; }
|
|
292
|
-
await wsBtn.click();
|
|
293
|
-
await page.waitForURL(/\/workspaces\//);
|
|
294
|
-
await page.waitForTimeout(1000);
|
|
295
|
-
|
|
296
|
-
const countBefore = await page.locator("[data-testid='task-card']").count();
|
|
297
|
-
if (countBefore === 0) { test.skip(); return; }
|
|
298
|
-
|
|
299
|
-
const firstCard = page.locator("[data-testid='task-card']").first();
|
|
300
|
-
await firstCard.hover();
|
|
301
|
-
const menuBtn = firstCard.locator("button").first();
|
|
302
|
-
await menuBtn.click({ force: true });
|
|
303
|
-
await page.waitForTimeout(300);
|
|
304
|
-
|
|
305
|
-
const menuItems = page.locator("[role='menuitem'], [data-slot='menu-item']");
|
|
306
|
-
for (let i = 0; i < await menuItems.count(); i++) {
|
|
307
|
-
const text = await menuItems.nth(i).textContent();
|
|
308
|
-
if (text?.includes("删除") || text?.includes("\u5220\u9664")) {
|
|
309
|
-
await menuItems.nth(i).click();
|
|
310
|
-
break;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
await page.waitForTimeout(2000);
|
|
314
|
-
const countAfter = await page.locator("[data-testid='task-card']").count();
|
|
315
|
-
expect(countAfter).toBeLessThan(countBefore);
|
|
316
|
-
});
|
|
317
|
-
});
|