v1.0.13
7
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4f915e4e2c |
refactor(plugin): drop managed/ compat layer left by PR #126 (#135)
PR #126 removed the privileged managed-plugin mechanism but kept LoadManaged, IsManaged, and ~/.dws/plugins/managed/ fallbacks so that plugins installed by pre-#126 builds would keep loading. The window for that migration was ~4 days (2026-04-15 → 2026-04-19), and the original install path mostly failed anyway (issue #124 / GitHub Pages HTML response), so there is no real user base to preserve. Scope of deletion: - plugin.Loader.LoadManaged, scanDir's isManaged param, loadPlugin's isManaged param. LoadAll now combines user + dev only. - Plugin.IsManaged field. Converter/root.go no longer branch on it; stdio and HTTP descriptors both report source="plugin". - ~/.dws/plugins/managed/ branches in ListInstalled, SetEnabled, RemovePlugin. - config.PluginManagedDir constant. - TestLoaderLoadManaged, TestRemoveLegacyManagedPlugin, and the "legacy managed" table case in TestRemovePluginPurgesSettings. Kept on purpose: - Manifest.Type public schema field ("managed"|"user") — it appears in existing plugin.json files and is only validated, never behaviorally consumed. Users with an orphaned ~/.dws/plugins/managed/ directory can `rm -rf ~/.dws/plugins/managed/` — the CLI no longer reads it. |
||
|
|
725577103d |
feat: PAT scope error visualization and auto-retry with authorization polling (#113)
* feat: PAT scope error visualization and auto-retry with authorization polling 1. PAT error result visualization (non-JSON) - Human-readable error output matching lark-cli style - Shows error type, message, hint, and authorization command - JSON output also available via --format json 2. Auto-retry with polling after authorization wall - Detects missing_scope / insufficient_scope / permission errors - Polls every 5s for token update after user completes auth - 10 minute timeout before giving up - Automatically retries the original command after successful auth Changes: - internal/app/pat_auth_retry.go: Core PAT error handling and retry logic - internal/app/pat_auth_retry_test.go: 11 unit tests - internal/app/runner.go: Integration with executeInvocation error path - internal/auth/device_flow.go: Add SetScope() method * feat: migrate PAT (Permission Authorization) infrastructure to open-source core Move PAT permission management code from dws-wukong overlay to the open-source dingtalk-workspace-cli core. This enables PAT handling in the public distribution while keeping dws-wukong fully compatible through the edition.Hooks mechanism. Changes: - pkg/edition: add 6 new Hooks fields (AuthClientID, AuthClientFromMCP, SaveToken, LoadToken, DeleteToken, ClassifyToolResult) for overlay extensions to inject custom auth/token/error behaviour - internal/errors/pat: new PATError type with ExitCode()=4 and RawStderr() for embedded-mode passthrough, plus ClassifyToolResultContent and ClassifyMCPResponseText classification functions - internal/pat: new command group (pat chmod) with tool result handling - internal/app/root: register PAT commands before RegisterExtraCommands hook - internal/app/runner: integrate ClassifyToolResult hook in the callResult.IsError branch so overlays can intercept PAT/gateway errors before generic handling The dws-wukong overlay remains unchanged — its existing pat/ package and RegisterExtraCommands hook continue to work. Through the go.mod replace directive and deduplicateCommands mechanism, both codebases coexist without conflict. * feat(pat): add PAT auth check with device flow polling and auto-retry - Add ClassifyPatAuthCheck / AsPatAuthCheckError in pat.go for AGENT_CODE_NOT_EXISTS error detection - Add handlePatAuthCheck in pat_auth_retry.go: inject clientId as x-robot-uid header, poll device flow endpoint, auto-retry on APPROVED - Integrate PAT check into runner.go executeInvocation pipeline (edition hook + open-source fallback) - Add patAuthRequiredCodes map for extensible auth-required code matching - Remove test_parse.go (temporary test script) * fix(pat): update poll path to /cli/oauth/device/poll and add x-user-access-token header - Change DevicePollPath from /api/dingtalk-workspace-cli/oauth/device/poll to /cli/oauth/device/poll (aligning with backend endpoint convention) - Add x-user-access-token header to poll requests (loaded from stored token) * feat(auth): PAT device flow improvements and flowId empty guard - pat_auth_retry: fix JSON field parsing (result -> data) using DevicePollResponse - pat_auth_retry: fix elapsed time calculation based on start timestamp - device_flow: add flowId empty guard - skip polling and show auth URL for manual handling - device_flow: unify terminalBaseURL to GetMCPBaseURL for polling endpoint - device_flow: remove unused PollFlowApproval dead code - runner: integrate DWS_CLIENT_ID env and app.json persistence - oauth_provider: add x-robot-uid header removal on logout - client: add request/response logging for transport debugging * feat(env): switch all service discovery URLs from pre-release to production - endpoints: pre-login/pre-api/pre-mcp/pre-open-dev -> login/api/mcp/open-dev - loader: DefaultMarketBaseURL -> mcp.dingtalk.com - registry: defaultBaseURL -> mcp.dingtalk.com - constants: DefaultTerminalBaseURL -> open-dev.dingtalk.com * fix: remove residual merge conflict markers and duplicate Hooks fields in edition.go; unify developer-settings URL via config helper in device_flow.go * chore: remove lark-cli reference from PrintPatAuthError comment * test: add comprehensive unit tests for PAT auth modules - Create internal/errors/pat_test.go (38 tests): covers ClassifyToolResultContent, ClassifyMCPResponseText, ClassifyPatAuthCheck, AsPatAuthCheckError, cleanPATJSON, stripClassFields, getDWSGatewayErrorCode, isNotLoggedInError, isBusinessError, IsPATError, IsPATNoPermissionCode, suggestForBusinessErrorText - Supplement pat_auth_retry_test.go (+7 tests): IsPatRetrying context checks, pollPatDeviceFlow edge cases (server error fallback, SSO redirect skip), extractPatScopeError nil/identity extraction * feat(pat): exchange authCode for fresh token after PAT APPROVED Previously pollPatDeviceFlow discarded the authCode from the poll response, so handlePatAuthCheck retried with the stale token after APPROVED. This mirrors device_flow.go loginOnce which calls exchangeCode → SaveTokenData. Changes: - pollPatDeviceFlow: return (status, authCode, error) instead of (status, error); extract Data.AuthCode on APPROVED - handlePatAuthCheck APPROVED path: call ExchangeCodeForToken + SaveTokenData before ResetRuntimeTokenCache, with graceful fallback on exchange failure - Update all 6 poll test cases for new 3-return signature; add authCode assertions for APPROVED/REJECTED/EXPIRED/CANCELLED/ ServerError scenarios * fix(pat): CR round-2 must-fix items - scopeValueRegex: support multi-segment scopes (mail:a.b:send) Updated regex to ([a-zA-Z][a-zA-Z0-9_.]*(?::[a-zA-Z][a-zA-Z0-9_.]*)+) - handlePatAuthCheck: add 3 integration tests (APPROVED/REJECTED/EmptyFlowID) Covers the 132-line main orchestrator with mock runner + httptest server - Extract ParseDeviceFlowStatus + status constants to auth package Eliminates string literal duplication across device_flow.go and pat_auth_retry.go * fix(pat): use direct OAuth path when clientSecret is provided When PAT error response includes both clientId and clientSecret, use SetClientID() (direct DingTalk API mode) instead of SetClientIDFromMCP() (MCP proxy mode). The MCP proxy does not hold the secret for the PAT-assigned app, causing HTTP 400 'invalidParameter.idOrSecret.notFound' on token exchange. Now: clientSecret present → direct mode; absent → MCP proxy mode. --------- Co-authored-by: shangguanxuan.sgx <shangguanxuan.sgx@alibaba-inc.com> |
||
|
|
33ae780103 |
refactor(plugin): remove default/managed plugin privileged mechanism
Drop the hardcoded default-managed-plugin bootstrap that auto-fetched DingTalk-Real-AI/* plugins on CLI startup. All third-party plugins are now installed equally via `dws plugin install` — no privileged workspace. Motivation (issue #124): first-run startup printed WARN failed to fetch remote info for default plugin DingTalk-Real-AI/conference: invalid character '<' looking for beginning of value because the GitHub Pages registry returned HTML for the missing plugin. Beyond the error, the whole "built-in plugin" concept contradicts the CLI's lightweight design: plugin installation planning belongs to agent-authored skills, not to the CLI binary. Changes: - Delete internal/plugin/updater.go (EnsureManaged, CheckAndUpdate, checkRemoteVersion, downloadAndInstall, promptUpdate, zip extraction — the entire managed-plugin update pipeline). - Delete internal/plugin/updater_test.go. - Remove DefaultManagedPlugins, OfficialPluginWorkspace, and PluginUpdateCheckInterval from pkg/config/constants.go. - Remove the EnsureManaged/CheckAndUpdate bootstrap block from internal/app/root.go; only legacy LoadManaged() kept for back-compat so plugins already installed under ~/.dws/plugins/managed/ still load. - internal/plugin/loader.go: InstallFromGit always installs under PluginUserDir; RemovePlugin allows removal of legacy managed-dir plugins instead of refusing. - internal/app/plugin_cmd.go: drop `--type managed` flag and related gating from `plugin install`; disable/remove commands no longer differentiate managed vs user. - Update plugin_test.go accordingly (replace TestRemoveManagedPluginBlocked with TestRemoveLegacyManagedPlugin, drop TestPromptUpdate). Backward compatibility: `PluginManagedDir = "managed"` constant retained so plugins already on disk from older CLI versions still load and are removable. No migration required. Verification: - go build ./cmd → success - go test ./internal/plugin/... → PASS - go test ./internal/app/... → PASS (436s, matches main baseline) - Smoke: `/tmp/dws-new plugin list` no longer prints the "Pulling built-in plugin" or "failed to fetch remote info" WARN. - Pre-existing failures on main (unrelated): test/cli_compat, test/integration/extensions (requires auth login), test/scripts (requires DWS_PACKAGE_VERSION or git tag), test/unit TestOpenSourceTreeOmitsEmbeddedHostMarkers. Closes #124 |
||
|
|
d25b106e4f |
fix(plugin): harden plugin system security boundaries
- Validate git URL protocol: reject file:// and local paths, only allow https/ssh - Reject symlink entries in ZIP extraction to prevent path traversal - Validate build.output must be relative path within plugin directory - Reject absolute paths in stdio server command declarations - Block dangerous env var names (PATH, LD_PRELOAD, etc.) from plugin config injection - Remove conference from default managed plugins (source not yet available) |
||
|
|
8ecbff391c |
feat(plugin): bootstrap default managed plugins on first run
- Add `EnsureManaged` to the plugin updater to automatically install missing default plugins on startup. - Translate the managed plugin removal error message to English for better consistency. - Update tests to match the new error message. |
||
|
|
c4fb1bbd3e |
feat(plugin): add plugin system core framework
Introduce the plugin system for DWS CLI, enabling official and third-party plugin management. This includes plugin manifest parsing/validation, loader with managed/user directory-based identity, MCP server conversion and injection into the dynamic routing registry, pipeline hook adapter for shell-based hooks, and CLI commands (list/install/info/enable/disable/ remove/validate). |
||
|
|
93d6fdb17e |
feat: edition layer for Wukong overlay; promote shared code to pkg/
Introduce a build-time edition hook so downstream overlays (e.g. Wukong)
can customize auth UX, config dir, static server list, visible products,
and extra root commands while keeping the default open-source behavior.
- Add pkg/edition (defaults) and pkg/editiontest contract tests; Makefile
target edition-test; CI job edition-tests.
- Root: optional RegisterExtraCommands with tool caller adapter; inject
static servers to skip market discovery when configured; deduplicate
top-level commands so overlay wins; extend hideNonDirectRuntimeCommands
with edition VisibleProducts and static commands (recovery/schema/mcp).
- Auth/config: gate login subcommand and auth login hints for embedded
editions; optional token auto-purge; edition ConfigDir override.
- version: human-readable multi-line output plus JSON with edition,
architecture, build, commit.
- Relocate internal/{config,convert,validate} to pkg/; add pkg/cli and
pkg/cmdutil (flags/time helpers).
- CI: optional notify-downstream job (GitLab trigger via secrets) on main
push; open_source_policy_test adjusted for new layout.
Secrets (repo settings): WUKONG_TRIGGER_TOKEN, WUKONG_TRIGGER_URL — optional;
if unset, downstream step is skipped.
Made-with: Cursor
|