Skip to content

Feature/sites secondary development - #2618

Merged
qdaxb merged 2 commits into
wecode-ai:mainfrom
earthAlone2026:feature/sites-secondary-development
Aug 12, 2026
Merged

qdaxb merged 2 commits into
wecode-ai:mainfrom
earthAlone2026:feature/sites-secondary-development

Conversation

@earthAlone2026

@earthAlone2026 earthAlone2026 commented Aug 12, 2026 •

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Edit site titles and custom-domain prefixes directly from the Sites workspace.
    • Continue development on existing sites through a streamlined action.
    • Site and mini-program details now display project information.
    • Sites support richer edit, publish, and delete actions based on available capabilities.
    • Wegent Sites project links now render as recognizable link previews and composer chips.
    • Plugin inputs can open directly in a new chat.
  • Documentation

    • Updated application capability guidance for editing sites.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds authenticated site metadata editing across the backend and frontend. It advertises the edit capability, adds continuation-development actions, queues plugin trials for new chats, and recognizes Wegent Sites project links in chat rendering.

Changes

Backend site metadata update

Layer / File(s) Summary
Metadata contract and upstream mapping
backend/app/schemas/site.py, backend/app/services/site_application_types.py, backend/app/services/sites.py
Site responses now include project and domain fields. The service maps these fields and sends authenticated, idempotent PATCH updates.
PATCH endpoint and validation
backend/app/api/endpoints/sites.py, wework/e2e/utils/mock-sites-upstream-server.mjs
The authenticated endpoint validates trimmed metadata and delegates updates. The upstream mock supports authenticated PATCH requests and required headers.
Backend validation
backend/tests/api/test_sites_api.py
Tests cover capabilities, response fields, metadata updates, headers, payloads, and idempotency keys.

Frontend site editing and continuation

Layer / File(s) Summary
Site update API and edit controls
wework/src/api/sites.ts, wework/src/components/sites/SiteActionsMenu.tsx, wework/src/components/sites/EditSiteDialog.tsx
The frontend adds updateSite, capability-gated edit actions, and a validated metadata dialog.
Workspace integration
wework/src/components/sites/SitesWorkspace.tsx, wework/src/components/sites/SitesWorkspace.test.tsx, wework/src/i18n/locales/*/sites.json
The workspace updates site rows after successful saves and preserves the dialog with localized errors after failures.
Continuation flow
wework/src/pages/SitesPage.tsx, wework/src/components/sites/ApplicationRows.tsx, wework/src/features/plugins/pluginTrial.ts
Site rows can start continuation development. The page prepares plugins and queues site-specific input in a new chat.
Capability and telemetry alignment
wework/src/components/sites/applicationTypeDefinitions.tsx, wework/src/telemetry/events.ts, wework/e2e/desktop/modules/desktop-server.mjs, docs/en/..., docs/zh/...
The edit capability is added to application definitions, telemetry validation, desktop fixtures, and documentation.

Wegent Sites project links

Layer / File(s) Summary
Project-link recognition and rendering
wework/src/lib/link-preview.ts, wework/src/components/chat/AssistantMarkdown.tsx, wework/src/components/chat/MessageList.tsx, wework/src/components/chat/composer/composerLinks.ts
Chat link parsing accepts valid URI schemes, and Wegent Sites project links render as recognized composer chips.
Project-link validation
wework/src/lib/link-preview.test.ts, wework/src/components/chat/MessageList.test.tsx, wework/src/components/chat/composer/ComposerProseMirrorEditor.test.tsx, wework/src/features/plugins/pluginTrial.test.ts
Tests cover recognition, rendering, serialization, and queued plugin input.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Suggested reviewers: qdaxb

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title identifies the sites secondary-development feature, which matches the primary continuation and editing changes in the pull request.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (6)
wework/src/components/chat/composer/composerLinks.ts (2)

15-18: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prefer a regex literal over new RegExp with escaped strings.

The string form requires double escaping and is harder to read. A literal expresses the same pattern.

♻️ Proposed literal
-const MARKDOWN_LINK_REGEX = new RegExp(
-  '\\[!?([^\\]]*)\\]\\(([a-z][a-z0-9+.-]*:\\/\\/[^\\s)\\]]+)\\)',
-  'gi'
-)
+const MARKDOWN_LINK_REGEX = /\[!?([^\]]*)\]\(([a-z][a-z0-9+.-]*:\/\/[^\s)\]]+)\)/gi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/components/chat/composer/composerLinks.ts` around lines 15 - 18,
Replace the MARKDOWN_LINK_REGEX RegExp constructor with an equivalent regex
literal, preserving the current matching behavior and global, case-insensitive
flags.

15-18: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the widened URI-scheme pattern into one shared constant. This PR widens the same scheme sub-pattern [a-z][a-z0-9+.-]*:// in three places. The three copies already diverge: the composer regex accepts an optional leading !, the message regex does not. A future scheme change must be applied three times, and the copies can drift further.

  • wework/src/components/chat/composer/composerLinks.ts#L15-L18: export the scheme pattern as a shared constant, and build MARKDOWN_LINK_REGEX from it.
  • wework/src/components/chat/MessageList.tsx#L1700-L1700: build COMPOSER_LINK_PATTERN from the shared constant, and decide whether the optional ! prefix should also apply here.
  • wework/src/components/chat/AssistantMarkdown.tsx#L183-L187: replace the inline /^[a-z][a-z0-9+.-]*:\/\//i test with a helper that uses the shared constant.

As per coding guidelines: "Before adding code, search for and reuse existing components, services, utilities, and patterns; extract shared logic instead of duplicating it."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/components/chat/composer/composerLinks.ts` around lines 15 - 18,
The URI-scheme pattern is duplicated across three locations and must be
centralized. In wework/src/components/chat/composer/composerLinks.ts:15-18,
export a shared scheme-pattern constant and build MARKDOWN_LINK_REGEX from it;
in wework/src/components/chat/MessageList.tsx:1700, build COMPOSER_LINK_PATTERN
from that constant and preserve or explicitly align the optional “!” handling;
in wework/src/components/chat/AssistantMarkdown.tsx:183-187, replace the inline
scheme test with a helper using the shared constant.

Source: Coding guidelines

wework/src/features/plugins/pluginTrial.ts (1)

267-281: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Restrict the options type or honor reference.

queuePluginInputTrial accepts the full PluginTrialOptions but only reads openInNewChat and prompt. If a caller passes reference, the function silently ignores it. Narrow the parameter type to the supported fields, or forward reference like queuePluginTrial does.

♻️ Proposed narrowing
-  { openInNewChat = false, prompt }: PluginTrialOptions = {}
+  { openInNewChat = false, prompt }: Pick<PluginTrialOptions, 'openInNewChat' | 'prompt'> = {}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/features/plugins/pluginTrial.ts` around lines 267 - 281, Update
queuePluginInputTrial so its options parameter type only exposes the supported
openInNewChat and prompt fields, preventing callers from passing the ignored
reference option; keep the existing queuePendingPluginTrial behavior unchanged.
wework/src/features/plugins/pluginTrial.test.ts (1)

196-205: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider asserting the derived templates.

The new path passes prompt ?? normalizedInput into pluginTrialTemplates. When no prompt is given, the whole Markdown link becomes the selected use case. Add an assertion on trial?.templates to lock this behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/features/plugins/pluginTrial.test.ts` around lines 196 - 205,
Extend the “queues a custom plugin trial input for a fresh chat” test to assert
trial?.templates, verifying that when no prompt is provided the derived template
uses the full normalized Markdown-link input as the selected use case.
wework/src/pages/SitesPage.tsx (1)

327-387: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Simplify the redundant alias and shorten the function.

plugin is only an alias of locallyInstalledPlugin and adds no meaning. The function is also longer than the preferred 50-line limit. Remove the alias, and consider extracting the target-device resolution into a helper.

As per coding guidelines: "functions should remain focused, preferably under 50 lines."

♻️ Proposed cleanup
-    const plugin = locallyInstalledPlugin
-    if (!plugin) {
+    if (!locallyInstalledPlugin) {
       setCreateNotice(t('plugin_installing', '正在安装应用插件,完成后将进入会话...'))
     }
-    const prepared = plugin
-      ? { plugin, sync: null }
+    const prepared = locallyInstalledPlugin
+      ? { plugin: locallyInstalledPlugin, sync: null }
       : await pluginApi.ensureBuiltinPluginInstalled(createStrategy.pluginName, {
           deviceId: targetDeviceId,
         })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/pages/SitesPage.tsx` around lines 327 - 387, Remove the redundant
plugin alias in prepareApplicationPlugin and use locallyInstalledPlugin
directly. Extract target-device resolution and its unavailable-device error
handling into a focused helper, then call it from prepareApplicationPlugin so
the function is reduced below the preferred 50-line limit while preserving
existing behavior.

Source: Coding guidelines

wework/src/lib/link-preview.test.ts (1)

70-79: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add negative and decoding cases for the new recognizer.

The test covers only the happy path. WegentSitesProjectRecognizer also rejects an empty project ID and decodes percent-encoded identifiers. Add cases for wegent-sites-project:// and for an encoded ID so both branches stay covered.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/lib/link-preview.test.ts` around lines 70 - 79, Add tests
alongside the existing Wegent Sites project link test for
WegentSitesProjectRecognizer rejecting the empty URL `wegent-sites-project://`
and decoding a percent-encoded project identifier. Assert the empty case is
unrecognized and the encoded case produces the decoded label while preserving
the expected provider, URL, icon, and abbreviation behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@wework/e2e/desktop/modules/desktop-server.mjs`:
- Line 901: Update the desktop Sites fixture payloads used by the /api/sites
mock to include the required project_id field in both web and mini-program
responses, and add custom_domain_prefix to the web payload. Keep the existing
capabilities and other fixture values unchanged while matching the backend site
response contract.

In `@wework/src/components/sites/ApplicationRows.tsx`:
- Around line 128-141: Update the continue-development button in ApplicationRows
to use a responsive height that provides at least a 44px touch target on mobile
while preserving the existing compact height at larger breakpoints. Keep the
button’s other styling and behavior unchanged.

In `@wework/src/components/sites/EditSiteDialog.tsx`:
- Around line 77-99: Increase mobile touch targets across the affected controls:
in wework/src/components/sites/EditSiteDialog.tsx lines 77-99, apply h-11 to
both inputs and restore compact height with an md: class; in lines 109-127,
apply h-11 min-w-11 to both buttons with md: overrides; and in
wework/src/components/sites/SiteActionsMenu.tsx lines 72-78, apply h-11 w-11 to
the menu trigger with md: overrides. Update the relevant input and button
className values while preserving existing styling.

In `@wework/src/pages/SitesPage.tsx`:
- Around line 461-466: Update the input-missing branch in SitesPage’s
buildSiteContinueDevelopmentInput flow to use a dedicated translation key
describing the missing site project identifier, rather than the plugin
configuration synchronization message. Add the corresponding English and
Simplified Chinese entries under the Wework sites locale namespace, then pass
that key to setCreateError while preserving the existing early return.
- Around line 453-454: Update handleContinueDevelopment and handleCreate to
guard against the other flow’s active state: handleContinueDevelopment must also
reject when creatingType is set, and handleCreate must also reject when
continuingSiteId is set. Preserve each flow’s existing own-state guard and
ensure both flows cannot queue trials, navigate, or clear createNotice
concurrently.

---

Nitpick comments:
In `@wework/src/components/chat/composer/composerLinks.ts`:
- Around line 15-18: Replace the MARKDOWN_LINK_REGEX RegExp constructor with an
equivalent regex literal, preserving the current matching behavior and global,
case-insensitive flags.
- Around line 15-18: The URI-scheme pattern is duplicated across three locations
and must be centralized. In
wework/src/components/chat/composer/composerLinks.ts:15-18, export a shared
scheme-pattern constant and build MARKDOWN_LINK_REGEX from it; in
wework/src/components/chat/MessageList.tsx:1700, build COMPOSER_LINK_PATTERN
from that constant and preserve or explicitly align the optional “!” handling;
in wework/src/components/chat/AssistantMarkdown.tsx:183-187, replace the inline
scheme test with a helper using the shared constant.

In `@wework/src/features/plugins/pluginTrial.test.ts`:
- Around line 196-205: Extend the “queues a custom plugin trial input for a
fresh chat” test to assert trial?.templates, verifying that when no prompt is
provided the derived template uses the full normalized Markdown-link input as
the selected use case.

In `@wework/src/features/plugins/pluginTrial.ts`:
- Around line 267-281: Update queuePluginInputTrial so its options parameter
type only exposes the supported openInNewChat and prompt fields, preventing
callers from passing the ignored reference option; keep the existing
queuePendingPluginTrial behavior unchanged.

In `@wework/src/lib/link-preview.test.ts`:
- Around line 70-79: Add tests alongside the existing Wegent Sites project link
test for WegentSitesProjectRecognizer rejecting the empty URL
`wegent-sites-project://` and decoding a percent-encoded project identifier.
Assert the empty case is unrecognized and the encoded case produces the decoded
label while preserving the expected provider, URL, icon, and abbreviation
behavior.

In `@wework/src/pages/SitesPage.tsx`:
- Around line 327-387: Remove the redundant plugin alias in
prepareApplicationPlugin and use locallyInstalledPlugin directly. Extract
target-device resolution and its unavailable-device error handling into a
focused helper, then call it from prepareApplicationPlugin so the function is
reduced below the preferred 50-line limit while preserving existing behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a0f70086-ce2f-4351-a25d-3de5ada1b04e

📥 Commits

Reviewing files that changed from the base of the PR and between 7937acd and bcfd526.

📒 Files selected for processing (32)
  • backend/app/api/endpoints/sites.py
  • backend/app/schemas/site.py
  • backend/app/services/site_application_types.py
  • backend/app/services/sites.py
  • backend/tests/api/test_sites_api.py
  • docs/en/wework/developer-guide/wework-codex-plugins.md
  • docs/zh/wework/developer-guide/wework-codex-plugins.md
  • wework/e2e/desktop/modules/desktop-server.mjs
  • wework/e2e/utils/mock-sites-upstream-server.mjs
  • wework/src/App.plugins.test.tsx
  • wework/src/api/sites.test.ts
  • wework/src/api/sites.ts
  • wework/src/components/chat/AssistantMarkdown.tsx
  • wework/src/components/chat/MessageList.test.tsx
  • wework/src/components/chat/MessageList.tsx
  • wework/src/components/chat/composer/ComposerProseMirrorEditor.test.tsx
  • wework/src/components/chat/composer/composerLinks.ts
  • wework/src/components/sites/ApplicationRows.tsx
  • wework/src/components/sites/EditSiteDialog.tsx
  • wework/src/components/sites/SiteActionsMenu.tsx
  • wework/src/components/sites/SitesWorkspace.test.tsx
  • wework/src/components/sites/SitesWorkspace.tsx
  • wework/src/components/sites/applicationTypeDefinitions.test.tsx
  • wework/src/components/sites/applicationTypeDefinitions.tsx
  • wework/src/features/plugins/pluginTrial.test.ts
  • wework/src/features/plugins/pluginTrial.ts
  • wework/src/i18n/locales/en/sites.json
  • wework/src/i18n/locales/zh-CN/sites.json
  • wework/src/lib/link-preview.test.ts
  • wework/src/lib/link-preview.ts
  • wework/src/pages/SitesPage.tsx
  • wework/src/telemetry/events.ts

enabled: true,
order: 10,
capabilities: ['create', 'publish', 'delete'],
capabilities: ['create', 'publish', 'edit', 'delete'],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Keep the desktop Sites fixture aligned with the API response contract.

backend/app/schemas/site.py now requires project_id for web and mini-program responses. The /api/sites fixture omits this field from both payloads. The web payload also omits custom_domain_prefix. Add these fields so desktop tests use the same contract as the Backend.

Proposed fixture update
 {
   app_type: 'miniapp',
   siteid: 'prj_e2e_mini',
+  project_id: 'prj_e2e_mini',
   taskid: 'prj_e2e_mini',
 }
 
 {
   app_type: 'web',
   siteid: 'prj_e2e_product',
+  project_id: 'prj_e2e_product',
   taskid: 'prj_e2e_product',
+  custom_domain_prefix: null,
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
capabilities: ['create', 'publish', 'edit', 'delete'],
{
app_type: 'miniapp',
siteid: 'prj_e2e_mini',
project_id: 'prj_e2e_mini',
taskid: 'prj_e2e_mini',
}
{
app_type: 'web',
siteid: 'prj_e2e_product',
project_id: 'prj_e2e_product',
taskid: 'prj_e2e_product',
custom_domain_prefix: null,
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/e2e/desktop/modules/desktop-server.mjs` at line 901, Update the
desktop Sites fixture payloads used by the /api/sites mock to include the
required project_id field in both web and mini-program responses, and add
custom_domain_prefix to the web payload. Keep the existing capabilities and
other fixture values unchanged while matching the backend site response
contract.

Comment on lines +128 to +141
<button
type="button"
data-testid={`site-continue-development-${site.siteid}`}
disabled={deleting || continuing}
onClick={() => context.onContinueDevelopment(site)}
className="flex h-8 shrink-0 items-center gap-1.5 rounded-lg border border-border bg-background px-3 text-sm font-medium text-text-primary transition-colors hover:bg-surface focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-focus/30 disabled:cursor-default disabled:text-text-secondary disabled:opacity-70"
>
{continuing ? (
<Loader2 className="h-3.5 w-3.5 animate-spin" aria-hidden="true" />
) : (
<Code2 className="h-3.5 w-3.5" aria-hidden="true" />
)}
{t('continue_development', '继续开发')}
</button>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Increase the mobile touch target for the new continue-development button.

The button uses a fixed 32px height (h-8). On mobile the row is a single column and this control is reachable by touch. The design rules require at least 44px × 44px for mobile controls. Use a responsive height.

As per coding guidelines: "Mobile controls must be at least 44px × 44px."

♿ Proposed responsive height
-          className="flex h-8 shrink-0 items-center gap-1.5 rounded-lg border border-border bg-background px-3 text-sm font-medium text-text-primary transition-colors hover:bg-surface focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-focus/30 disabled:cursor-default disabled:text-text-secondary disabled:opacity-70"
+          className="flex h-11 min-w-[44px] shrink-0 items-center gap-1.5 rounded-lg border border-border bg-background px-3 text-sm font-medium text-text-primary transition-colors hover:bg-surface focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-focus/30 disabled:cursor-default disabled:text-text-secondary disabled:opacity-70 md:h-8"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<button
type="button"
data-testid={`site-continue-development-${site.siteid}`}
disabled={deleting || continuing}
onClick={() => context.onContinueDevelopment(site)}
className="flex h-8 shrink-0 items-center gap-1.5 rounded-lg border border-border bg-background px-3 text-sm font-medium text-text-primary transition-colors hover:bg-surface focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-focus/30 disabled:cursor-default disabled:text-text-secondary disabled:opacity-70"
>
{continuing ? (
<Loader2 className="h-3.5 w-3.5 animate-spin" aria-hidden="true" />
) : (
<Code2 className="h-3.5 w-3.5" aria-hidden="true" />
)}
{t('continue_development', '继续开发')}
</button>
<button
type="button"
data-testid={`site-continue-development-${site.siteid}`}
disabled={deleting || continuing}
onClick={() => context.onContinueDevelopment(site)}
className="flex h-11 min-w-[44px] shrink-0 items-center gap-1.5 rounded-lg border border-border bg-background px-3 text-sm font-medium text-text-primary transition-colors hover:bg-surface focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-focus/30 disabled:cursor-default disabled:text-text-secondary disabled:opacity-70 md:h-8"
>
{continuing ? (
<Loader2 className="h-3.5 w-3.5 animate-spin" aria-hidden="true" />
) : (
<Code2 className="h-3.5 w-3.5" aria-hidden="true" />
)}
{t('continue_development', '继续开发')}
</button>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/components/sites/ApplicationRows.tsx` around lines 128 - 141,
Update the continue-development button in ApplicationRows to use a responsive
height that provides at least a 44px touch target on mobile while preserving the
existing compact height at larger breakpoints. Keep the button’s other styling
and behavior unchanged.

Source: Coding guidelines

Comment on lines +77 to +99
<input
ref={titleInputRef}
value={title}
onChange={event => setTitle(event.target.value)}
data-testid="site-edit-title-input"
disabled={loading}
maxLength={255}
className="mt-1 h-9 w-full rounded-lg border border-border bg-background px-3 text-sm text-text-primary outline-none transition-colors placeholder:text-text-muted focus:border-focus focus:ring-2 focus:ring-focus/15 disabled:cursor-wait disabled:opacity-60"
/>
</label>
<label className="block">
<span className="text-xs font-medium text-text-secondary">
{t('edit_domain_prefix_label', '自定义域名前缀')}
</span>
<input
value={customDomainPrefix}
onChange={event => setCustomDomainPrefix(event.target.value.toLowerCase())}
data-testid="site-edit-domain-prefix-input"
disabled={loading}
maxLength={63}
placeholder={t('edit_domain_prefix_placeholder', '只允许小写字母、数字、短横线')}
className="mt-1 h-9 w-full rounded-lg border border-border bg-background px-3 text-sm text-text-primary outline-none transition-colors placeholder:text-text-muted focus:border-focus focus:ring-2 focus:ring-focus/15 disabled:cursor-wait disabled:opacity-60"
/>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Increase mobile touch targets to 44px.

The new edit controls do not meet the required mobile touch-target size. This can prevent reliable interaction on touch devices.

  • wework/src/components/sites/EditSiteDialog.tsx#L77-L99: use h-11 for both inputs on mobile, then restore compact sizing with an md: class.
  • wework/src/components/sites/EditSiteDialog.tsx#L109-L127: use h-11 min-w-11 for both buttons on mobile, then restore compact sizing with md: classes.
  • wework/src/components/sites/SiteActionsMenu.tsx#L72-L78: use h-11 w-11 for the menu trigger on mobile, then restore compact sizing with md: classes.

As per coding guidelines: “Mobile controls must be at least 44px × 44px.”

📍 Affects 2 files
  • wework/src/components/sites/EditSiteDialog.tsx#L77-L99 (this comment)
  • wework/src/components/sites/EditSiteDialog.tsx#L109-L127
  • wework/src/components/sites/SiteActionsMenu.tsx#L72-L78
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/components/sites/EditSiteDialog.tsx` around lines 77 - 99,
Increase mobile touch targets across the affected controls: in
wework/src/components/sites/EditSiteDialog.tsx lines 77-99, apply h-11 to both
inputs and restore compact height with an md: class; in lines 109-127, apply
h-11 min-w-11 to both buttons with md: overrides; and in
wework/src/components/sites/SiteActionsMenu.tsx lines 72-78, apply h-11 w-11 to
the menu trigger with md: overrides. Update the relevant input and button
className values while preserving existing styling.

Source: Coding guidelines

Comment on lines +453 to +454
if (continuingSiteId) return
setContinuingSiteId(site.siteid)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Guard the continuation flow against a concurrent creation flow.

handleContinueDevelopment checks only continuingSiteId, and handleCreate checks only creatingType. The two flows can run at the same time. Both write to the same plugin-trial sessionStorage key through queuePendingPluginTrial, so the second write overwrites the first and one queued trial is lost. Both flows also call navigateTo('/') and clear createNotice in their finally blocks, so the surviving notice state is nondeterministic. Make each flow reject while the other is active.

🐛 Proposed guards
   const handleContinueDevelopment = async (
     site: Site,
     createStrategy: ApplicationCreateStrategy
   ) => {
-    if (continuingSiteId) return
+    if (continuingSiteId || creatingType) return
     setContinuingSiteId(site.siteid)
   const handleCreate = async (appType: SiteAppType, createStrategy: ApplicationCreateStrategy) => {
-    if (creatingType) return
+    if (creatingType || continuingSiteId) return
     setCreatingType(appType)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/pages/SitesPage.tsx` around lines 453 - 454, Update
handleContinueDevelopment and handleCreate to guard against the other flow’s
active state: handleContinueDevelopment must also reject when creatingType is
set, and handleCreate must also reject when continuingSiteId is set. Preserve
each flow’s existing own-state guard and ensure both flows cannot queue trials,
navigate, or clear createNotice concurrently.

Comment on lines +461 to 466
if (!input) {
setCreateError(
t('plugin_device_sync_failed', '应用插件未能同步到目标设备,请检查设备后重试')
t('plugin_create_configuration_missing', '应用创建插件配置尚未同步,请刷新后重试')
)
} else {
setCreateError(t('plugin_install_failed', '应用插件安装失败,请重试'))
return
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use a message that matches the failure.

buildSiteContinueDevelopmentInput returns null only when the site has neither project_id nor siteid. The current message reports a plugin configuration problem and tells the user to refresh. Refreshing cannot fix a site without a project identifier. Add a dedicated key to both wework/src/i18n/locales/en/sites.json and wework/src/i18n/locales/zh-CN/sites.json, then use it here.

As per coding guidelines: "Add new copy to the appropriate Wework namespace in both src/i18n/locales/en/ and src/i18n/locales/zh-CN/."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/pages/SitesPage.tsx` around lines 461 - 466, Update the
input-missing branch in SitesPage’s buildSiteContinueDevelopmentInput flow to
use a dedicated translation key describing the missing site project identifier,
rather than the plugin configuration synchronization message. Add the
corresponding English and Simplified Chinese entries under the Wework sites
locale namespace, then pass that key to setCreateError while preserving the
existing early return.

Source: Coding guidelines

@qdaxb
qdaxb added this pull request to the merge queue Aug 12, 2026
Merged via the queue into wecode-ai:main with commit a8a2e86 Aug 12, 2026
68 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants