{"_id":"@dsh-xhl/workspace-groups","_rev":"9-6ee545ef4b64e3169318b5cd04a6fc42","name":"@dsh-xhl/workspace-groups","dist-tags":{"latest":"0.4.2"},"versions":{"0.1.0":{"name":"@dsh-xhl/workspace-groups","version":"0.1.0","keywords":["dsh","deepseek-harness","deepseek-harness-plugin","dsh-plugin","plugin","sidebar","workspace","workspace-groups","client-plugin"],"license":"MIT","_id":"@dsh-xhl/workspace-groups@0.1.0","maintainers":[{"name":"wojiaoxiaomayun","email":"1146897508@qq.com"}],"homepage":"https://github.com/z-col/dsh-workspace-groups#readme","bugs":{"url":"https://github.com/z-col/dsh-workspace-groups/issues"},"dsh":{"bundle":{"patch":"./cordis.patch.yml"},"client":{"inject":["@deepseek-ai/dsh-api-remotes","@deepseek-ai/dsh-api-session-controller","@deepseek-ai/dsh-api-workspace-controller","@deepseek-ai/dsh-client-connection","@deepseek-ai/dsh-client-locale","@deepseek-ai/dsh-client-ui-renderer","@deepseek-ai/dsh-client-ui-session","@deepseek-ai/dsh-client-ui-sidebar"],"platform":"web"}},"dist":{"shasum":"1d24a6d88e50ea9f7e13fb958830b949582d0762","tarball":"https://registry.npmjs.org/@dsh-xhl/workspace-groups/-/workspace-groups-0.1.0.tgz","fileCount":27,"integrity":"sha512-9OwjoRfEvDoFnlki8SeSdh12TPmMSO6K96izwhZ9zz7/Lu7Dqf7PEQhwf3Ptf+TEKXFn61z7uRLAEXvGzFRFtA==","signatures":[{"sig":"MEQCIF93mTwTcDpL5iHSmQx7EmTDRCANideUeZW15b8h7csLAiAur381wbAv9Ml15YS1t4vgpjZ52DQDOIeazUkSUfwVDg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":613291},"main":"lib/index.js","type":"module","types":"lib/types/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./lib/types/index.d.ts","default":"./lib/index.js"},"./client":{"types":"./lib/types/client/index.d.ts","default":"./lib/client.js"},"./package.json":"./package.json","./cordis.patch.yml":"./cordis.patch.yml"},"gitHead":"c5e4aeaf7a57dca52722081c3c7ab0e4dbe34c92","scripts":{"test":"vitest run","build":"node -e \"require('node:fs').rmSync('lib', { recursive: true, force: true })\" && pnpm build:types && tsdown","watch":"tsdown --watch","verify":"pnpm typecheck && pnpm test","typecheck":"tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit","build:types":"tsc -p tsconfig.build.json --noEmit false --declaration --emitDeclarationOnly --outDir lib/types"},"_npmUser":{"name":"wojiaoxiaomayun","email":"1146897508@qq.com"},"repository":{"url":"git+https://github.com/z-col/dsh-workspace-groups.git","type":"git"},"_npmVersion":"12.0.2","description":"Complete workspace grouping manager for the DSH web sidebar: 分类 → 项目 → 会话 three-level tree, manual group create/rename/delete, drag-and-drop grouping & ordering with insertion indicator, rule-based auto-classification, tree search. Sidecar YAML + runtime ","directories":{},"_nodeVersion":"24.19.0","dependencies":{"js-yaml":"^4.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^30.0.1","react":"^18.2.0","tsdown":"^0.22.2","vitest":"^4.1.8","js-yaml":"^4.1.0","react-dom":"^18.2.0","typescript":"^5.6.0","@types/node":"^24.0.0","@types/react":"~18.3.1","lightningcss":"^1.32.0","@types/js-yaml":"^4.0.9","@types/react-dom":"~18.3.0","@deepseek-ai/cordis":"^4.0.2","@deepseek-ai/dsh-session":"^0.1.2-rc.1","@deepseek-ai/dsh-api-remotes":"^0.1.2-rc.1","@deepseek-ai/dsh-client-store":"^0.1.2-rc.1","@deepseek-ai/dsh-client-locale":"^0.1.2-rc.1","@deepseek-ai/dsh-host-webserver":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-slots":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-session":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-sidebar":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-renderer":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-primitives":"^0.1.2-rc.1","@deepseek-ai/dsh-api-session-controller":"^0.1.2-rc.1","@deepseek-ai/dsh-api-workspace-controller":"^0.1.2-rc.1"},"peerDependencies":{"react":"^18.2.0","react-dom":"^18.2.0","@deepseek-ai/cordis":"^4.0.2","@deepseek-ai/dsh-session":"^0.1.2-rc.1","@deepseek-ai/dsh-api-remotes":"^0.1.2-rc.1","@deepseek-ai/dsh-client-store":"^0.1.2-rc.1","@deepseek-ai/dsh-client-locale":"^0.1.2-rc.1","@deepseek-ai/dsh-host-webserver":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-slots":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-session":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-sidebar":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-primitives":"^0.1.2-rc.1","@deepseek-ai/dsh-api-session-controller":"^0.1.2-rc.1","@deepseek-ai/dsh-api-workspace-controller":"^0.1.2-rc.1"},"peerDependenciesMeta":{"react-dom":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/workspace-groups_0.1.0_1788632803826_0.45849682828546734","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@dsh-xhl/workspace-groups","version":"0.1.1","keywords":["dsh","deepseek-harness","deepseek-harness-plugin","dsh-plugin","plugin","sidebar","workspace","workspace-groups","client-plugin"],"license":"MIT","_id":"@dsh-xhl/workspace-groups@0.1.1","maintainers":[{"name":"wojiaoxiaomayun","email":"1146897508@qq.com"}],"homepage":"https://github.com/z-col/dsh-workspace-groups#readme","bugs":{"url":"https://github.com/z-col/dsh-workspace-groups/issues"},"dsh":{"bundle":{"patch":"./cordis.patch.yml"},"client":{"inject":["@deepseek-ai/dsh-api-remotes","@deepseek-ai/dsh-api-session-controller","@deepseek-ai/dsh-api-workspace-controller","@deepseek-ai/dsh-client-connection","@deepseek-ai/dsh-client-locale","@deepseek-ai/dsh-client-ui-renderer","@deepseek-ai/dsh-client-ui-session","@deepseek-ai/dsh-client-ui-sidebar"],"platform":"web"}},"dist":{"shasum":"96a0050e369b9e8a6694ddb51fe3e28adf6f4b58","tarball":"https://registry.npmjs.org/@dsh-xhl/workspace-groups/-/workspace-groups-0.1.1.tgz","fileCount":27,"integrity":"sha512-T/cJ0FxmC7bVYdGr6I/RRuPeB7HoVkAY5wqwFH7eRO7MbLyB4KAmn/sbC8JQjBXrCZ9SJdCnhF5Ax/y1RpMJFg==","signatures":[{"sig":"MEQCIDD1m849wUFXegd2vegN1QWRuzpjkZfZwnficPaiIsG4AiAeHPW0d7RbPSii7S7gXhSTdyOxrSXN08VDyGH/tHz+kQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":624547},"main":"lib/index.js","type":"module","types":"lib/types/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./lib/types/index.d.ts","default":"./lib/index.js"},"./client":{"types":"./lib/types/client/index.d.ts","default":"./lib/client.js"},"./package.json":"./package.json","./cordis.patch.yml":"./cordis.patch.yml"},"gitHead":"cf9d481aa3a76574768928e6440a8b786f722941","scripts":{"test":"vitest run","build":"node -e \"require('node:fs').rmSync('lib', { recursive: true, force: true })\" && pnpm build:types && tsdown","watch":"tsdown --watch","verify":"pnpm typecheck && pnpm test","typecheck":"tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit","build:types":"tsc -p tsconfig.build.json --noEmit false --declaration --emitDeclarationOnly --outDir lib/types"},"_npmUser":{"name":"wojiaoxiaomayun","email":"1146897508@qq.com"},"repository":{"url":"git+https://github.com/z-col/dsh-workspace-groups.git","type":"git"},"_npmVersion":"12.0.2","description":"Complete workspace grouping manager for the DSH web sidebar: 分类 → 项目 → 会话 three-level tree, manual group create/rename/delete, drag-and-drop grouping & ordering with insertion indicator, rule-based auto-classification, tree search. Sidecar YAML + runtime ","directories":{},"_nodeVersion":"24.19.0","dependencies":{"js-yaml":"^4.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^30.0.1","react":"^18.2.0","tsdown":"^0.22.2","vitest":"^4.1.8","js-yaml":"^4.1.0","react-dom":"^18.2.0","typescript":"^5.6.0","@types/node":"^24.0.0","@types/react":"~18.3.1","lightningcss":"^1.32.0","@types/js-yaml":"^4.0.9","@types/react-dom":"~18.3.0","@deepseek-ai/cordis":"^4.0.2","@deepseek-ai/dsh-session":"^0.1.2-rc.1","@deepseek-ai/dsh-api-remotes":"^0.1.2-rc.1","@deepseek-ai/dsh-client-store":"^0.1.2-rc.1","@deepseek-ai/dsh-client-locale":"^0.1.2-rc.1","@deepseek-ai/dsh-host-webserver":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-slots":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-session":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-sidebar":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-renderer":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-primitives":"^0.1.2-rc.1","@deepseek-ai/dsh-api-session-controller":"^0.1.2-rc.1","@deepseek-ai/dsh-api-workspace-controller":"^0.1.2-rc.1"},"peerDependencies":{"react":"^18.2.0","react-dom":"^18.2.0","@deepseek-ai/cordis":"^4.0.2","@deepseek-ai/dsh-session":"^0.1.2-rc.1","@deepseek-ai/dsh-api-remotes":"^0.1.2-rc.1","@deepseek-ai/dsh-client-store":"^0.1.2-rc.1","@deepseek-ai/dsh-client-locale":"^0.1.2-rc.1","@deepseek-ai/dsh-host-webserver":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-slots":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-session":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-sidebar":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-primitives":"^0.1.2-rc.1","@deepseek-ai/dsh-api-session-controller":"^0.1.2-rc.1","@deepseek-ai/dsh-api-workspace-controller":"^0.1.2-rc.1"},"peerDependenciesMeta":{"react-dom":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/workspace-groups_0.1.1_1788655647808_0.2192788096522793","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@dsh-xhl/workspace-groups","version":"0.1.2","keywords":["dsh","deepseek-harness","deepseek-harness-plugin","dsh-plugin","plugin","sidebar","workspace","workspace-groups","client-plugin"],"license":"MIT","_id":"@dsh-xhl/workspace-groups@0.1.2","maintainers":[{"name":"wojiaoxiaomayun","email":"1146897508@qq.com"}],"homepage":"https://github.com/z-col/dsh-workspace-groups#readme","bugs":{"url":"https://github.com/z-col/dsh-workspace-groups/issues"},"dsh":{"bundle":{"patch":"./cordis.patch.yml"},"client":{"inject":["@deepseek-ai/dsh-api-remotes","@deepseek-ai/dsh-api-session-controller","@deepseek-ai/dsh-api-workspace-controller","@deepseek-ai/dsh-client-connection","@deepseek-ai/dsh-client-locale","@deepseek-ai/dsh-client-ui-renderer","@deepseek-ai/dsh-client-ui-session","@deepseek-ai/dsh-client-ui-sidebar"],"platform":"web"}},"dist":{"shasum":"367a4648272dc1cdfb62225e2e9ae0e68f6b23fe","tarball":"https://registry.npmjs.org/@dsh-xhl/workspace-groups/-/workspace-groups-0.1.2.tgz","fileCount":28,"integrity":"sha512-tyvRqSbtXXuho2BlNx/sRyPLQGinJHB7qVUaJJCnY8TUjAkxNDa82zNWTF7kydfUH+utge5xmSffAVeYWGD5ig==","signatures":[{"sig":"MEYCIQC9UcagG7zl4+8m09Ozn96YpgqYx7Ur3xFslvXIb2ZfKwIhANkBqzAvnBQVKsToepUASNbVXtafIUaRe8cYpCGT+t64","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":645359},"main":"lib/index.js","type":"module","types":"lib/types/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./lib/types/index.d.ts","default":"./lib/index.js"},"./client":{"types":"./lib/types/client/index.d.ts","default":"./lib/client.js"},"./package.json":"./package.json","./cordis.patch.yml":"./cordis.patch.yml"},"gitHead":"f8ca75cc2eb572f1a6924710dc581236826c9f84","scripts":{"test":"vitest run","build":"node -e \"require('node:fs').rmSync('lib', { recursive: true, force: true })\" && pnpm build:types && tsdown","watch":"tsdown --watch","verify":"pnpm typecheck && pnpm test","typecheck":"tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit","build:types":"tsc -p tsconfig.build.json --noEmit false --declaration --emitDeclarationOnly --outDir lib/types"},"_npmUser":{"name":"wojiaoxiaomayun","email":"1146897508@qq.com"},"repository":{"url":"git+https://github.com/z-col/dsh-workspace-groups.git","type":"git"},"_npmVersion":"12.0.2","description":"Complete workspace grouping manager for the DSH web sidebar: 分类 → 项目 → 会话 three-level tree, manual group create/rename/delete, drag-and-drop grouping & ordering with insertion indicator, rule-based auto-classification, tree search. Sidecar YAML + runtime ","directories":{},"_nodeVersion":"24.20.0","dependencies":{"js-yaml":"^4.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^30.0.1","react":"^18.2.0","tsdown":"^0.22.2","vitest":"^4.1.8","js-yaml":"^4.1.0","react-dom":"^18.2.0","typescript":"^5.6.0","@types/node":"^24.0.0","@types/react":"~18.3.1","lightningcss":"^1.32.0","@types/js-yaml":"^4.0.9","@types/react-dom":"~18.3.0","@deepseek-ai/cordis":"^4.0.2","@deepseek-ai/dsh-session":"^0.1.2-rc.1","@deepseek-ai/dsh-api-remotes":"^0.1.2-rc.1","@deepseek-ai/dsh-client-store":"^0.1.2-rc.1","@deepseek-ai/dsh-client-locale":"^0.1.2-rc.1","@deepseek-ai/dsh-host-webserver":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-slots":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-session":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-sidebar":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-renderer":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-primitives":"^0.1.2-rc.1","@deepseek-ai/dsh-api-session-controller":"^0.1.2-rc.1","@deepseek-ai/dsh-api-workspace-controller":"^0.1.2-rc.1"},"peerDependencies":{"react":"^18.2.0","react-dom":"^18.2.0","@deepseek-ai/cordis":"^4.0.2","@deepseek-ai/dsh-session":"^0.1.2-rc.1","@deepseek-ai/dsh-api-remotes":"^0.1.2-rc.1","@deepseek-ai/dsh-client-store":"^0.1.2-rc.1","@deepseek-ai/dsh-client-locale":"^0.1.2-rc.1","@deepseek-ai/dsh-host-webserver":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-slots":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-session":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-sidebar":"^0.1.2-rc.1","@deepseek-ai/dsh-client-ui-primitives":"^0.1.2-rc.1","@deepseek-ai/dsh-api-session-controller":"^0.1.2-rc.1","@deepseek-ai/dsh-api-workspace-controller":"^0.1.2-rc.1"},"peerDependenciesMeta":{"react-dom":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/workspace-groups_0.1.2_1789543884918_0.5715381443520593","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@dsh-xhl/workspace-groups","version":"0.2.0","keywords":["dsh","deepseek-harness","deepseek-harness-plugin","dsh-plugin","plugin","sidebar","workspace","workspace-groups","client-plugin"],"license":"MIT","_id":"@dsh-xhl/workspace-groups@0.2.0","maintainers":[{"name":"wojiaoxiaomayun","email":"1146897508@qq.com"}],"homepage":"https://github.com/z-col/dsh-workspace-groups#readme","bugs":{"url":"https://github.com/z-col/dsh-workspace-groups/issues"},"dsh":{"bundle":{"patch":"./cordis.patch.yml"},"client":{"inject":["@deepseek-ai/dsh-api-remotes","@deepseek-ai/dsh-api-session-controller","@deepseek-ai/dsh-api-workspace-controller","@deepseek-ai/dsh-client-connection","@deepseek-ai/dsh-client-locale","@deepseek-ai/dsh-client-ui-renderer","@deepseek-ai/dsh-client-ui-session","@deepseek-ai/dsh-client-ui-sidebar","@deepseek-ai/dsh-client-ui-workspace"],"platform":"web"}},"dist":{"shasum":"afc1ed5794c1e7933356077deddbb8e71aa7eb0e","tarball":"https://registry.npmjs.org/@dsh-xhl/workspace-groups/-/workspace-groups-0.2.0.tgz","fileCount":28,"integrity":"sha512-5JYy0G+tiNlfA5kfc2Lnt/0gyAvRCnQcLAQI6PoawsgWhiH1qyfN2m7J2Rj/mqEQp4sSsmQmbELCQjbH1HsI0Q==","signatures":[{"sig":"MEUCIGnw9tutIzeooyjVOQtzokangbmQQTT4vQypsCOunwswAiEAi16vcPns1pSon/hwl2ULJa8F0Qe6rmVOvKXJDFuet+0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":640924},"main":"lib/index.js","type":"module","types":"lib/types/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./lib/types/index.d.ts","default":"./lib/index.js"},"./client":{"types":"./lib/types/client/index.d.ts","default":"./lib/client.js"},"./package.json":"./package.json","./cordis.patch.yml":"./cordis.patch.yml"},"gitHead":"4aad626c15f118676290145b9af82db1b303d426","scripts":{"test":"vitest run","build":"node -e \"require('node:fs').rmSync('lib', { recursive: true, force: true })\" && pnpm build:types && tsdown","watch":"tsdown --watch","verify":"pnpm typecheck && pnpm test","typecheck":"tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit","build:types":"tsc -p tsconfig.build.json --noEmit false --declaration --emitDeclarationOnly --outDir lib/types"},"_npmUser":{"name":"wojiaoxiaomayun","email":"1146897508@qq.com"},"repository":{"url":"git+https://github.com/z-col/dsh-workspace-groups.git","type":"git"},"_npmVersion":"12.0.2","description":"Complete workspace grouping manager for the DSH web sidebar: 分类 → 项目 → 会话 three-level tree, manual group create/rename/delete, drag-and-drop grouping & ordering with insertion indicator, rule-based auto-classification, tree search. Sidecar YAML + runtime ","directories":{},"_nodeVersion":"24.20.0","dependencies":{"js-yaml":"^4.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^30.0.1","react":"^18.2.0","tsdown":"^0.22.2","vitest":"^4.1.8","js-yaml":"^4.1.0","react-dom":"^18.2.0","typescript":"^5.6.0","@types/node":"^24.0.0","@types/react":"~18.3.1","lightningcss":"^1.32.0","@types/js-yaml":"^4.0.9","@types/react-dom":"~18.3.0","@deepseek-ai/cordis":"^4.0.2","@deepseek-ai/dsh-session":"^0.1.6-alpha.2","@deepseek-ai/dsh-api-remotes":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-store":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-locale":"^0.1.6-alpha.2","@deepseek-ai/dsh-host-webserver":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-slots":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-session":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-sidebar":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-renderer":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-workspace":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-primitives":"^0.1.6-alpha.2","@deepseek-ai/dsh-api-session-controller":"^0.1.6-alpha.2","@deepseek-ai/dsh-api-workspace-controller":"^0.1.6-alpha.2"},"peerDependencies":{"react":"^18.2.0","react-dom":"^18.2.0","@deepseek-ai/cordis":"^4.0.2","@deepseek-ai/dsh-session":"^0.1.6-alpha.2","@deepseek-ai/dsh-api-remotes":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-store":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-locale":"^0.1.6-alpha.2","@deepseek-ai/dsh-host-webserver":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-slots":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-session":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-sidebar":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-workspace":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-primitives":"^0.1.6-alpha.2","@deepseek-ai/dsh-api-session-controller":"^0.1.6-alpha.2","@deepseek-ai/dsh-api-workspace-controller":"^0.1.6-alpha.2"},"peerDependenciesMeta":{"react-dom":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/workspace-groups_0.2.0_1789666523066_0.7944797785875721","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@dsh-xhl/workspace-groups","version":"0.2.1","keywords":["dsh","deepseek-harness","deepseek-harness-plugin","dsh-plugin","plugin","sidebar","workspace","workspace-groups","client-plugin"],"license":"MIT","_id":"@dsh-xhl/workspace-groups@0.2.1","maintainers":[{"name":"wojiaoxiaomayun","email":"1146897508@qq.com"}],"homepage":"https://github.com/z-col/dsh-workspace-groups#readme","bugs":{"url":"https://github.com/z-col/dsh-workspace-groups/issues"},"dsh":{"bundle":{"patch":"./cordis.patch.yml"},"client":{"inject":["@deepseek-ai/dsh-api-remotes","@deepseek-ai/dsh-api-session-controller","@deepseek-ai/dsh-api-workspace-controller","@deepseek-ai/dsh-client-connection","@deepseek-ai/dsh-client-locale","@deepseek-ai/dsh-client-ui-renderer","@deepseek-ai/dsh-client-ui-session","@deepseek-ai/dsh-client-ui-sidebar","@deepseek-ai/dsh-client-ui-workspace"],"platform":"web"}},"dist":{"shasum":"e89e0a67b362b9fd28083a2c345380a08816fd28","tarball":"https://registry.npmjs.org/@dsh-xhl/workspace-groups/-/workspace-groups-0.2.1.tgz","fileCount":29,"integrity":"sha512-aSLgq5OG+jwqPFN3q7+61GrRKp0bd2I+xtUaCnPY8fEXRKmkK5uinPzHAl44K9jRXnqnyqIJ6+Eap+axz8NReA==","signatures":[{"sig":"MEYCIQDD2LnQH38iL5KBJTb2Xt1PXBQDbh9BMGN2N1R6EFL24gIhAL9Cz5kFR1xamcnm4GxAT2ei/MqI0N/lnfBrWL5lfH30","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQCckY6f5bcrEjM3xJmWX01LbQOauK9nOl9tkoa/02YLYQIhAJGHhTfn8CqLVmnITsIVzwNob5ebCBU/Li9u9v3YUvq/","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":657461},"main":"lib/index.js","type":"module","types":"lib/types/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./lib/types/index.d.ts","default":"./lib/index.js"},"./client":{"types":"./lib/types/client/index.d.ts","default":"./lib/client.js"},"./package.json":"./package.json","./cordis.patch.yml":"./cordis.patch.yml"},"gitHead":"e025b5d53616ac0d8e35b48640bfe923588107eb","scripts":{"test":"vitest run","build":"node -e \"require('node:fs').rmSync('lib', { recursive: true, force: true })\" && pnpm build:types && tsdown","watch":"tsdown --watch","verify":"pnpm typecheck && pnpm test","typecheck":"tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit","build:types":"tsc -p tsconfig.build.json --noEmit false --declaration --emitDeclarationOnly --outDir lib/types"},"_npmUser":{"name":"wojiaoxiaomayun","email":"1146897508@qq.com"},"repository":{"url":"git+https://github.com/z-col/dsh-workspace-groups.git","type":"git"},"_npmVersion":"11.19.0","description":"Complete workspace grouping manager for the DSH web sidebar: 分类 → 项目 → 会话 three-level tree, manual group create/rename/delete, drag-and-drop grouping & ordering with insertion indicator, rule-based auto-classification, tree search. Sidecar YAML + runtime ","directories":{},"_nodeVersion":"24.20.0","dependencies":{"js-yaml":"^4.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^30.0.1","react":"^18.2.0","tsdown":"^0.22.2","vitest":"^4.1.8","js-yaml":"^4.1.0","react-dom":"^18.2.0","typescript":"^5.6.0","@types/node":"^24.0.0","@types/react":"~18.3.1","lightningcss":"^1.32.0","@types/js-yaml":"^4.0.9","@types/react-dom":"~18.3.0","@deepseek-ai/cordis":"^4.0.2","@deepseek-ai/dsh-session":"^0.1.6-alpha.2","@deepseek-ai/dsh-api-remotes":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-store":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-locale":"^0.1.6-alpha.2","@deepseek-ai/dsh-host-webserver":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-slots":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-session":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-sidebar":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-renderer":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-workspace":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-primitives":"^0.1.6-alpha.2","@deepseek-ai/dsh-api-session-controller":"^0.1.6-alpha.2","@deepseek-ai/dsh-api-workspace-controller":"^0.1.6-alpha.2"},"peerDependencies":{"react":"^18.2.0","react-dom":"^18.2.0","@deepseek-ai/cordis":"^4.0.2","@deepseek-ai/dsh-session":"^0.1.6-alpha.2","@deepseek-ai/dsh-api-remotes":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-store":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-locale":"^0.1.6-alpha.2","@deepseek-ai/dsh-host-webserver":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-slots":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-session":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-sidebar":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-workspace":"^0.1.6-alpha.2","@deepseek-ai/dsh-client-ui-primitives":"^0.1.6-alpha.2","@deepseek-ai/dsh-api-session-controller":"^0.1.6-alpha.2","@deepseek-ai/dsh-api-workspace-controller":"^0.1.6-alpha.2"},"peerDependenciesMeta":{"react-dom":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/workspace-groups_0.2.1_1790073183582_0.8376670013525227","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@dsh-xhl/workspace-groups","version":"0.3.0","keywords":["dsh","deepseek-harness","deepseek-harness-plugin","dsh-plugin","plugin","sidebar","workspace","workspace-groups","client-plugin"],"license":"MIT","_id":"@dsh-xhl/workspace-groups@0.3.0","maintainers":[{"name":"wojiaoxiaomayun","email":"1146897508@qq.com"}],"homepage":"https://github.com/z-col/dsh-workspace-groups#readme","bugs":{"url":"https://github.com/z-col/dsh-workspace-groups/issues"},"dsh":{"bundle":{"patch":"./cordis.patch.yml"},"client":{"inject":["@deepseek-ai/dsh-api-remotes","@deepseek-ai/dsh-api-session-controller","@deepseek-ai/dsh-api-workspace-controller","@deepseek-ai/dsh-client-connection","@deepseek-ai/dsh-client-locale","@deepseek-ai/dsh-client-ui-conversation","@deepseek-ai/dsh-client-ui-renderer","@deepseek-ai/dsh-client-ui-session","@deepseek-ai/dsh-client-ui-sidebar","@deepseek-ai/dsh-client-ui-workspace"],"platform":"web"}},"dist":{"shasum":"b9f57bd24dc0016f700c405cb0335a2e54f9e770","tarball":"https://registry.npmjs.org/@dsh-xhl/workspace-groups/-/workspace-groups-0.3.0.tgz","fileCount":37,"integrity":"sha512-lz0Bx7oNLC6KX+BgFVJ2yNfNNdRBUZwZvU6Tf041tODV7A3BGYm22aJjjUQzLs8B0ynu4d+0eR5FjLuOAmRRPw==","signatures":[{"sig":"MEQCIAGQ52aKdavd3u/uH0IC+gfAXQkasSNTXj9QgMQJGloTAiA/7ScXUFTGSEV/nK7xznJ9p9uo8AYLOiIA52OZsdYxZQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDEtTmYqmHMwXluLHyyR53gmJ7euFhUYdYs4xpYH8Sm0wIgD9AlpmcLdxYEDeF6z4XHizy+RzvVCX3NYQY6880ZC9o=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":843402},"main":"lib/index.js","type":"module","types":"lib/types/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./lib/types/index.d.ts","default":"./lib/index.js"},"./client":{"types":"./lib/types/client/index.d.ts","default":"./lib/client.js"},"./package.json":"./package.json","./cordis.patch.yml":"./cordis.patch.yml"},"gitHead":"03bb0865abb232701c2b926589e301b971cdfa73","scripts":{"test":"vitest run","build":"node -e \"require('node:fs').rmSync('lib', { recursive: true, force: true })\" && pnpm build:types && tsdown","watch":"tsdown --watch","verify":"pnpm typecheck && pnpm test","typecheck":"tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit","build:types":"tsc -p tsconfig.build.json --noEmit false --declaration --emitDeclarationOnly --outDir lib/types"},"_npmUser":{"name":"wojiaoxiaomayun","email":"1146897508@qq.com"},"repository":{"url":"git+https://github.com/z-col/dsh-workspace-groups.git","type":"git"},"_npmVersion":"12.0.2","description":"Complete workspace grouping manager for the DSH web sidebar: 分类 → 项目 → 会话 three-level tree, manual group create/rename/delete, drag-and-drop grouping & ordering with insertion indicator, rule-based auto-classification, tree search. Sidecar YAML + runtime ","directories":{},"_nodeVersion":"24.20.0","dependencies":{"js-yaml":"^4.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"immer":"^11.1.18","jsdom":"^30.0.1","react":"^18.2.0","tsdown":"^0.22.2","vitest":"^4.1.8","js-yaml":"^4.1.0","zustand":"^5.0.15","react-dom":"^18.2.0","typescript":"^5.6.0","@types/node":"^24.0.0","@types/react":"~18.3.1","lightningcss":"^1.32.0","@types/js-yaml":"^4.0.9","@types/react-dom":"~18.3.0","@deepseek-ai/cordis":"^4.0.2","@deepseek-ai/dsh-session":"^0.1.7-rc.2","@deepseek-ai/dsh-api-remotes":"^0.1.7-rc.2","@deepseek-ai/dsh-client-store":"^0.1.7-rc.2","@deepseek-ai/dsh-client-locale":"^0.1.7-rc.2","@deepseek-ai/dsh-host-webserver":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-slots":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-session":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-sidebar":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-renderer":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-workspace":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-primitives":"^0.1.7-rc.2","@deepseek-ai/dsh-api-session-controller":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-conversation":"^0.1.7-rc.2","@deepseek-ai/dsh-api-workspace-controller":"^0.1.7-rc.2"},"peerDependencies":{"react":"^18.2.0","react-dom":"^18.2.0","@deepseek-ai/cordis":"^4.0.2","@deepseek-ai/dsh-session":"^0.1.7-rc.2","@deepseek-ai/dsh-api-remotes":"^0.1.7-rc.2","@deepseek-ai/dsh-client-store":"^0.1.7-rc.2","@deepseek-ai/dsh-client-locale":"^0.1.7-rc.2","@deepseek-ai/dsh-host-webserver":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-slots":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-session":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-sidebar":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-workspace":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-primitives":"^0.1.7-rc.2","@deepseek-ai/dsh-api-session-controller":"^0.1.7-rc.2","@deepseek-ai/dsh-api-workspace-controller":"^0.1.7-rc.2"},"peerDependenciesMeta":{"react-dom":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/workspace-groups_0.3.0_1790305482845_0.1771645835502489","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@dsh-xhl/workspace-groups","version":"0.4.0","keywords":["dsh","deepseek-harness","deepseek-harness-plugin","dsh-plugin","plugin","sidebar","workspace","workspace-groups","client-plugin"],"license":"MIT","_id":"@dsh-xhl/workspace-groups@0.4.0","maintainers":[{"name":"wojiaoxiaomayun","email":"1146897508@qq.com"}],"homepage":"https://github.com/z-col/dsh-workspace-groups#readme","bugs":{"url":"https://github.com/z-col/dsh-workspace-groups/issues"},"dsh":{"bundle":{"patch":"./cordis.patch.yml"},"client":{"inject":["@deepseek-ai/dsh-api-remotes","@deepseek-ai/dsh-api-session-controller","@deepseek-ai/dsh-api-workspace-controller","@deepseek-ai/dsh-client-connection","@deepseek-ai/dsh-client-locale","@deepseek-ai/dsh-client-ui-conversation","@deepseek-ai/dsh-client-ui-renderer","@deepseek-ai/dsh-client-ui-session","@deepseek-ai/dsh-client-ui-sidebar","@deepseek-ai/dsh-client-ui-workspace"],"platform":"web"}},"dist":{"shasum":"699c082af2fa1b32505a478d663446146d4953ed","tarball":"https://registry.npmjs.org/@dsh-xhl/workspace-groups/-/workspace-groups-0.4.0.tgz","fileCount":37,"integrity":"sha512-siBk62HXtYeAcqGJz90Z/+w+Ghkc+vEdNzyD/Bk8wt9mU6a3UhddfFE22GjRQx8IyiFYrz/3R3VvBc54BwI/XQ==","signatures":[{"sig":"MEQCIBg+5Olqv1Aihbt/patCZqWc98R0qVqogcBUHpHwb8JLAiAw3bxsZkIPEqnheVHADiW3573G4mCIttUWljly+QxlZA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIFq3V9BxJ5kyFTe95oa31rRf/ZLbfwvTpSoGRVk44LZQAiBID++q1EfxrnX3K/LUndVGx5iCLEIOX/HVLXYGPbwHLQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":866304},"main":"lib/index.js","type":"module","types":"lib/types/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./lib/types/index.d.ts","default":"./lib/index.js"},"./client":{"types":"./lib/types/client/index.d.ts","default":"./lib/client.js"},"./package.json":"./package.json","./cordis.patch.yml":"./cordis.patch.yml"},"gitHead":"893ece73be4368840e5daf117f7194bb2111e9ad","scripts":{"test":"vitest run","build":"node -e \"require('node:fs').rmSync('lib', { recursive: true, force: true })\" && pnpm build:types && tsdown","watch":"tsdown --watch","verify":"pnpm typecheck && pnpm test","typecheck":"tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit","build:types":"tsc -p tsconfig.build.json --noEmit false --declaration --emitDeclarationOnly --outDir lib/types"},"_npmUser":{"name":"wojiaoxiaomayun","email":"1146897508@qq.com"},"repository":{"url":"git+https://github.com/z-col/dsh-workspace-groups.git","type":"git"},"_npmVersion":"12.0.2","description":"Complete workspace grouping manager for the DSH web sidebar: 分类 → 项目 → 会话 three-level tree, manual group create/rename/delete, drag-and-drop grouping & ordering with insertion indicator, rule-based auto-classification, tree search. Sidecar YAML + runtime ","directories":{},"_nodeVersion":"24.20.0","dependencies":{"js-yaml":"^4.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"immer":"^11.1.18","jsdom":"^30.0.1","react":"^18.2.0","tsdown":"^0.22.2","vitest":"^4.1.8","js-yaml":"^4.1.0","zustand":"^5.0.15","react-dom":"^18.2.0","typescript":"^5.6.0","@types/node":"^24.0.0","@types/react":"~18.3.1","lightningcss":"^1.32.0","@types/js-yaml":"^4.0.9","@types/react-dom":"~18.3.0","@deepseek-ai/cordis":"^4.0.2","@deepseek-ai/dsh-session":"^0.1.7-rc.2","@deepseek-ai/dsh-api-remotes":"^0.1.7-rc.2","@deepseek-ai/dsh-client-store":"^0.1.7-rc.2","@deepseek-ai/dsh-client-locale":"^0.1.7-rc.2","@deepseek-ai/dsh-host-webserver":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-slots":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-session":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-sidebar":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-renderer":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-workspace":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-primitives":"^0.1.7-rc.2","@deepseek-ai/dsh-api-session-controller":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-conversation":"^0.1.7-rc.2","@deepseek-ai/dsh-api-workspace-controller":"^0.1.7-rc.2"},"peerDependencies":{"react":"^18.2.0","react-dom":"^18.2.0","@deepseek-ai/cordis":"^4.0.2","@deepseek-ai/dsh-session":"^0.1.7-rc.2","@deepseek-ai/dsh-api-remotes":"^0.1.7-rc.2","@deepseek-ai/dsh-client-store":"^0.1.7-rc.2","@deepseek-ai/dsh-client-locale":"^0.1.7-rc.2","@deepseek-ai/dsh-host-webserver":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-slots":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-session":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-sidebar":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-workspace":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-primitives":"^0.1.7-rc.2","@deepseek-ai/dsh-api-session-controller":"^0.1.7-rc.2","@deepseek-ai/dsh-api-workspace-controller":"^0.1.7-rc.2"},"peerDependenciesMeta":{"react-dom":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/workspace-groups_0.4.0_1790426656185_0.6788279390556489","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"@dsh-xhl/workspace-groups","version":"0.4.1","keywords":["dsh","deepseek-harness","deepseek-harness-plugin","dsh-plugin","plugin","sidebar","workspace","workspace-groups","client-plugin"],"license":"MIT","_id":"@dsh-xhl/workspace-groups@0.4.1","maintainers":[{"name":"wojiaoxiaomayun","email":"1146897508@qq.com"}],"homepage":"https://github.com/z-col/dsh-workspace-groups#readme","bugs":{"url":"https://github.com/z-col/dsh-workspace-groups/issues"},"dsh":{"bundle":{"patch":"./cordis.patch.yml"},"client":{"inject":["@deepseek-ai/dsh-api-remotes","@deepseek-ai/dsh-api-session-controller","@deepseek-ai/dsh-api-workspace-controller","@deepseek-ai/dsh-client-connection","@deepseek-ai/dsh-client-locale","@deepseek-ai/dsh-client-ui-conversation","@deepseek-ai/dsh-client-ui-renderer","@deepseek-ai/dsh-client-ui-session","@deepseek-ai/dsh-client-ui-sidebar","@deepseek-ai/dsh-client-ui-workspace"],"platform":"web"}},"dist":{"shasum":"b5f9bb89e94beea9e499ebb1c090b3201deb0a38","tarball":"https://registry.npmjs.org/@dsh-xhl/workspace-groups/-/workspace-groups-0.4.1.tgz","fileCount":37,"integrity":"sha512-n0DVXpBBCFox7j78zkzshA1rwpRRdaETcrjro72LbNiRilhXfN0GEAdeSPQ4UUdgj9KOSmBbYhdeFFs4t42xcQ==","signatures":[{"sig":"MEQCIHKbFTz1/NJU9Wey8QE7XrIlcrNWMATe3ylrnu+i/X8qAiAC2Yq/q3Hna8qELt3dzjTU92H8MKRBVnZrFS8Ot9X01w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIH3kqwKPf8MOli74YU7cucmTW1HFwDPj1m2VaXW23zOqAiEAv8HEThGuPm88pJv+m2in0LReYvsja5wXZeG/kZ7qmuo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":867438},"main":"lib/index.js","type":"module","types":"lib/types/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./lib/types/index.d.ts","default":"./lib/index.js"},"./client":{"types":"./lib/types/client/index.d.ts","default":"./lib/client.js"},"./package.json":"./package.json","./cordis.patch.yml":"./cordis.patch.yml"},"gitHead":"b03db8f90715cb3a2919db10ddac84e0382774ae","scripts":{"test":"vitest run","build":"node -e \"require('node:fs').rmSync('lib', { recursive: true, force: true })\" && pnpm build:types && tsdown","watch":"tsdown --watch","verify":"pnpm typecheck && pnpm test","typecheck":"tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit","build:types":"tsc -p tsconfig.build.json --noEmit false --declaration --emitDeclarationOnly --outDir lib/types"},"_npmUser":{"name":"wojiaoxiaomayun","email":"1146897508@qq.com"},"repository":{"url":"git+https://github.com/z-col/dsh-workspace-groups.git","type":"git"},"_npmVersion":"12.0.2","description":"Complete workspace grouping manager for the DSH web sidebar: 分类 → 项目 → 会话 three-level tree, manual group create/rename/delete, drag-and-drop grouping & ordering with insertion indicator, rule-based auto-classification, tree search. Sidecar YAML + runtime ","directories":{},"_nodeVersion":"24.20.0","dependencies":{"js-yaml":"^4.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"immer":"^11.1.18","jsdom":"^30.0.1","react":"^18.2.0","tsdown":"^0.22.2","vitest":"^4.1.8","js-yaml":"^4.1.0","zustand":"^5.0.15","react-dom":"^18.2.0","typescript":"^5.6.0","@types/node":"^24.0.0","@types/react":"~18.3.1","lightningcss":"^1.32.0","@types/js-yaml":"^4.0.9","@types/react-dom":"~18.3.0","@deepseek-ai/cordis":"^4.0.2","@deepseek-ai/dsh-session":"^0.1.7-rc.2","@deepseek-ai/dsh-api-remotes":"^0.1.7-rc.2","@deepseek-ai/dsh-client-store":"^0.1.7-rc.2","@deepseek-ai/dsh-client-locale":"^0.1.7-rc.2","@deepseek-ai/dsh-host-webserver":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-slots":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-session":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-sidebar":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-renderer":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-workspace":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-primitives":"^0.1.7-rc.2","@deepseek-ai/dsh-api-session-controller":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-conversation":"^0.1.7-rc.2","@deepseek-ai/dsh-api-workspace-controller":"^0.1.7-rc.2"},"peerDependencies":{"react":"^18.2.0","react-dom":"^18.2.0","@deepseek-ai/cordis":"^4.0.2","@deepseek-ai/dsh-session":"^0.1.7-rc.2","@deepseek-ai/dsh-api-remotes":"^0.1.7-rc.2","@deepseek-ai/dsh-client-store":"^0.1.7-rc.2","@deepseek-ai/dsh-client-locale":"^0.1.7-rc.2","@deepseek-ai/dsh-host-webserver":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-slots":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-session":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-sidebar":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-workspace":"^0.1.7-rc.2","@deepseek-ai/dsh-client-ui-primitives":"^0.1.7-rc.2","@deepseek-ai/dsh-api-session-controller":"^0.1.7-rc.2","@deepseek-ai/dsh-api-workspace-controller":"^0.1.7-rc.2"},"peerDependenciesMeta":{"react-dom":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/workspace-groups_0.4.1_1790439408233_0.9248143264393014","host":"s3://npm-registry-packages-npm-production"}},"0.4.2":{"_id":"@dsh-xhl/workspace-groups@0.4.2","dsh":{"bundle":{"patch":"./cordis.patch.yml"},"client":{"inject":["@deepseek-ai/dsh-api-remotes","@deepseek-ai/dsh-api-session-controller","@deepseek-ai/dsh-api-workspace-controller","@deepseek-ai/dsh-client-connection","@deepseek-ai/dsh-client-locale","@deepseek-ai/dsh-client-ui-conversation","@deepseek-ai/dsh-client-ui-renderer","@deepseek-ai/dsh-client-ui-session","@deepseek-ai/dsh-client-ui-sidebar","@deepseek-ai/dsh-client-ui-workspace"],"platform":"web"}},"bugs":{"url":"https://github.com/z-col/dsh-workspace-groups/issues"},"dist":{"shasum":"db1eaccf5a168e0ad36387aa7938a66f8ed137da","tarball":"https://registry.npmjs.org/@dsh-xhl/workspace-groups/-/workspace-groups-0.4.2.tgz","fileCount":37,"integrity":"sha512-ueqyM77sbq9jnEG8QR8VRfDk+v2RLmrUgOQv+NUmRrGrGN6XAuXyqs09Ne7ZQmR2FOnmt1W92LRTcHSK63zO+Q==","signatures":[{"sig":"MEUCIF0JKVz6BRqFFI61Hi2nt5iEP36l3wmn9/XLQejxh0IFAiEAhOjMzV0UxTYlRI3E7XQ0NXFBSb2KQWYaZg97sKK8QWk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIGXfp4BsqkXH0RJu2rz1EGv+vAtGMcuz1oqdQvjPG64+AiEAyYPTu8WwFwx/hB1W7e2Pex6HPF4Lt011gJXkC4E1Bm0="}],"unpackedSize":872019},"main":"lib/index.js","name":"@dsh-xhl/workspace-groups","type":"module","types":"lib/types/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./lib/types/index.d.ts","default":"./lib/index.js"},"./client":{"types":"./lib/types/client/index.d.ts","default":"./lib/client.js"},"./package.json":"./package.json","./cordis.patch.yml":"./cordis.patch.yml"},"gitHead":"2ddc49017456dec6c25922fecf9103180aa05130","license":"MIT","scripts":{"test":"vitest run","build":"node -e \"require('node:fs').rmSync('lib', { recursive: true, force: true })\" && pnpm build:types && tsdown","watch":"tsdown --watch","verify":"pnpm typecheck && pnpm test","typecheck":"tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit","build:types":"tsc -p tsconfig.build.json --noEmit false --declaration --emitDeclarationOnly --outDir lib/types"},"version":"0.4.2","_npmUser":{"name":"wojiaoxiaomayun","email":"1146897508@qq.com"},"homepage":"https://github.com/z-col/dsh-workspace-groups#readme","keywords":["dsh","deepseek-harness","deepseek-harness-plugin","dsh-plugin","plugin","sidebar","workspace","workspace-groups","client-plugin"],"repository":{"url":"git+https://github.com/z-col/dsh-workspace-groups.git","type":"git"},"_npmVersion":"11.19.0","description":"Complete workspace grouping manager for the DSH web sidebar: 分类 → 项目 → 会话 three-level tree, manual group create/rename/delete, drag-and-drop grouping & ordering with insertion indicator, rule-based auto-classification, tree search. Sidecar YAML + runtime ","directories":{},"maintainers":[{"name":"wojiaoxiaomayun","email":"1146897508@qq.com"}],"_nodeVersion":"24.20.0","dependencies":{"js-yaml":"^4.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"immer":"^11.1.18","jsdom":"^30.0.1","react":"^18.2.0","tsdown":"^0.22.2","vitest":"^4.1.8","js-yaml":"^4.1.0","zustand":"^5.0.15","react-dom":"^18.2.0","typescript":"^5.6.0","@types/node":"^24.0.0","@types/react":"~18.3.1","lightningcss":"^1.32.0","@types/js-yaml":"^4.0.9","@types/react-dom":"~18.3.0","@deepseek-ai/cordis":"^4.0.4","@deepseek-ai/dsh-session":"0.2.0-rc.1","@deepseek-ai/dsh-api-remotes":"0.2.0-rc.1","@deepseek-ai/dsh-client-store":"0.2.0-rc.1","@deepseek-ai/dsh-client-locale":"0.2.0-rc.1","@deepseek-ai/dsh-host-webserver":"0.2.0-rc.1","@deepseek-ai/dsh-client-ui-slots":"0.2.0-rc.1","@deepseek-ai/dsh-client-ui-session":"0.2.0-rc.1","@deepseek-ai/dsh-client-ui-sidebar":"0.2.0-rc.1","@deepseek-ai/dsh-client-ui-renderer":"0.2.0-rc.1","@deepseek-ai/dsh-client-ui-workspace":"0.2.0-rc.1","@deepseek-ai/dsh-client-ui-primitives":"0.2.0-rc.1","@deepseek-ai/dsh-api-session-controller":"0.2.0-rc.1","@deepseek-ai/dsh-client-ui-conversation":"0.2.0-rc.1","@deepseek-ai/dsh-api-workspace-controller":"0.2.0-rc.1"},"peerDependencies":{"react":"^18.2.0","react-dom":"^18.2.0","@deepseek-ai/cordis":"^4.0.2","@deepseek-ai/dsh-session":">=0.1.7-rc.2 <0.3.0","@deepseek-ai/dsh-api-remotes":">=0.1.7-rc.2 <0.3.0","@deepseek-ai/dsh-client-store":">=0.1.7-rc.2 <0.3.0","@deepseek-ai/dsh-client-locale":">=0.1.7-rc.2 <0.3.0","@deepseek-ai/dsh-host-webserver":">=0.1.7-rc.2 <0.3.0","@deepseek-ai/dsh-client-ui-slots":">=0.1.7-rc.2 <0.3.0","@deepseek-ai/dsh-client-ui-session":">=0.1.7-rc.2 <0.3.0","@deepseek-ai/dsh-client-ui-sidebar":">=0.1.7-rc.2 <0.3.0","@deepseek-ai/dsh-client-ui-workspace":">=0.1.7-rc.2 <0.3.0","@deepseek-ai/dsh-client-ui-primitives":">=0.1.7-rc.2 <0.3.0","@deepseek-ai/dsh-api-session-controller":">=0.1.7-rc.2 <0.3.0","@deepseek-ai/dsh-api-workspace-controller":">=0.1.7-rc.2 <0.3.0"},"peerDependenciesMeta":{"react-dom":{"optional":true}},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/workspace-groups_0.4.2_1790648350068_0.942155587444423"}}},"time":{"created":"2026-09-05T18:26:43.666Z","modified":"2026-09-29T02:19:10.375Z","0.1.0":"2026-09-05T18:26:43.986Z","0.1.1":"2026-09-06T00:47:27.945Z","0.1.2":"2026-09-16T07:31:25.042Z","0.2.0":"2026-09-17T17:35:23.251Z","0.2.1":"2026-09-22T10:33:03.678Z","0.3.0":"2026-09-25T03:04:42.931Z","0.4.0":"2026-09-26T12:44:16.275Z","0.4.1":"2026-09-26T16:16:48.398Z","0.4.2":"2026-09-29T02:19:10.191Z"},"bugs":{"url":"https://github.com/z-col/dsh-workspace-groups/issues"},"license":"MIT","homepage":"https://github.com/z-col/dsh-workspace-groups#readme","keywords":["dsh","deepseek-harness","deepseek-harness-plugin","dsh-plugin","plugin","sidebar","workspace","workspace-groups","client-plugin"],"repository":{"url":"git+https://github.com/z-col/dsh-workspace-groups.git","type":"git"},"description":"Complete workspace grouping manager for the DSH web sidebar: 分类 → 项目 → 会话 three-level tree, manual group create/rename/delete, drag-and-drop grouping & ordering with insertion indicator, rule-based auto-classification, tree search. Sidecar YAML + runtime ","maintainers":[{"name":"wojiaoxiaomayun","email":"1146897508@qq.com"}],"readme":"<p align=\"right\">\r\n  <strong>English</strong> · <a href=\"./README_ZH.md\">简体中文</a>\r\n</p>\r\n\r\n# @dsh-xhl/workspace-groups\r\n\r\n![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)\r\n![DSH](https://img.shields.io/badge/DSH-0.1.7--rc.2-purple.svg)\r\n<img src=\"https://img.shields.io/badge/DeepSeek%20Harness-plugin-202724\" alt=\"DeepSeek Harness plugin\">\r\n\r\n> **A DeepSeek Harness (DSH) web client plugin: a complete workspace grouping manager.**\r\n> Turns the GUI sidebar's two-level workspace list (Projects → Sessions) into a\r\n> three-level **Category folder → Project folder → Session** tree, backed by full\r\n> group-management capabilities: manual group creation, rename/delete of any group,\r\n> drag-and-drop grouping, free ordering of projects and groups, rule-based\r\n> auto-classification, and tree-shaped search. Every action takes effect\r\n> **immediately and persists**, with **zero intrusion** on official data.\r\n\r\n\r\n## Screenshot\r\n\r\n<img src=\"screenshot.png\" alt=\"@dsh-xhl/workspace-groups workspace grouping manager\" width=\"280\" />\r\n\r\n## Features\r\n\r\n### Grouped tree browsing\r\n- **Group folder → project folder → session row**, both levels collapsible; expansion state\r\n  persists independently (`dsh.workspace.groups.view.v1`, survives refresh/restart)\r\n- **Top-level project rows**: ungrouped projects (matching no rule, dragged out of a group,\r\n  or returned by a group delete) render as plain rows right after the group folders, at the\r\n  same level — **there is no \"未分类\" bucket**\r\n- **A \"flower branch\" runs down the tree and grows to the row you are on.** Ported from the\r\n  [RewampUI Flower Sidebar](https://www.rewampui.com/components/flower-sidebar): one continuous\r\n  SVG stem behind the rows, with **every dot anchored to its own row's marker** — a folder's dot\r\n  sits on its expand triangle, a session's on its status dot — so the three levels form three\r\n  clean columns instead of one stem floating beside them. A faint dashed *ghost* draws the whole\r\n  route while a solid stroke is drawn only as far as the active row, so the stem visibly reaches\r\n  where you are; that row's dot blooms (r 3.2 vs 2). Both coordinates are **measured per row**\r\n  (the tree mixes row heights and indents per row via padding, so neither a single pitch nor a\r\n  single stem x lands correctly). The overlay is `pointer-events: none` and paints behind the\r\n  rows, so every click, hover and drag still belongs to the row. The host theme has no accent hue\r\n  to borrow (`--dsw-alias-brand-primary` is the same near-black as the label colour, and the only\r\n  saturated tokens are the state colours, which would falsely read as \"running\" / \"needs\r\n  attention\"), so the bloom is expressed by **size plus full-strength ink** instead.\r\n- **You can tell at a glance which workspace a session belongs to.** Beyond the branch, three\r\n  more independent cues — not indent alone, since a 20px indent with identical type at both\r\n  levels was previously the *only* difference between a child session and a sibling project row:\r\n  1. **Weight**: folder labels 600 (700 for the folder holding the open session); session titles\r\n     400 (500 when that session is open).\r\n  2. **Typeface**: folder names are directory names and render **monospace**; session titles are\r\n     prose in the UI font. This cue is not colour-based, so it survives every theme.\r\n  3. **Colour**: folder labels primary, session titles secondary — the open session lifts back.\r\n\r\n### Group management (full lifecycle)\r\n- **Create groups manually**: the \"新建分组\" button in the section header shows the group\r\n  immediately (empty groups render too)\r\n- **Rename / delete any group**: every group row (**rule categories included**) has a hover\r\n  `⋯` menu; deleting a group sends all of its projects back to the **top level**;\r\n  rule-category rename/delete rides the overlay (`renamed` / `hidden`),\r\n  **the rule YAML stays untouched**\r\n- **Rule-based auto-classification**: the sidecar YAML declares category rules (`pathPrefix` /\r\n  `pathExact` / `nameContains` / `basenameContains`); edit the config to adjust grouping\r\n  without touching code\r\n\r\n### Drag-and-drop grouping + ordering\r\n- **Drag projects into groups**: drop on any group row or on a project row inside a group\r\n  (cross-group move = overrides the rule classification)\r\n- **Drag projects OUT of a group**: the **entire top-level area** is the move-out drop\r\n  target while dragging, shown with an **insertion line** (not a highlight box) — drop on\r\n  any top-level row (reorder before/after it), on the blank space below the last row\r\n  (append), or, when the top level is empty, a standalone line under the last group\r\n  folder; grouped projects also have a \"移出分组\" menu item (rule-classified ones included)\r\n- **Reorder projects inside a group**: top half of a project row = insert before it,\r\n  bottom half = insert after it\r\n- **Reorder top-level projects**: top-level rows are draggable too — top half = insert\r\n  before, bottom half = insert after; the top-level order persists under\r\n  `workspaceOrder[\"__topLevel__\"]`\r\n- **Reorder groups**: group rows are draggable — top half of another group row = move before it,\r\n  bottom half = move after it\r\n- **Insertion position indicator**: a 2px line (above/below the row) shows the exact drop\r\n  point while dragging — what you see is where it lands\r\n- **Level-aware folding, auto-restored**: dragging a project folds every project row\r\n  (grouped AND top-level; group rows stay expanded); dragging a group folds every group\r\n  (project rows keep their expansion) — dragend restores the pre-drag expansion snapshot\r\n- **Distinct row icons**: group rows use a folder glyph, project rows a project glyph\r\n  (same as the official workspace browser) — groups and projects are easy to tell apart\r\n\r\n### Search & operations\r\n- **Tree-shaped search**: results keep the three-level structure (category → project → matched\r\n  session), matched rows highlighted with a content snippet, 250ms debounce\r\n- **No regression on workspace/session actions**: Add Workspace, project rename/delete,\r\n  session new/open/rename/fork/archive\r\n- **Open in folder**: the project row menu gains an \"Open in folder\" entry whenever the\r\n  host resolved a system file manager (reusing the official open-in-app routes — this\r\n  plugin adds no host route of its own)\r\n\r\n### Session tabs\r\n- **A tab means \"in play\", not \"once opened\".** A session earns a tab only once a conversation\r\n  has actually started in it *and* it is still engaged: **running**, **waiting on you**\r\n  (approval / plan review / question), or **finished while you were away** (the unread marker —\r\n  the tab is what tells you to come back). A blank draft holds no tab until its first message is\r\n  sent, and **browsing settled history leaves the strip alone** — clicking through finished\r\n  conversations no longer litters it with tabs. Tabs already opened stay open; this rule only\r\n  decides whether a *new* one appears. (Browsing history is the sidebar's job; the strip is a\r\n  working set. The earlier `!blank` rule failed because a conversation finished last week is\r\n  also non-blank.)\r\n- **Each tab is shaped like a folder tab**: the workspace on a **short top line** over the session\r\n  title on a **longer bottom line**, so the stacked pair reads as a labelled folder rather than two\r\n  unrelated strings. The workspace line is monospace, smaller (10px) and secondary; the title is\r\n  12px and primary, making the conversation the chip's subject. Each line sizes to its own content\r\n  (`align-items: flex-start`), which is what produces the short-over-long shape. Chips carry a\r\n  faint inset outline that strengthens on the active one, so a row of them reads as separate\r\n  objects instead of one continuous bar. A session in no workspace shows its title alone,\r\n  vertically centred. The tooltip carries the full `workspace · title` plus the directory path.\r\n- **The strip is kept on the HOST, and survives a reload, a restart and a port change.** It is\r\n  stored in a JSON sidecar under `$DSH_HOME` (`workspace-groups.tabs.json`), served over\r\n  `GET|PUT /workspace-groups/tabs`. Browser storage **cannot** do this job: the origin includes\r\n  the **port**, every launch picks a new one, and `localStorage` / `sessionStorage` are both\r\n  scoped to the origin — so a tab list kept there starts empty next time. The read is deliberately\r\n  **not gated by any browser-session marker**: a marker has to live in browser storage too, so the\r\n  port change would erase it and every restart would look like a fresh session (that bug shipped\r\n  once and silently discarded the user's tabs). The sidecar simply is the strip's memory, and a\r\n  file written by the older marker-based build still loads — the extra field is ignored.\r\n- **A tab appears the moment a session starts working**: a sidebar session row, a workspace's\r\n  `+` (New Session), the Ctrl+R quick switch, or a conversation-header crumb — open a session\r\n  from any entry point and, once it starts running, is waiting on you, or finished while you\r\n  were away, a tab appears in the strip at the **top of the conversation column**; opening\r\n  another adds another (one tab per session)\r\n- **Positions never move once placed**: a tab's slot in the strip is decided when it is first\r\n  opened and never changes afterwards. Switching to a tab — or re-opening a session that\r\n  already has one — only moves the *highlight*; the chips stay exactly where they are, so a\r\n  click never slides the chip out from under your pointer. Only two things change the order:\r\n  a session opening for the first time (appended at the end) and a tab closing\r\n- **Scrolls sideways when the strip fills up, with no scrollbar**: chips hold their natural\r\n  width instead of squeezing, so past the available width the row scrolls horizontally. The\r\n  bar itself is hidden (`scrollbar-width: none` + `::-webkit-scrollbar`), keeping the strip\r\n  one line tall. A plain mouse wheel scrolls it sideways, and the active chip is scrolled into\r\n  view when you switch sessions — so a tab far to the right is never stranded off-screen\r\n- **Only YOU close a tab.** The `×` on the right of a tab is the single way it disappears — the\r\n  plugin never trims the strip on its own. Not on archive, not on Host deletion, not when a\r\n  session drops out of the catalog: a tab you opened stays until you say otherwise, and it\r\n  survives reloads and restarts (see the persistence note below). This is deliberate. An\r\n  automatic sweep eventually eats tabs the user wanted, and it also misfires for a mechanical\r\n  reason — the session catalog is briefly empty on every load, so a \"close tabs whose session is\r\n  gone\" rule deletes every restored tab before the sessions have even arrived.\r\n- **Session status per tab**: the dot reuses the sidebar's vocabulary — amber = a question,\r\n  approval, or plan review is waiting, green = running (subagent work included), grey = idle\r\n  (the unread-completion reminder uses the same completion dot)\r\n- **Active chip**: the tab whose session is open is highlighted with an inset accent bar; a\r\n  click on a background chip switches through the official `ctx.uiWorkspace.openSession` — the\r\n  exact path a sidebar row takes\r\n- **Double-click renames**: double-clicking a tab opens the session rename dialog (the same one\r\n  the sidebar's `⋯` menu opens)\r\n- **Blank drafts never take a tab**: a scratch New Session stays out of the strip and earns a\r\n  tab the moment its first turn gives the session a title\r\n- Tab order and the open selection **persist** (`dsh.workspace.groups.tabs.v1`), so a reload\r\n  keeps the strip in the same order\r\n\r\n### Persistence & zero intrusion\r\n- Every manual action (groups, grouping, ordering, rename, hide) is written to the plugin's own\r\n  overlay (`~/.dsh/workspace-groups.manual.json`), validated by the host and **written\r\n  atomically** (a malformed write returns 400 and keeps the previous file)\r\n- **Zero intrusion**: never touches `~/.dsh/storages/workspace.json`, session on-disk\r\n  structures, or the official `@deepseek-ai/dsh-client-ui-workspace` package; the rule YAML\r\n  is never rewritten\r\n- **Self-contained artifact**: `lib/` is prebuilt and shipped with the repo — installing from\r\n  Git runs no dependency scripts\r\n\r\n## How it works\r\n\r\n- The plugin is a **client plugin** with ONE slot registration plus one DOM-seated view:\r\n  1. the sidebar browser, registered into the official sidebar shell's `sidebar.workspaces`\r\n     slot (`kind: 'single'`, `scope: 'root'`) at `priority: -1`, replacing the official\r\n     WorkspaceBrowser (registered at priority 0; lowest priority wins in a single slot);\r\n  2. the session tab strip, which is **not a slot occupant**. It renders through a React\r\n     portal into a container injected as the **first child of the conversation column**\r\n     (`centerCol` in ui-layout's AppFrame) — the row directly above the conversation panel.\r\n- **Why a DOM seat instead of a slot**: the conversation column declares **no child slot**.\r\n  Its only child is the `main` slot's occupant (the Conversation or a global panel), so there\r\n  is nowhere to register a strip. The nearest shipped slot,\r\n  `conversation.composer.dock`, is the band *under* the composer card — a different place\r\n  entirely. The strip therefore claims a real DOM node: `tab-seat.ts` finds the column by the\r\n  `_centerCol` class suffix the CSS-Modules transform always preserves (never the build-hashed\r\n  prefix), prepends its own `<div>`, and re-inserts that same element if React reconciles the\r\n  column's child list. A `MutationObserver` plus a bounded `requestAnimationFrame` retry covers\r\n  the column mounting after the plugin's `apply()` runs; both are torn down with the effect.\r\n- **One handle, one scope**: the DOM seat is also what keeps the tab store legal. DSH's slot\r\n  registry enforces *one handle, one scope* — mounting one store handle under both\r\n  `sidebar.workspaces` (`root`) and a session-scoped slot (`session`) throws and aborts the\r\n  whole client `apply()`. Because the strip is a child of the browser entry rather than a\r\n  second registration, the store is seated exactly once.\r\n- **Who owns the strip**: tabs are a **view**, not a second navigation model. The tab\r\n  lifecycle (which sessions hold a tab, in what order) belongs to the sidebar browser — it\r\n  already derives the open session for its own tree, so \"does this session need a tab?\" is\r\n  decided in exactly one place (and the effect is idempotent per session). The strip only\r\n  renders and supplies the navigation verbs, receiving the tab store, the session hooks and\r\n  the navigation callbacks as ordinary props from that one component.\r\n- All data comes from the runtime API: the `useWorkspaces` / `useSessions` /\r\n  `useSessionStatus` global hooks and `ctx.workspaces.*` / `ctx.sessions.*` /\r\n  `ctx.uiWorkspace.*` — grouping is purely a **presentation-layer transform**.\r\n- The host half does two things: parses the sidecar YAML and merges it with the runtime\r\n  overlay, served to the client via `GET /workspace-groups/config` (`Cache-Control: no-cache`);\r\n  and `PUT /workspace-groups/manual` accepts the full overlay (manual groups, per-workspace\r\n  grouping overrides, group/project ordering, rule-category renames and hides), validates it\r\n  and writes it atomically to `$DSH_HOME/workspace-groups.manual.json`.\r\n- **Classification priority**: manual override (written by drag/menu; `null` = forced\r\n  top-level, rules ignored) → YAML rule classification (hidden rule categories are inert)\r\n  → **top level** (ungrouped projects render as top-level rows). The YAML is never\r\n  rewritten.\r\n\r\n## Install (npm)\r\n\r\n> Prerequisite: [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)\r\n> installed (`dsh` available) with a target profile initialized (e.g. the built-in `web`).\r\n>\r\n> Version pairing: `0.3.x` of this plugin targets the `dsh 0.1.7-rc.2` client\r\n> contract (`useSessionStatus` / `ctx.uiWorkspace` / the `mainView` selection\r\n> model); on a `0.1.2-rc.1`-era `dsh`, use `0.1.2`.\r\n>\r\n> `0.3.0` note: `dsh 0.1.7` renamed the whole `dsh-client-ui-primitives` icon set\r\n> from size suffixes to weight suffixes (`IconCloseFill14` → `IconCloseFillMedium` /\r\n> `…Regular`, no legacy aliases); every call site now uses the new names directly.\r\n\r\n```sh\r\ndsh plugin --profile web add @dsh-xhl/workspace-groups\r\n```\r\n\r\nThis automatically:\r\n\r\n1. Adds `\"@dsh-xhl/workspace-groups\": \"^0.3.0\"` to `dependencies` in\r\n   `~/.dsh/profiles/web/package.json`\r\n2. Appends `\"@dsh-xhl/workspace-groups\"` to `dsh.profile.bundles`\r\n3. Runs pnpm install and validates the bundle layer\r\n\r\n**Restart the web profile after installing** (both the bundle and the host half only load\r\non restart):\r\n\r\n```sh\r\n# Stop the running dsh web process and start it again, e.g.:\r\ndsh web\r\n```\r\n\r\nVerify the install:\r\n\r\n```sh\r\ndsh --profile web --dump-config | grep -A3 workspace-groups\r\n# expect: - id: workspace-groups / name: @dsh-xhl/workspace-groups / config: {}\r\ncurl http://127.0.0.1:3080/workspace-groups/config\r\n# expect: the sidecar YAML parsed as JSON\r\n```\r\n\r\n### Alternative: install from GitHub\r\n\r\n```sh\r\ndsh plugin --profile web add github:z-col/dsh-workspace-groups\r\n```\r\n\r\nThis adds `\"dsh-workspace-groups\": \"github:z-col/dsh-workspace-groups\"` (pinned to\r\nversion/commit) to `dependencies` instead. The GitHub distribution works from the\r\ncommitted `lib/` artifacts and requires no publish step.\r\n\r\n## Uninstall\r\n\r\n```sh\r\ndsh plugin --profile web remove @dsh-xhl/workspace-groups\r\n```\r\n\r\nThis removes the dependency from `dependencies` and the matching line from\r\n`dsh.profile.bundles`. A **web profile restart** is required for it to take effect.\r\n\r\n> Manual equivalent (pick one, don't repeat): edit `~/.dsh/profiles/web/package.json`,\r\n> remove the `@dsh-xhl/workspace-groups` line from `dependencies` and\r\n> `\"@dsh-xhl/workspace-groups\"` from `dsh.profile.bundles`, then run `pnpm install` in\r\n> that directory.\r\n\r\n## Classification config (sidecar)\r\n\r\nDefault location `~/.dsh/workspace-groups.yaml` (override the home dir with the\r\n`$DSH_HOME` env var). Template: `workspace-groups.example.yaml` at the repo root.\r\n\r\n```yaml\r\ncategories:\r\n  - name: DSH 插件\r\n    rules:\r\n      - pathPrefix: /Users/zcol/Project/SkillsManagePlugins\r\n      - nameContains: 插件\r\n      - basenameContains: plugin\r\n  - name: 个人项目\r\n    rules:\r\n      - pathPrefix: /Users/zcol/Project/yeluzi\r\n```\r\n\r\nRule fields (each rule is an OR — any match classifies; categories are matched in order,\r\nfirst match wins):\r\n\r\n| Field | Meaning |\r\n|---|---|\r\n| `pathPrefix` | Project absolute path prefix |\r\n| `pathExact` | Project absolute path exact match |\r\n| `nameContains` | Project display title contains (case-insensitive) |\r\n| `basenameContains` | Project directory name contains (case-insensitive) |\r\n\r\nProjects matching no category — or moved out of a group — render as **top-level project\r\nrows** (same level as the group folders), never hidden.\r\n\r\n## Manual groups & drag-and-drop grouping (runtime overlay)\r\n\r\nBesides the rule YAML there is a plugin-owned runtime overlay, **recording only manual\r\nUI operations**, at `$DSH_HOME/workspace-groups.manual.json` (e.g. `~/.dsh/workspace-groups.manual.json`):\r\n\r\n```json\r\n{\r\n  \"categories\": [\"临时\", \"归档\"],\r\n  \"assignments\": {\r\n    \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\": \"临时\",\r\n    \"a1b2c3d4-e5f6-7890-abcd-ef1234567891\": null\r\n  },\r\n  \"categoryOrder\": [\"临时\", \"DSH 插件\"],\r\n  \"workspaceOrder\": { \"临时\": [\"a1b2c3d4-e5f6-7890-abcd-ef1234567890\"] },\r\n  \"renamed\": { \"DSH 插件\": \"插件集\" },\r\n  \"hidden\": [\"文档\"]\r\n}\r\n```\r\n\r\n- `categories` — manually created group names (no rules; empty groups render too).\r\n- `assignments` — workspace → group classification overrides keyed by the stable workspace id\r\n  (renames don't affect it). **Takes precedence over YAML rules**; a value of `null` means\r\n  **forced top-level** (even when a rule would match).\r\n- `categoryOrder` — group display order (top-level rows are not listed here; they always\r\n  render after the group folders).\r\n- `workspaceOrder` — per-group manual ordering of projects (written by drag ordering).\r\n- `renamed` / `hidden` — UI rename/delete of rule categories (a hidden category's rules become\r\n  inert and its matches go top-level); the rule YAML stays untouched.\r\n- The file is written in full by the browser UI (`PUT /workspace-groups/manual`, atomic\r\n  replace); manual edits also take effect on next load. A malformed write returns 400 and\r\n  keeps the previous file — the rule YAML is never at risk.\r\n\r\n| Action | How |\r\n|---|---|\r\n| Create group | \"新建分组\" button in the section header (folder icon), enter a name in the dialog |\r\n| Rename/delete group | hover `⋯` menu on **any** group (rule categories included); deleting sends its projects back to the top level |\r\n| Drag project into group | drag a project row onto a target group row / any project row inside a group, release to move |\r\n| Reorder projects | drag a project row onto another project row in the same group: **top half = insert before, bottom half = insert after** (indicator shows the spot); all project rows fold while dragging and restore on dragend |\r\n| Reorder top-level projects | drag a top-level row onto another top-level row: **top half = insert before, bottom half = insert after**; order persists under `workspaceOrder[\"__topLevel__\"]` |\r\n| Move out of a group | drop anywhere on the **top-level area** (an insertion line shows the spot — reorder before/after a top-level row, or append below the last row; when the top level is empty a line shows under the last group), or the project row's \"移出分组\" menu (forced top-level) |\r\n| Reorder groups | drag a group row onto another group row: **top half = move before, bottom half = move after** (indicator shows the spot; all groups fold while dragging, restored on dragend) |\r\n| Open in folder | the project row's \"在文件夹中打开\" / \"Open in folder\" menu entry — opens the project directory in the host's file manager (see below) |\r\n\r\n### Open in folder (reuses the official open-in-app)\r\n\r\nThe project row's \"Open in folder\" entry carries **no launching logic of its own**: it\r\nreuses what the official `@deepseek-ai/dsh-host-open-in-app` already resolved —\r\n`GET /open-in-app/apps` reads back the applications that host verified as launchable,\r\nthe plugin picks this platform's file manager from them\r\n(Windows `explorer` / macOS `finder` / Linux `filemanager`), and POSTs the project\r\ndirectory to `POST /open-in-app/open` for its **verified launcher** to handle.\r\n\r\n- When that host half resolved no file manager (e.g. a remote SSH deployment),\r\n  **the entry is simply absent** rather than failing on click; a project whose\r\n  directory no longer exists is refused by the host with 404 and surfaces as a\r\n  transient \"could not open the folder\" banner.\r\n- This plugin's own host half is therefore **unchanged**: no new route, no process\r\n  spawn — permissions and the Host/Origin fence stay with those three official routes.\r\n\r\n## Topics\r\n\r\nThis repo targets automatic discovery by the DSH plugin ecosystem (community marketplaces\r\nscan GitHub topics). Already set:\r\n\r\n- `dsh-plugin` (core tag; [1024Store](https://github.com/imsai-sh/awesome-deepseek-harness-plugins)\r\n  and similar marketplaces discover by this topic periodically, validating\r\n  `package.json` + the plugin bundle manifest (`cordis.patch.yml`))\r\n- `deepseek-harness` / `deepseek-harness-plugin` / `dsh`\r\n- `sidebar` / `workspace` / `workspace-groups`\r\n\r\n`package.json` also provides `keywords` for npm/search indexing.\r\n\r\n## Development\r\n\r\n```sh\r\npnpm install\r\npnpm typecheck   # host + client dual-program type checking\r\npnpm test        # core rules, overlay, tree derivation unit tests\r\npnpm build       # build lib/ (node half + client bundle)\r\npnpm watch       # tsdown watch (client HMR)\r\nnode scripts/verify-groups.mjs   # real-browser CDP verification (host restarted; self-spawns a headless Chrome, auto-restores the scene)\r\n```\r\n\r\nArtifact contract (mirrors the official client packages):\r\n\r\n- `lib/index.js` — host half (ESM; reads the sidecar + `/workspace-groups/config` route;\r\n  js-yaml inlined, no runtime dependencies)\r\n- `lib/client.js` — browser half (`window.__ModuleLoader__.load({id, factory})`; only\r\n  requires platform seeds: react / react/jsx-runtime / react-dom /\r\n  @deepseek-ai/dsh-client-store / @deepseek-ai/dsh-client-ui-slots /\r\n  @deepseek-ai/dsh-client-ui-primitives; cross-plugin value imports are rejected at build\r\n  time by the purity gate)\r\n- `lib/types/**` — declaration files\r\n\r\n> Release strategy: `lib/` build artifacts are committed (no `prepare` script), so\r\n> `dsh plugin add github:...` never runs third-party build scripts — install and use.\r\n\r\n## Repository layout\r\n\r\n```\r\nsrc/\r\n  index.ts              # host half: config snapshot route + manual write route + tabs route\r\n  host-config.ts        # sidecar YAML reading/validation\r\n  host-manual.ts        # runtime overlay read/write/validation (atomic publish)\r\n  host-tabs.ts          # session-tab sidecar: atomic write + browser-session lifetime\r\n  context-types.ts      # host-side cordis service structure types\r\n  core/\r\n    types.ts            # config types (shared by both halves)\r\n    matcher.ts          # classification + manual override priority + ordering pure functions (shared)\r\n  client/\r\n    index.ts            # apply: registers sidebar.workspaces (priority -1); seats the tab store once\r\n    contract.ts         # injected surface types (browser) + the strip's plain props\r\n    stores.ts           # expansion-state store (persist: dsh.workspace.groups.view.v1)\r\n    tab-store.ts        # session-tab store (hydrated from the host)\r\n    tab-persist.ts      # client side of /workspace-groups/tabs (host-backed strip)\r\n    tabs.ts             # pure tab state: append/close/restore/indicator derivation\r\n    store-hook.ts       # selector hook over a store instance (the framework binds this for slot seats only)\r\n    tab-seat.ts         # DOM seat: injects the strip container as the conversation column's first child\r\n    tree.ts             # three-level tree derivation + tree search derivation\r\n    branch.ts           # flower-branch geometry: the curly stem, its kinks, and the dots\r\n    GroupsBrowser.tsx   # browser region component (group dialogs + drag grouping/ordering + insertion indicator)\r\n    SessionTabs.tsx     # session tab strip component (portalled into the column-head seat)\r\n    FlowerBranch.tsx    # SVG overlay that grows the stem to the active row\r\n    rows.tsx            # category/project/session/search-result rows (drag sources/targets)\r\n    open-folder.ts      # \"open in folder\" transport (client of the official open-in-app routes)\r\n    locales.ts          # zh/en copy\r\n    styles.css          # inline styles (browser + tab strip)\r\ntests/\r\n  core.test.ts          # classification rules + override priority + moveBefore/moveAfter + config parsing\r\n  manual.test.ts        # overlay validation + atomic file round-trip\r\n  tree.test.ts          # tree derivation rendering contract (manual group empty render / override priority)\r\n  store.test.ts         # expansion semantics (collapse writes false, never deletes the key)\r\n  quick.test.ts         # quick-panel data shaping (running first / workspace search ranking)\r\n  tabs.test.ts          # tab state (append, close, restore, blank drafts, indicators, no sweep)\r\n  tab-seat.test.ts      # DOM seat (first-child placement, late column mount, re-seat after React removes it, dispose)\r\n  branch.test.ts        # flower-branch geometry (kink per group, dot per row on its own y, grown stops at active)\r\n  host-tabs.test.ts     # host tab store (atomic write, no session gating, legacy-file compat, corrupt fallback)\r\n  styles.test.ts        # tab-strip layout contract (chips do not shrink, row scrolls, scrollbar hidden)\r\n  open-folder.test.ts   # open-in-app transport (file-manager pick + read/POST contract)\r\nscripts/\r\n  verify-groups.mjs     # real-browser CDP verification (self-spawns headless Chrome, auto-restores the scene)\r\n```\r\n\r\n> Development docs (`docs/` five-level framework and `AGENTS.md`) are engineering files for\r\n> development, **not shipped with the repo** (excluded via `.gitignore`).\r\n\r\n## Verification record\r\n\r\n- v0.1/v0.2 real-combination verification (headless Chrome + CDP): three-level tree takeover,\r\n  correct classification, expansion persistence, search keeps workspace membership;\r\n  `workspace.json` / session on-disk / official store: zero intrusion.\r\n- v0.3 real-browser verification 24/24 (`scripts/verify-groups.mjs`: create group / drag /\r\n  order / collapse / rule-category menu / rename / delete-back-to-top-level /\r\n  scene restore; zero-intrusion assertions).\r\n- v0.4 real-browser verification 30/30 (added: insertion indicator, project/group\r\n  **downward drag** (bottom half → insert after the target), group upward drag (top half →\r\n  move before the target); scene restored).\r\n- v0.4.1 real-browser verification 34/34 (added: dragging projects OUT of a group —\r\n  top-level drop zone / top-level rows = forced top-level; grouped projects get the\r\n  \"移出分组\" menu item).\r\n- v0.5 real-browser verification 35/35 (model change: **no \"未分类\" bucket** — top-level\r\n  project rows, group delete returns members to the top level, drag/menu move-out to the\r\n  top level, no uncategorized bucket anywhere in the tree; scene restored).\r\n- v0.6 real-browser verification 40/40 (added: **level-aware folding** — dragging a project\r\n  folds project rows only (group rows stay open), dragging a group folds group rows only;\r\n  dragend restores the pre-drag expansion snapshot).\r\n- v0.6.1 real-browser verification 42/42 (added: the whole top-level area as the move-out\r\n  drop target with a visible landing highlight; distinct folder-vs-project row icons;\r\n  scene restored).\r\n- v0.7 real-browser verification 46/46 (added: top-level landing shown with an **insertion\r\n  line** instead of a highlight box — reorder before/after a top-level row, append below\r\n  the last row, or a standalone line when the top level is empty; **top-level projects are\r\n  reorderable** with their order persisted under `workspaceOrder[\"__topLevel__\"]`; also\r\n  fixed a host validation bug that rejected `__topLevel__` and a drop-positioning bug where\r\n  dropping between two top-level rows landed above the first; scene restored).\r\n- v0.8: **open in folder** on the project row, reusing the official open-in-app host routes\r\n  (per-platform file-manager pick, entry absent when the host resolved none, launch\r\n  failures surfaced as a transient banner).\r\n- v0.9: **session tabs** — one strip at the **top of the conversation column**, injected as the\r\n  column's first child (the column declares no child slot, and the nearest shipped slot sits\r\n  under the composer card instead); clicking a session opens a tab, tabs close individually,\r\n  the status dot reuses the sidebar vocabulary, double-click renames, blank drafts stay out,\r\n  and the order persists.\r\n- v0.9.1: rebuilt for **DSH 0.1.7-rc.2** — the client contract moved the icon set from\r\n  size-suffixed names (`IconCloseFill14`) to weight-suffixed ones (`IconCloseFillMedium` /\r\n  `…Regular`), and the tab store now mounts under a single scope (the slot version mounted one\r\n  handle under both `root` and `session`, which the registry rejects).\r\n- v0.9.2: **tab positions are stable** — the strip no longer pulls the active tab to the front,\r\n  so clicking a tab switches the conversation without moving the chip; the store's `touch`\r\n  and `close` transforms are now no-ops when nothing changed, which stops the arrival counter\r\n  churning on every catalog update.\r\n- v0.9.3: **the strip scrolls sideways past the available width, with no scrollbar** — chips\r\n  hold their natural width (`flex: 0 0 auto`) instead of shrinking, a plain wheel scrolls the\r\n  row horizontally, and the active chip is kept in view. The active chip also gets the host's\r\n  selected-row fill instead of a hardcoded blue accent bar (`--dsw-accent` / `--dsw-bg-selected`\r\n  are not product theme tokens, so those always fell through to blue literals).\r\n- v0.9.4: **tabs name their project** (`project · title`, mono prefix, tooltip with the path),\r\n  and the **sidebar tree is legible at a glance** — heavier monospace folder labels against\r\n  lighter prose session titles.\r\n- v0.10: **flower branch** — one continuous SVG stem down the sidebar tree, kinking at each\r\n  project, with a dot per row on the curve; a dashed ghost draws the whole route and a solid\r\n  stroke grows to the active row, whose dot blooms. Replaces the per-folder guide rail.\r\n- v0.10.1: **tabs mean \"in play\", not \"once opened\"** — a session earns a tab only while it is\r\n  running, waiting on you, or finished-unread, so browsing settled history no longer fills the\r\n  strip. A draft holds no tab until its first message is sent.\r\n- v0.10.2: **tabs are folder-shaped** — the workspace sits on a short top line over the session\r\n  title on a longer bottom line, each line sizing to its own content.\r\n- v0.11: **roomier tabs** (56px strip, 8/10px padding, 6px between chips, 3px between the two\r\n  lines, an inset outline per chip) and **tabs persist to the host** (`$DSH_HOME/…tabs.json` over\r\n  `GET|PUT /workspace-groups/tabs`) — browser storage is per-origin and the port changes every\r\n  launch, so it could never restore a strip. One bug found while verifying: the persistence\r\n  subscriber wrote the store's initial EMPTY state over the stored tabs before the host read\r\n  resolved (fixed with a hydration latch — writes now happen only on a real state change).\r\n- v0.11.1: **a tab is removed only by the user.** All automatic trimming is gone: no catalog-driven\r\n  sweep, no close on archive or Host deletion. The rule is the user's (\"unless I close it, the\r\n  program must not delete it\"), and the sweep was also mechanically broken — the session catalog\r\n  is briefly empty on every load, so it deleted restored tabs before the sessions arrived. The\r\n  persistence subscriber now only writes on a real state change, so a failed or empty read can no\r\n  longer erase the stored strip either.\r\n- v0.11.2: **the restart fix.** The `X-WG-Session` marker is gone. It lived in `sessionStorage`,\r\n  which the port change erased, so every restart presented a new marker and the host withheld the\r\n  stored tabs — the exact \"restart doesn't show my tabs\" bug. The sidecar is now returned\r\n  verbatim, and a legacy file's extra `sessionKey` field is ignored. `restore` also MERGES\r\n  instead of bailing on a non-empty strip: the tab opened during startup and the stored tabs now\r\n  both survive.\r\n- v0.12 (release `0.3.0`): merged the remote `0.2.1` icon-rename fix — every call site now uses\r\n  the `dsh 0.1.7` weight-suffixed names directly (`IconCloseFillMedium` / `…Regular`), so the\r\n  remote `icons.ts` alias table is no longer needed and has been deleted. The remote inject-face\r\n  fixes are kept: the reserved `hooks.directoryFlow` compartment (the official entry stays\r\n  registered behind this one and gates its own \"Add workspace…\" affordance on that hole) and the\r\n  dual map/record read of `SessionStatusSnapshot`.\r\n- Typecheck + build pass (including the client-bundle purity gate).\r\n- 179 unit tests green (vitest: `core` / `manual` / `tree` / `store` / `quick` / `tabs` /\r\n  `tab-seat` / `host-tabs` / `branch` / `styles` / `open-folder`).\r\n- Reproducible automated verification: `node scripts/verify-groups.mjs` (host restarted).\r\n\r\n## License\r\n\r\nMIT\r\n","readmeFilename":"README.md"}