Repository navigation
feat(web-shell): redesign Channel policy and workspace management #8848
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
wenshao
merged 23 commits into
QwenLM:main
from
qqqys:codex/issue-8845-channel-access-policies
Aug 14, 2026
Merged
Changes from 11 commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
f6f74a2
feat(web-shell): expose channel access policies
qqqys c197181
test(cli): cover shared Channel management fields
qqqys aed48dc
feat(web-shell): clarify channel policy controls
qqqys 3807cb9
feat(web-shell): select channel workspace
qqqys 111e17e
feat(web-shell): redesign channel management
qqqys 2333a05
fix(web-shell): align channel manager with shell tabs
qqqys f7adc65
fix(web-shell): prioritize conversation settings
qqqys f8ac419
fix(web-shell): preserve legacy channel defaults
qqqys 907b46a
fix(channels): address management review blockers
qqqys 26849ba
fix(channels): address editor review blockers
qqqys b6f26d0
fix(channels): preserve workspace action and route state
qqqys 49f7a25
fix(web-shell): prevent stale channel editor state
qqqys 844d833
fix(channels): preserve stored group settings
qqqys 410543b
fix(channels): preserve group behavior settings
qqqys 7c5c125
fix(web-shell): reset channel workspace UI state
qqqys a811c93
fix(web-shell): resolve channel management conflicts
qqqys 013b31e
test(web-shell): assert restored channel scope
qqqys 3a7b0f0
Merge branch 'main' into codex/issue-8845-channel-access-policies
qqqys ec7f42f
fix(web-shell): preserve legacy channel scope
qqqys 6c532fe
fix(web-shell): preserve inherited channel defaults
qqqys fd6241b
fix(channels): preserve compatible legacy settings
qqqys 1bd4a48
fix(web-shell): keep workspace navigation available
qqqys ad365b8
fix(channels): default new channels to pairing
qqqys File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ import type { | |
| ChannelConfigFieldDescriptor, | ||
| ChannelConfigFieldKind, | ||
| ChannelPlugin, | ||
| SessionScope, | ||
| } from '@qwen-code/channel-base'; | ||
|
|
||
| export interface ChannelTypeDescriptor { | ||
|
|
@@ -30,6 +31,77 @@ const FIELD_KINDS: ReadonlySet<ChannelConfigFieldKind> = new Set([ | |
| 'object', | ||
| ]); | ||
|
|
||
| const SHARED_ACCESS_FIELDS: readonly ChannelConfigFieldDescriptor[] = [ | ||
| { | ||
| key: 'senderPolicy', | ||
| label: 'Sender Policy', | ||
| kind: 'enum', | ||
| required: true, | ||
| default: 'allowlist', | ||
| description: 'Controls who can start direct conversations', | ||
| options: [ | ||
| { value: 'pairing', label: 'Pairing' }, | ||
| { value: 'allowlist', label: 'Allowlist' }, | ||
| { value: 'open', label: 'Open' }, | ||
| ], | ||
| }, | ||
| { | ||
| key: 'allowedUsers', | ||
| label: 'Allowed Users', | ||
| kind: 'string-list', | ||
| description: 'Stable user IDs allowed without pairing', | ||
| }, | ||
| { | ||
| key: 'groupPolicy', | ||
| label: 'Group Policy', | ||
| kind: 'enum', | ||
| required: true, | ||
| default: 'disabled', | ||
| description: 'Controls which group conversations can use this Channel', | ||
| options: [ | ||
| { value: 'disabled', label: 'Disabled' }, | ||
| { value: 'pairing', label: 'Pairing' }, | ||
| { value: 'allowlist', label: 'Allowlist' }, | ||
| { value: 'open', label: 'Open' }, | ||
| ], | ||
| }, | ||
| ]; | ||
|
|
||
| const SESSION_SCOPE_OPTIONS: ReadonlyArray<{ | ||
| value: SessionScope; | ||
| label: string; | ||
| }> = [ | ||
| { value: 'user', label: 'Per User and Chat' }, | ||
| { value: 'thread', label: 'Per Thread (Legacy)' }, | ||
|
Comment on lines
+70
to
+75
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 已修复。验证证据:旧 |
||
| { value: 'chat_thread', label: 'Per Chat and Thread' }, | ||
| { value: 'single', label: 'One Shared Session' }, | ||
| ]; | ||
|
|
||
| function managementFieldsWithSharedControls( | ||
| fields: readonly ChannelConfigFieldDescriptor[], | ||
| defaultSessionScope: SessionScope, | ||
| ): readonly ChannelConfigFieldDescriptor[] { | ||
| const declared = new Set(fields.map((field) => field.key)); | ||
| return [ | ||
| ...fields, | ||
| ...SHARED_ACCESS_FIELDS.filter((field) => !declared.has(field.key)), | ||
| ...(declared.has('sessionScope') | ||
| ? [] | ||
| : [ | ||
| { | ||
| key: 'sessionScope', | ||
| label: 'Session Scope', | ||
| kind: 'enum' as const, | ||
| required: true, | ||
| default: defaultSessionScope, | ||
| description: | ||
| 'Controls how conversations share persistent agent sessions', | ||
| options: SESSION_SCOPE_OPTIONS, | ||
| }, | ||
| ]), | ||
| ]; | ||
| } | ||
|
|
||
| function assertManagementFields( | ||
| fields: readonly ChannelConfigFieldDescriptor[], | ||
| parentPath?: string, | ||
|
|
@@ -273,11 +345,16 @@ export async function supportedChannelCatalog(): Promise< | |
| > { | ||
| await ensureBuiltins(); | ||
| return [...registry.values()].map( | ||
| ({ channelType, displayName, management }) => ({ | ||
| ({ channelType, displayName, management, defaultSessionScope }) => ({ | ||
| type: channelType, | ||
| displayName, | ||
| manageable: management !== undefined, | ||
| fields: management?.fields ?? [], | ||
| fields: management | ||
| ? managementFieldsWithSharedControls( | ||
| management.fields, | ||
| defaultSessionScope ?? 'user', | ||
| ) | ||
| : [], | ||
| }), | ||
| ); | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Critical] Routing key format change for
'chat_thread'orphans existing sessions with thread IDs on migration — Failure scenario: a channel withsessionScope: 'thread'had an active session routed asname:topic-1. After upgrade,parseChannelConfignormalizes the config to'chat_thread', soSessionRouter.routingKeyproducesname:chat-1:topic-1. The old session is never found, and old attachment directories are orphaned.中文说明
迁移后
'chat_thread'的路由键格式变化会使现有含有 thread ID 的会话孤立。— 失败场景:sessionScope: 'thread'的频道有一个活跃会话,路由键为name:topic-1。升级后parseChannelConfig将配置归一化为'chat_thread',SessionRouter.routingKey产生name:chat-1:topic-1。旧会话无法找到,旧附件目录也被孤立。建议添加路由键迁移兼容层。— deepseek-v4-flash via Qwen Code /review (v0.21.8)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
已修复 + 验证证据:b6f26d0dee;config-utils.test.ts 50/50、channel-editor-state.test.ts 31/31 通过,legacy thread 在加载和编辑保存两条路径保持原路由与授权语义。