Skip to content

fix: workspace plugin identity for application creation - #2481

Merged
qdaxb merged 4 commits into
wecode-ai:mainfrom
earthAlone2026:fix/wework-sites-create
Aug 7, 2026
Merged

qdaxb merged 4 commits into
wecode-ai:mainfrom
earthAlone2026:fix/wework-sites-create

Conversation

@earthAlone2026

@earthAlone2026 earthAlone2026 commented Aug 7, 2026 •

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Application types now provide server-driven plugin and marketplace configuration.
    • Site and mini-app creation reuses or installs plugins on the selected device, with synchronization confirmation and progress notices.
    • Added workspace marketplace support and improved marketplace identification.
    • Composer plugin lists now update correctly when available apps change.
  • Bug Fixes

    • Plugin references now use the correct marketplace across installations and trials.
    • Uninstall messaging clarifies that runtime records and local login state are removed while reusable caches remain.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The change moves application plugin creation metadata to backend descriptors, derives marketplace identity from plugin visibility, and updates Wework to cache descriptors, prepare plugins on target devices, confirm synchronization, show installation progress, and clear stale composer apps.

Changes

Application plugin creation and marketplace integration

Layer / File(s) Summary
Backend descriptors and marketplace identity
backend/app/schemas/site.py, backend/app/services/*, backend/tests/*, docs/*
Backend descriptors include plugin and marketplace creation metadata. Built-in plugins use workspace visibility. Marketplace names derive from visibility during installation, migration, payload creation, and reconciliation.
Descriptor resolution and marketplace references
wework/src/api/sites.ts, wework/src/components/sites/*, wework/src/features/plugins/*
Wework validates and caches backend descriptors. Managed plugin references resolve marketplace names from visibility, including the wework alias.
Target-device application creation
wework/src/pages/SitesPage.tsx, wework/src/components/sites/*, wework/e2e/*, wework/src/App.plugins.test.tsx
Application creation validates plugin metadata, reuses or installs the plugin on the target device, confirms synchronization, queues the plugin reference, and displays installation progress.
Composer synchronization and runtime support
wework/src/components/chat/composer/*, wework/src/features/workbench/*, wework/src/features/cloud-connection/*, wework/src/App.tsx, scripts/*, backend/init_data/README.md
Composer state can represent an explicit empty inventory and suppress empty republishing. Workbench refreshes clear stale apps after plugin state changes. Runtime wiring, localization, staging data, documentation, and tests reflect the updated behavior.

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

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant SitesWorkspace
  participant SitesPage
  participant TargetDevice
  participant PluginService
  User->>SitesWorkspace: select application type
  SitesWorkspace->>SitesPage: submit create strategy
  SitesPage->>TargetDevice: check plugin installation
  TargetDevice-->>SitesPage: installed or missing
  SitesPage->>PluginService: install and synchronize when missing
  PluginService-->>SitesPage: synchronization result
  SitesPage->>SitesWorkspace: show progress and create application
Loading

Possibly related PRs

  • wecode-ai/Wegent#1844: Both changes modify marketplace installation, visibility-derived marketplace identity, and installed-plugin handling.
  • wecode-ai/Wegent#2228: This change extends the Sites built-in-plugin installation flow.
  • wecode-ai/Wegent#2406: This change extends application-type creation metadata and built-in-plugin identity handling.

Suggested reviewers: qdaxb, ficohu

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.14% 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 clearly summarizes the main change: correcting workspace plugin identity handling during application creation.
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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
backend/app/services/installed_plugin_service.py (1)

382-391: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Normalize legacy built-in visibility before installation.

install_builtin_plugin accepts public, but install_marketplace_plugin maps that visibility to wework. The descriptors in backend/tests/api/test_sites_api.py advertise wegent, and wework/src/pages/SitesPage.tsx matches installed application plugins by that identity. A stale public row can therefore produce an installation that the application flow does not recognize.

Use the registry's canonical workspace visibility for built-ins, or pass wegent explicitly. Add a regression test with a public legacy row and no bootstrap synchronization.

🤖 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 `@backend/app/services/installed_plugin_service.py` around lines 382 - 391,
Update install_builtin_plugin in the built-in installation path to normalize
legacy public visibility to the registry’s canonical workspace/wegent identity
before calling install_marketplace_plugin, while preserving rejection of
unsupported visibility values. Add a regression test covering a public legacy
row without bootstrap synchronization and verify the resulting installed plugin
is recognized by the application flow.
wework/e2e/desktop/task-flow.e2e.mjs (1)

5801-5838: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

The installed fixture never exercises the plugin-reuse path.

installedMiniProgramPlugin() returns status: { state: 'Available' } with no devices array. isPluginInstalledOnDevice in wework/src/pages/SitesPage.tsx requires a status.devices entry with deviceId === targetDeviceId and state: 'installed'. The E2E therefore always takes the install branch and never covers the new "reuse the plugin already installed on the target device" branch, which skips the ensure-installed request.

Add a devices entry to the fixture and assert a second creation attempt that sends no ensure-installed request.

💚 Proposed fixture change
-    status: { state: 'Available' },
+    status: {
+      state: 'Available',
+      devices: [
+        {
+          deviceId: 'local-device',
+          desiredReleaseId: 1,
+          actualReleaseId: 1,
+          state: 'installed',
+          attemptCount: 1,
+          updatedAt: '2026-07-22T00:00:00Z',
+        },
+      ],
+    },

Based on the coding guideline "Changes affecting core user flows must add or update automated E2E regression coverage in the same change."

🤖 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/task-flow.e2e.mjs` around lines 5801 - 5838, Update
installedMiniProgramPlugin() so status.devices contains the target device with
state 'installed', allowing isPluginInstalledOnDevice to take the reuse path.
Extend the E2E scenario to perform a second creation attempt for that device and
assert that no ensure-installed request is sent.

Source: Coding guidelines

🧹 Nitpick comments (1)
wework/src/features/plugins/pluginTrial.test.ts (1)

161-173: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for personal visibility.

The new tests cover workspace and public. The personal branch of marketplaceNameForVisibility returns wework-personal and stays untested in this file and in composerPluginMetadata.test.ts. A regression in that branch would break personal plugin mentions without failing any test.

💚 Proposed additional test
+  test('falls back to the personal marketplace for personal managed installs', () => {
+    const plugin = pluginWithSkill()
+    plugin.metadata.namespace = 'default'
+    plugin.spec.visibility = 'personal'
+    plugin.spec.source = {
+      type: 'marketplace',
+      providerKey: 'wegent-market',
+      pluginKey: 'documents',
+    }
+    plugin.spec.sourcePayload = { filename: 'documents.zip' }
+
+    expect(pluginTrialInput(plugin)).toBe('[$Documents](plugin://documents@wework-personal) ')
+  })
🤖 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 161 - 173, Add
test coverage for personal visibility in pluginTrial.test.ts and
composerPluginMetadata.test.ts, using the existing marketplace-plugin test
patterns and setting visibility to personal. Assert that
marketplaceNameForVisibility resolves to wework-personal in the generated plugin
mention or metadata, while preserving the existing workspace and public cases.
🤖 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 `@backend/app/services/plugin_marketplace_service.py`:
- Line 2385: Update _reconcile_installed_kind_catalog_ref so a visibility-only
marketplace change is not treated as a no-op: include the expected marketplace
from marketplace_name_for_visibility(plugin.visibility) in the equality guard,
or apply normalization before returning. Add a regression test covering a
public-to-workspace visibility change and verifying the persisted marketplace
changes from wework to wegent.

In `@wework/src/components/sites/useApplicationTypeDefinitions.ts`:
- Around line 55-60: Update readCachedApplicationTypes to validate every parsed
items entry before returning it as ApplicationTypeDescriptor: require each
descriptor to be a non-null object and ensure optional create.plugin_name and
create.marketplace_name fields are strings when present. Return null for invalid
cached data, and only cast the array after all entries pass validation.

In `@wework/src/features/plugins/pluginTrial.ts`:
- Around line 73-90: Extract the shared marketplace identity logic into
wework/src/features/plugins/pluginMarketplaceIdentity.ts: export
marketplaceNameForVisibility and managedMarketplaceName, including the existing
provider-key validation and visibility fallback. In
wework/src/features/plugins/pluginTrial.ts lines 73-90, remove the local helpers
and import the shared exports; do the same in
wework/src/features/plugins/composerPluginMetadata.ts lines 85-102. In
wework/src/pages/SitesPage.tsx lines 52-75, remove the local visibility mapper
and replace the inlined provider-key check in installedPluginMarketplaces with
managedMarketplaceName(plugin).

In `@wework/src/pages/SitesPage.tsx`:
- Around line 176-191: Guard the sync.results access in the plugin sync
evaluation before calling find, treating a missing results collection as having
no matching device result. Preserve the existing targetResult and fallback sync
validation behavior while preventing the TypeError in the surrounding sync
handling flow.

---

Outside diff comments:
In `@backend/app/services/installed_plugin_service.py`:
- Around line 382-391: Update install_builtin_plugin in the built-in
installation path to normalize legacy public visibility to the registry’s
canonical workspace/wegent identity before calling install_marketplace_plugin,
while preserving rejection of unsupported visibility values. Add a regression
test covering a public legacy row without bootstrap synchronization and verify
the resulting installed plugin is recognized by the application flow.

In `@wework/e2e/desktop/task-flow.e2e.mjs`:
- Around line 5801-5838: Update installedMiniProgramPlugin() so status.devices
contains the target device with state 'installed', allowing
isPluginInstalledOnDevice to take the reuse path. Extend the E2E scenario to
perform a second creation attempt for that device and assert that no
ensure-installed request is sent.

---

Nitpick comments:
In `@wework/src/features/plugins/pluginTrial.test.ts`:
- Around line 161-173: Add test coverage for personal visibility in
pluginTrial.test.ts and composerPluginMetadata.test.ts, using the existing
marketplace-plugin test patterns and setting visibility to personal. Assert that
marketplaceNameForVisibility resolves to wework-personal in the generated plugin
mention or metadata, while preserving the existing workspace and public cases.
🪄 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: 31aa2822-5b4b-4d2d-92ea-16dfd893a164

📥 Commits

Reviewing files that changed from the base of the PR and between b30058e and e312ecd.

📒 Files selected for processing (44)
  • backend/app/schemas/site.py
  • backend/app/services/builtin_plugin_registry.py
  • backend/app/services/installed_plugin_service.py
  • backend/app/services/plugin_marketplace_identity.py
  • backend/app/services/plugin_marketplace_migration_service.py
  • backend/app/services/plugin_marketplace_service.py
  • backend/app/services/site_application_types.py
  • backend/init_data/README.md
  • backend/tests/api/test_sites_api.py
  • backend/tests/services/test_installed_plugin_upload.py
  • backend/tests/services/test_plugin_marketplace_v2.py
  • docs/en/wework/developer-guide/plugin-marketplace-v2.md
  • docs/en/wework/developer-guide/wework-codex-plugins.md
  • docs/en/wework/plugins-and-skills.md
  • docs/zh/wework/developer-guide/plugin-marketplace-v2.md
  • docs/zh/wework/developer-guide/wework-codex-plugins.md
  • docs/zh/wework/plugins-and-skills.md
  • scripts/builtin-plugin-staging.mjs
  • wework/e2e/desktop/task-flow.e2e.mjs
  • wework/src/App.plugins.test.tsx
  • wework/src/App.tsx
  • wework/src/api/sites.test.ts
  • wework/src/api/sites.ts
  • wework/src/components/plugins/PluginsWorkspace.test.tsx
  • wework/src/components/plugins/plugin-dialogs/UninstallPluginDialog.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/components/sites/useApplicationTypeDefinitions.ts
  • wework/src/features/cloud-connection/CloudConnectionProvider.test.tsx
  • wework/src/features/cloud-connection/CloudConnectionProvider.tsx
  • wework/src/features/plugins/builtinPlugins.ts
  • wework/src/features/plugins/composerPluginMetadata.test.ts
  • wework/src/features/plugins/composerPluginMetadata.ts
  • wework/src/features/plugins/pluginNavigation.test.ts
  • wework/src/features/plugins/pluginNavigation.ts
  • wework/src/features/plugins/pluginTrial.test.ts
  • wework/src/features/plugins/pluginTrial.ts
  • wework/src/i18n/locales/en/common.json
  • wework/src/i18n/locales/en/sites.json
  • wework/src/i18n/locales/zh-CN/common.json
  • wework/src/i18n/locales/zh-CN/sites.json
  • wework/src/pages/SitesPage.tsx
💤 Files with no reviewable changes (1)
  • wework/src/features/plugins/builtinPlugins.ts

Comment thread wework/src/pages/SitesPage.tsx Resolved

@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.

🧹 Nitpick comments (2)
wework/src/features/workbench/WorkbenchProvider.tsx (2)

1664-1666: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

The in-flight dedup discards allowEmptySnapshot.

Lines 1664-1666 return the pending promise before options is read. If a plain listLocalApps() load is in flight when a caller passes allowEmptySnapshot: true, the caller receives the earlier promise. That promise was created without the option, so it takes the lines 1743-1748 branch and keeps the stale non-empty snapshot instead of calling replaceComposerApps([]). The picker then keeps showing uninstalled plugins.

Today the only allowEmptySnapshot caller is line 1787, and the handler nulls localAppsInflightRef.current at line 1782 immediately before it. So the path is not currently reachable. The correctness of the new option depends on an unrelated line in a different function. Make the dedup honor the stronger request instead.

♻️ Proposed guard so an allow-empty request is not deduped into a weaker load
       const cached = localAppsCacheRef.current
       if (cached && cached.expiresAt > Date.now()) {
         return cached.apps
       }
-      if (localAppsInflightRef.current) {
+      // An allow-empty request must not reuse a load that cannot clear the
+      // shared snapshot; start a fresh load instead.
+      if (localAppsInflightRef.current && !options?.allowEmptySnapshot) {
         return localAppsInflightRef.current
       }
🤖 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/workbench/WorkbenchProvider.tsx` around lines 1664 -
1666, Update the in-flight deduplication around localAppsInflightRef so a
request with allowEmptySnapshot: true is not returned from a promise created for
a weaker request. Track whether the pending load supports allowEmptySnapshot,
and only reuse it when it satisfies the current options; otherwise start a new
load that preserves the empty-snapshot replacement behavior.

1686-1722: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the connector-app synchronization block.

listLocalApps now spans lines 1658-1767, about 110 lines. The connector block at lines 1686-1722 is self-contained: it reads cloudConnection, calls listWegentInstalledConnectorApps, syncs through requestLocalExecutor, and maps the result to LocalDeviceApp[]. Move it into a helper such as loadWegentConnectorApps(apiBaseUrl, token) in the plugins feature folder. The remaining body then reads as load, merge, publish.

The coding guidelines require functions to stay focused and preferably under 50 lines.

As per coding guidelines: "Comments must be in English, names must be clear, and functions should remain focused, preferably under 50 lines."

🤖 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/workbench/WorkbenchProvider.tsx` around lines 1686 -
1722, Extract the self-contained connector synchronization logic from
listLocalApps into a focused helper such as loadWegentConnectorApps(apiBaseUrl,
token) in the plugins feature folder. Move the API fetch, runtime sync,
LocalDeviceApp mapping, and error handling into that helper, then have
listLocalApps only load, merge, and publish the returned apps while preserving
the existing connection checks and deduplication behavior.

Source: Coding guidelines

🤖 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.

Nitpick comments:
In `@wework/src/features/workbench/WorkbenchProvider.tsx`:
- Around line 1664-1666: Update the in-flight deduplication around
localAppsInflightRef so a request with allowEmptySnapshot: true is not returned
from a promise created for a weaker request. Track whether the pending load
supports allowEmptySnapshot, and only reuse it when it satisfies the current
options; otherwise start a new load that preserves the empty-snapshot
replacement behavior.
- Around line 1686-1722: Extract the self-contained connector synchronization
logic from listLocalApps into a focused helper such as
loadWegentConnectorApps(apiBaseUrl, token) in the plugins feature folder. Move
the API fetch, runtime sync, LocalDeviceApp mapping, and error handling into
that helper, then have listLocalApps only load, merge, and publish the returned
apps while preserving the existing connection checks and deduplication behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7eca3df3-33d5-48b9-a739-abfe42693126

📥 Commits

Reviewing files that changed from the base of the PR and between e312ecd and eed909d.

📒 Files selected for processing (8)
  • wework/e2e/desktop/task-flow.e2e.mjs
  • wework/src/components/chat/composer/ComposerTextarea.tsx
  • wework/src/components/chat/composer/PluginPickerMenu.test.tsx
  • wework/src/components/chat/composer/PluginPickerMenu.tsx
  • wework/src/components/chat/composer/composerAppsSnapshot.test.ts
  • wework/src/components/chat/composer/composerAppsSnapshot.ts
  • wework/src/features/workbench/WorkbenchProvider.test.tsx
  • wework/src/features/workbench/WorkbenchProvider.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • wework/e2e/desktop/task-flow.e2e.mjs

@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: 2

🧹 Nitpick comments (1)
backend/tests/services/test_installed_plugin_upload.py (1)

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

Add types to the test signature.

Annotate test_db, test_user, and the None return type. Python guidelines require type hints.

As per coding guidelines, “Python code must follow PEP 8, Black with 88-column formatting, isort, and type hints.”

🤖 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 `@backend/tests/services/test_installed_plugin_upload.py` at line 498, Add type
annotations to the test_install_builtin_plugin_normalizes_legacy_public_row
signature for test_db, test_user, and its None return type, using the
established fixture types from nearby tests.

Source: Coding guidelines

🤖 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 `@docs/zh/wework/developer-guide/wework-codex-plugins.md`:
- Line 53: Update the application creation flow to derive the built-in
installation endpoint, plugin name, and plugin:// reference from the
application-type descriptor rather than hardcoded wegent-sites or
weibo-miniapp-h5-develop-agent branches. Reuse the descriptor’s
create.plugin_name and create.marketplace_name values for installation and task
creation, and remove the application-specific branching while preserving the
existing device sync validation and default-prompt behavior.

In `@wework/src/features/plugins/pluginMarketplaceIdentity.ts`:
- Around line 16-19: Update managedMarketplaceName so unrecognized
plugin.spec.visibility returns null instead of falling back to 'wegent'.
Preserve the existing providerKey eligibility check and recognized visibility
mappings, allowing downstream consumers to use explicit
plugin.spec.source.marketplace metadata.

---

Nitpick comments:
In `@backend/tests/services/test_installed_plugin_upload.py`:
- Line 498: Add type annotations to the
test_install_builtin_plugin_normalizes_legacy_public_row signature for test_db,
test_user, and its None return type, using the established fixture types from
nearby tests.
🪄 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: c65332fc-5939-4f38-bfe0-25c773d54f3d

📥 Commits

Reviewing files that changed from the base of the PR and between eed909d and 3fbe299.

📒 Files selected for processing (19)
  • backend/app/services/installed_plugin_service.py
  • backend/app/services/plugin_marketplace_service.py
  • backend/tests/services/test_installed_plugin_upload.py
  • backend/tests/services/test_plugin_marketplace_v2.py
  • docs/en/wework/developer-guide/plugin-marketplace-v2.md
  • docs/en/wework/developer-guide/wework-codex-plugins.md
  • docs/en/wework/plugins-and-skills.md
  • docs/zh/wework/developer-guide/plugin-marketplace-v2.md
  • docs/zh/wework/developer-guide/wework-codex-plugins.md
  • docs/zh/wework/plugins-and-skills.md
  • wework/e2e/desktop/task-flow.e2e.mjs
  • wework/src/App.plugins.test.tsx
  • wework/src/components/sites/useApplicationTypeDefinitions.ts
  • wework/src/features/plugins/composerPluginMetadata.test.ts
  • wework/src/features/plugins/composerPluginMetadata.ts
  • wework/src/features/plugins/pluginMarketplaceIdentity.ts
  • wework/src/features/plugins/pluginTrial.test.ts
  • wework/src/features/plugins/pluginTrial.ts
  • wework/src/pages/SitesPage.tsx
🚧 Files skipped from review as they are similar to previous changes (13)
  • backend/app/services/plugin_marketplace_service.py
  • docs/en/wework/plugins-and-skills.md
  • backend/tests/services/test_plugin_marketplace_v2.py
  • wework/src/features/plugins/pluginTrial.test.ts
  • wework/src/features/plugins/composerPluginMetadata.test.ts
  • wework/src/components/sites/useApplicationTypeDefinitions.ts
  • wework/src/features/plugins/pluginTrial.ts
  • wework/src/features/plugins/composerPluginMetadata.ts
  • backend/app/services/installed_plugin_service.py
  • wework/e2e/desktop/task-flow.e2e.mjs
  • wework/src/pages/SitesPage.tsx
  • wework/src/App.plugins.test.tsx
  • docs/en/wework/developer-guide/wework-codex-plugins.md

新增应用类型时,在 Backend 增加响应模型和 `ApplicationTypeHandler`,注册到 `APPLICATION_TYPE_HANDLERS`;在 Wework 的 `applicationTypeDefinitions.tsx` 增加对应 Definition,集中声明图标、文案、列、行渲染和创建策略(包括 `pluginName`)。若使用新的内置插件,同时在 Backend 内置插件注册表和 `builtin-plugin-staging.mjs` 增加插件定义。列表工作区和创建流程不应再增加按类型分支。服务端可独立调整类型顺序、开关和能力,但未知类型会被旧版客户端安全忽略。
新增应用类型时,在 Backend 增加响应模型和 `ApplicationTypeHandler`,注册到 `APPLICATION_TYPE_HANDLERS`;在 Wework 的 `applicationTypeDefinitions.tsx` 增加对应 Definition,只声明图标、文案、列和行渲染。创建插件身份由 `GET /api/sites/app-types` 的 `create.plugin_name` 和 `create.marketplace_name` 下发,Wework 会缓存最近一次成功的 app-types descriptor,并在云端短暂不可用时复用缓存。读取缓存时必须先验证 `items` 中每个 descriptor 都是对象,且可选的 `create.plugin_name`、`create.marketplace_name` 在存在时是字符串;缓存不满足契约时返回空缓存并回到服务端发现或默认 Definition。若使用新的内置插件,同时在 Backend 内置插件注册表和 `builtin-plugin-staging.mjs` 增加插件定义。列表工作区和创建流程不应再增加按类型分支。服务端可独立调整类型顺序、开关、能力和创建插件,但未知类型会被旧版客户端安全忽略。

创建入口会先调用 `GET /api/plugins/installed?device_id=<target>` 检查目标设备的本地插件安装态;如果对应插件在该设备上的 `currentDeviceInstallation` / `status.devices` 已是 `installed`,前端直接使用插件的 `displayName` 和默认提示词打开新任务,不再重复安装。未安装时,创建站点调用 `POST /api/plugins/builtin/wegent-sites/ensure-installed`,创建小程序调用 `POST /api/plugins/builtin/weibo-miniapp-h5-develop-agent/ensure-installed`,请求体都必须携带目标 `device_id`。该接口只允许安装系统所有者发布的内置插件;内置应用插件使用 `visibility=workspace`,因此 Backend 下发的 `create.marketplace_name` 和安装记录中的 `source.marketplace` 都是 `wegent`。不同 visibility 对应不同插件市场名:`personal` 使用 `wework-personal`,`workspace` 使用 `wegent`,`public` 使用 `wework`,前端不应写死某一个市场名,而应复用共享的 marketplace 身份工具。重复调用会复用并重新启用对应插件的已有安装记录;后端可能先执行全量 `replace` 同步,并在目标设备缺少该插件时再执行单插件 `merge`。前端只以目标设备回执为准,要求本次应用插件的安装 ID 或插件名返回 `synced`;如果旧响应没有 `sync.results`,则按没有目标设备专属结果处理,并继续使用顶层 `sync.plugins` 回退校验。其他设备或历史能力的同步错误不会阻塞应用创建对话。目标设备不存在、离线或本次请求的插件未能同步到目标设备时,前端不会创建对话。确认成功后,前端分别使用稳定的 `plugin://wegent-sites@wegent` 和 `plugin://weibo-miniapp-h5-develop-agent@wegent` 引用打开新任务;小程序入口还会带入插件提供的默认创建提示。插件安装和同步期间,应用页会显示“正在安装应用插件,完成后将进入会话...”的状态提示。点击 mention 时,插件页直接加载相应的云端插件详情。

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 | 🟠 Major | ⚡ Quick win

Derive the installation flow from the application-type descriptor.

This flow fixes installation endpoints and plugin URIs to wegent-sites and weibo-miniapp-h5-develop-agent. Line 51 states that Backend can independently change create.plugin_name and create.marketplace_name. A changed descriptor would then install or reference the wrong plugin.

Construct the built-in installation request and plugin:// reference from the descriptor. Remove the application-type-specific plugin branches.

🤖 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 `@docs/zh/wework/developer-guide/wework-codex-plugins.md` at line 53, Update
the application creation flow to derive the built-in installation endpoint,
plugin name, and plugin:// reference from the application-type descriptor rather
than hardcoded wegent-sites or weibo-miniapp-h5-develop-agent branches. Reuse
the descriptor’s create.plugin_name and create.marketplace_name values for
installation and task creation, and remove the application-specific branching
while preserving the existing device sync validation and default-prompt
behavior.

Comment on lines +16 to +19
export function managedMarketplaceName(plugin: InstalledPlugin): string | null {
const providerKey = plugin.spec.source?.providerKey
if (providerKey !== 'wegent-market' && providerKey !== 'wegent-marketplace') return null
return marketplaceNameForVisibility(plugin.spec.visibility) ?? 'wegent'

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 | 🟠 Major | ⚡ Quick win

Do not map unknown visibility to wegent.

?? 'wegent' overrides plugin.spec.source.marketplace because downstream consumers call managedMarketplaceName first. If a managed row has no recognized visibility but has source.marketplace = 'wework', Composer generates the wrong plugin URI and Sites cannot match the installed plugin.

Return null for unknown visibility. This lets consumers use explicit source metadata. Backend normalization should handle the eligible legacy built-in rows.

Proposed fix
-  return marketplaceNameForVisibility(plugin.spec.visibility) ?? 'wegent'
+  return marketplaceNameForVisibility(plugin.spec.visibility)
📝 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
export function managedMarketplaceName(plugin: InstalledPlugin): string | null {
const providerKey = plugin.spec.source?.providerKey
if (providerKey !== 'wegent-market' && providerKey !== 'wegent-marketplace') return null
return marketplaceNameForVisibility(plugin.spec.visibility) ?? 'wegent'
export function managedMarketplaceName(plugin: InstalledPlugin): string | null {
const providerKey = plugin.spec.source?.providerKey
if (providerKey !== 'wegent-market' && providerKey !== 'wegent-marketplace') return null
return marketplaceNameForVisibility(plugin.spec.visibility)
🤖 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/pluginMarketplaceIdentity.ts` around lines 16 -
19, Update managedMarketplaceName so unrecognized plugin.spec.visibility returns
null instead of falling back to 'wegent'. Preserve the existing providerKey
eligibility check and recognized visibility mappings, allowing downstream
consumers to use explicit plugin.spec.source.marketplace metadata.

@qdaxb
qdaxb added this pull request to the merge queue Aug 7, 2026
Merged via the queue into wecode-ai:main with commit b100bb8 Aug 7, 2026
50 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