Keep the add-only Wukong compat flag, but publish it as a CLI-local
polymorphic dispatch without a download_file property binding.
Co-authored-by: Cursor <cursoragent@cursor.com>
Expose minutes hot-word delete, permission apply, and audio-memo list from
live MCP gaps; add hidden/cross-product flag aliases only (never remove),
with TestCrossPlatformCoverage coverage for the new surfaces.
Co-authored-by: Cursor <cursoragent@cursor.com>
Port calendar event instances, markdown diff, drive list --latest,
mail calendar/calendar-event/shared-with-me/export/share-to-chat, and
doc whiteboard insert so open edition matches documented Wukong test
command surfaces.
Co-authored-by: Cursor <cursoragent@cursor.com>
Main brought --part-size/--parallel/--no-resume onto drive download leaves
without ParamDecl or mapping exclusions, so Catalog fell back to
flag_name_inference and failed the unpinned-adapter mapping audit.
Co-authored-by: Cursor <cursoragent@cursor.com>
When user interrupts multipart download with Ctrl+C, display a helpful
message indicating checkpoint is saved and download can be resumed,
instead of returning an internal error with context.Canceled.
- Replace context.Background() with cmd.Context() in download and
download-version commands so SIGINT propagates to download goroutines
- Enables graceful interruption of multipart downloads via Ctrl+C
- Add multipart download engine (drive_transfer.go) with Range probe,
resume support, and credential auto-refresh on 401/403
- Add --part-size, --parallel, --no-resume flags to drive download and
download-version commands
- Replace httpGetFile with driveTransferDownload for chunked parallel
downloads in download and download-version commands
- Replace uploadToDrive credential parsing with driveUploadPut
(transparent header pass-through, retry on 401/403)
- Add typed httpStatusError for non-2xx HTTP responses in doc.go
- Add comprehensive unit tests (32 cases) for drive_transfer
- Update drive reference documentation with multipart download behavior
- Add E2E test for multipart download (auto-test/, gitignored)
CR: 28984991
Move schema authority to declare-time ParamDecl/ContractFinal and
ResolveSchemaBuild so CI/runtime assemble instead of shipping JSON
exclusions/meta-index as delivery sources.
Co-authored-by: Cursor <cursoragent@cursor.com>
SchemaDecl confused authoring with Catalog/ToolSpec delivery. Authors now
declare ContractDecl (nested contract.* types) on Spec/LeafSpec/Shortcut;
AttachContract registers only through cli.RegisterRuntimeContractFinal, and
description provenance stamps cobra_help when Long wins.
Co-authored-by: Cursor <cursoragent@cursor.com>
Drop the dual-entry thin alias layer so helpers/shortcut/framework author
contract.* types directly; keep only AnnotateRuntime* delivery helpers in cli
and document the corecmd→cli seam.
Co-authored-by: Cursor <cursoragent@cursor.com>
Move the last hint parameter overlays into in-code ParamDecls (helpers +
shortcuts), regenerate catalog, and harden the migrate script for factory
and Use/RPC matching so all 74 overlay tools are declaration-backed.
Co-authored-by: Cursor <cursoragent@cursor.com>
DeclareLeafMetadata user_required wraps were confirming before RunE-local
checks, so illegal calls got confirmation_required instead of real errors.
Allow Validate on PreRunE, migrate event stop and drive publish checks, and
lock the Sheet dual-gate transitional state.
Co-authored-by: Cursor <cursoragent@cursor.com>
Must-fix: drive permission apply now gates on confirmDangerousAction and
declares confirmation=user_required, matching its help-text promise.
Wukong parity restored: formula-verify --exit-on-error (payload-parsing
exit path) and --targets conflict error, sheet info --include, chat
location/profile message types, search-advanced wukong flag aliases,
and a dedicated drive download-version leaf replacing the removed
polymorphic download --version.
Consistency fixes: transfer-owner --node/--workspace XOR and JSON-aware
dry-run after --yes validation; drive list --versions rejects
--depth/--pattern instead of misleading depth errors; depth BFS resumes
rate-limited folders from the failed page cursor to avoid duplicates;
doc style cover upload honors cmd.Context() and a 20 MiB size cap; chat
user-settings set validates per-item openConversationId and is
risk=medium.
Hardened the skill static audit to scan fenced code blocks and reject
unknown subcommands on group commands, fixing the stale aitable/drive
doc examples it exposed. Added CHANGELOG entry and coverage tests for
all changed statements plus previously untested ported commands.
- Port drive list --depth N BFS recursive listing (pan + workspace routes,
rate-limit requeue, SIGINT partial emit, --pattern/--quiet)
- Port doc style cover set/clear, background set/clear, get with local
image validation and attachment-upload subflow
- Register all 26 newly ported commands in schema_command_registry with
reviewed metadata/selection hints instead of exclusions (813->839 tools)
- Review fixes: drive list --node usage text no longer implies required
in agent schema; remove broken formula-verify --exit-on-error; error on
--range without --sheet-id; portable stdin read; drop local --yes
shadowing root -y on drive revert/transfer-owner; use
confirmDangerousAction for non-delete confirms; explicit
recursiveChange=false now transmitted; sheet version revert and
comment delete moved into sheet confirmationGuards registry
Remove --version flag from drive download (polymorphic tool dispatch
incompatible with schema validation). Regenerate schema catalog and
add new commands to schema_command_exclusions.json.
Switches the discovery version code bamboo -> cedar and aligns the open edition CLI with dws-wukong across communication (calendar book/acl/attendee, minutes tag, mail folder/template/contact, chat file upload, todo add-attachment, attendance transforms) and structured-office (aitable advperm/view/section/workflow/record, sheet/drive/wiki/doc) domains. Includes output-envelope parity, parse_bool/attendance_class_check_time transforms, --calendar-id support, CHANGELOG 1.0.43 and README command-index refresh. cedar config validated on pre and prod endpoints.
* fix(drive): drop client-side Content-Type fallback on presigned OSS PUT
The drive helper used to set req.Header["Content-Type"] = fallbackMIME
whenever the prepare_upload response returned an empty headers map.
DingTalk drive uses OSS presigned URLs whose StringToSign is computed
against an empty Content-Type at signing time, so any client-side
Content-Type makes the signature OSS recomputes at PUT time differ
from the server's presignature → HTTP 403 SignatureDoesNotMatch.
This broke every `dws drive upload` for any file whose mime detects
to a non-empty value (image/png, application/pdf, etc.), which is
basically everything in practice.
Reproduction (against DingTalk drive):
dws drive upload --file any.png
→ [1/3] 获取上传凭证 any.png (X 字节, image/png)...
→ [2/3] 上传文件到 OSS...
→ OSS 上传失败 HTTP 403: SignatureDoesNotMatch
Fix: trust the server's headers map as authoritative. Empty map means
"no client-side headers needed" — do not infer and add Content-Type.
Removes the hasContentType / fallbackMIME path entirely; httpPutDriveFile
signature loses the fallbackMIME parameter.
Manual verification:
curl -X PUT -H "Content-Type:" --data-binary @file <same-presigned-url>
→ HTTP 200 (proves the only difference was the client-side Content-Type)
Note: aitable.go's upload-file helper deliberately keeps its
Set("Content-Type", mimeType) call because its OSS endpoint uses a
different signing mode (server includes the client-declared mime in
its signature computation, verified by running aitable upload-file
across 12 file types — all succeed). The two helpers must not be
unified without re-validating both endpoints.
Tests:
- TestHttpPutDriveFile_NoContentTypeWhenServerHeadersEmpty: guards
that an empty server headers map results in no Content-Type on PUT.
- TestHttpPutDriveFile_PassthroughServerHeaders: guards that server
headers (Content-Type, x-oss-*) are forwarded verbatim.
* feat(aitable): unhide attachment upload-file + clarify prepare-only command
AI agents that discover commands only via --help (e.g. Lobster, generic
LLM agents) currently hit a dead end when trying to upload an attachment
to an AITable:
- `dws aitable attachment` exposes only `upload` (prepare-only),
which returns uploadUrl + fileToken but does not actually upload.
- The real one-shot command `attachment upload-file` (which performs
prepare + HTTP PUT + return fileToken automatically) is marked
Hidden:true, so it is invisible in --help output.
Agents that don't read skills/references/products/aitable.md therefore
get stuck after step 1 — they call `upload`, receive an uploadUrl they
have no idea how to consume, attempt various wrong things (e.g. write
the uploadUrl into the record's attachment field as if it were a token),
fail, and fall back to "please use the UI to upload" messages, which
makes dws look broken even though the capability is fully implemented.
This is the same UX gap that lark-cli avoids with its highly visible
`base +record-upload-attachment` command — discoverability via --help
is the difference between "works for any agent" and "only works if the
agent reads our skill docs".
Changes:
- newAITableUploadFileCommand: remove Hidden:true so the command
appears in `dws aitable attachment --help`. Tighten Short to
explicitly mention the 3 steps it bundles. Long now also calls
out the prepare-only sibling and recommends this command as the
default for AI agents.
- newAITableAttachmentUploadCommand (prepare-only): add a Long
description that explicitly states this command is only step 1
of a 3-step flow, lists what an agent must do after (HTTP PUT,
then write fileToken into record attachment field with the exact
[{"fileToken":"ft_xxx"}] shape), and points to upload-file as
the recommended one-shot alternative. Updated Short to flag that
no file is uploaded by this command.
- aitable_upload_file_test: add TestAITableUploadFileCommandIsDiscoverable
to guard against re-introducing Hidden:true. The test includes a
rationale comment explaining the agent-discoverability gap.
The drive Content-Type fix in the preceding commit and this aitable
discoverability fix together restore end-to-end attachment upload
functionality for both human operators and AI agents that only read
--help.
* feat(root): show 'dws upgrade' guidance in dws --help when commands are missing
AI agents (and users) reading `dws --help` see only the discovered MCP
service list and utility command list, with no hint about what to do if
none of the listed commands fit their task. The natural failure mode is
to give up or hack around — but in many cases the right action is just
`dws upgrade`, because new capabilities and bugfixes ship continuously
and a missing command is usually a stale binary issue.
Two changes restore visibility of the root command's Long description so
this guidance can be surfaced:
- internal/app/root.go: set root.Long to a one-paragraph hint —
"if you hit a missing command, an error, or cannot complete the
task, try `dws upgrade` first; both the DingTalk OpenAPI surface
and dws CLI evolve continuously."
- internal/app/root_help.go: the custom SetHelpFunc that renders the
root help (renderRootHelp) replaces cobra's default template, which
had been silently dropping root.Long from --help output. Restore
rendering by appending root.Long (when non-empty) after the command
list, separated by a blank line. This matches cobra's default
behavior for the Long field while preserving the custom services /
utilities sections renderRootHelp introduced.
- internal/app/visibility_test.go: new TestRenderRootHelpIncludesLong
guards against re-introducing the regression. Uses a sentinel Long
string and asserts renderRootHelp output contains it verbatim. If a
future change rewrites the help renderer without preserving Long
rendering, this test fails immediately and reminds the author the
upgrade hint must stay visible.
Verified locally:
$ ./dws --help | tail -3
Use "dws <service> --help" for more information about a discovered MCP
service or "dws <command> --help" for utility commands.
提示: 如果遇到能力缺失、命令报错、新功能未注册、或无法完成任务,
请先用 'dws upgrade' 升级到最新版本后再试. 钉钉 OpenAPI 和 dws CLI
持续迭代, 新能力和 bugfix 会先在新版本上线.