* fix: honor global --jq/--fields on product commands; round-2 QA fixes
Make the global --jq / --fields output filters actually work for the
product (MCP) commands. The helper Formatter used by every product
command ignored them, so they were silent no-ops there (they already
worked for `dws api`). Expose Fields()/JQ() on the ToolCaller interface
and apply the existing output.WriteFiltered path in the helper
Formatter's PrintJSON. The handful of bespoke utility commands
(auth/config/profile/...) still encode directly and are documented as
such.
Additional CLI fixes surfaced by the second real-machine QA pass:
- sheet write-image: emit clean JSON under --format json (suppress the
progress lines that leaked onto stdout, same as media-upload/export)
- sheet range batch-set-style: under --format json, collect per-item
results into a single JSON object instead of printing N separate ones
- chat download-media: create the output directory when missing and
strip URL-encoded path separators from the inferred filename so the
file actually lands instead of failing on a missing subdirectory
- pat chmod, aitable, sheet, chat, attendance: correct --help text
(real scope names, non-existent subcommands, flag requiredness,
alxs -> axls typo)
Helper scripts (mono and multi):
- minutes_extract_todos: parse dingtalkTodoList/actions (there is no
todos key), so todos are no longer silently dropped
- sync the multi copies of chat_export_messages / chat_history_with_user
(were crashing with AttributeError), minutes_list_parse /
minutes_recent_summary, and calendar_free_slot_finder to the fixed
mono versions
Skill docs (mono and multi): correct return-structure keys, flag names,
deprecated command routing (doc download -> drive download), enum values
and server-side limitations across products; update the global
reference to note --jq/--fields now apply to product commands.
* fix(skill): make skill setup --dry-run a no-op preview; doc/help fixups
skill setup ignored the global --dry-run flag and always wrote the skill
files (overwriting an existing install). Short-circuit into a preview
that lists the source, target dirs and selected sub-skills without
touching the filesystem.
Also correct a few doc/help mismatches found in the round-3 health check:
- attendance vacation balance/records quick-reference examples were
missing the required --leave-code flag
- mail mailbox list --help described the returned field as "mailboxes"
but the real field is "emailAccounts"
* docs: clarify --fields projects top-level/list keys, use --jq for nested
* docs: drop QA voice ("真机") and don't state env-specific quirks as absolute rules
The QA-driven doc/comment edits leaked test-process narration ("真机实测")
and this environment/account's quirks stated as universal rules into the
skill files, which are general-purpose instructions for any org/account.
Strip the "真机" narration everywhere; reword environment-specific findings
(PUBLIC sharing disabled by org policy, transient 1002, sender-open-dingtalk-id
behaviour) from absolute bans into conditional hints; keep genuinely
universal command behaviour, just without the QA voice.
Conflict resolutions:
- internal/app/direct_runtime.go: take upstream (532fcb4) — the maintainer
stabilized the endpoint tests by documenting the hardcoded devapp endpoint
as authoritative (tests renamed *DoesNotOverrideHardcoded), superseding our
demote-to-fallback fix for the same failing tests.
- skills/mono devapp.md: union — keep our reply-card/card-template/CLI
preflight bullets and upstream's Codex DWS_AGENT_CMD guidance.
Mirror hermes' semantics: without a configured card template, replies go as
plain text/markdown with the Thinking/Done reaction chips (which need no
template and always render); cards activate only when --card-template /
DWS_CARD_TEMPLATE is set ('public' opts into the openclaw shared template
explicitly). This removes the silent-failure trap where every card API call
succeeds but the client cannot render a template it is not authorized for —
the previous default left users staring at 内容加载失败 instead of falling
back to text.
The channel CLIs (claude/codebuddy/qodercli/...) may be missing on the
user's machine. Runtime already preflights at connect (auto-installing
package-manager CLIs, erroring with a hint otherwise), but agents had no
machine-readable way to check BEFORE starting the connector. dry-run now
reports a cli block ({required, installed, path, autoInstall, installHint})
per channel — desktop-app channels and openclaw/hermes report their
onboarding hint. Skill docs gain the agent preflight workflow: check
dry-run first; npm channels may auto-install; desktop-app channels must
have the app installed by the user before connecting.
Card templates are app-scoped — the hermes docs prescribe grabbing the
template ID from YOUR app's AI Card settings in the developer console, and
our live A/B confirmed another app's template renders 内容加载失败. Expose
the template as a flag (default: the openclaw public template, best-effort)
so operators can register an app-owned template for reliable, branded
rendering. Skill docs updated with the developer-console path.
Bring the official-channel reply experience (hermes/openclaw) to every
stream-bridge channel:
- "🤔Thinking" reaction chip on the user's message while the agent runs,
swapped to "🥳Done" when the reply lands — the hermes text-emotion contract
(POST /v1.0/robot/emotion/reply|recall, emotionId 2659900).
- AI-card reply using the openclaw connector's public template + payload
contract (msgContent + flowStatus state machine). Card templates are
app-scoped: hermes' own template renders "内容加载失败" for any other app —
confirmed by live A/B on the same robot.
- Live streaming into the card where the channel CLI supports it (verified
per CLI): claude/codebuddy stream-json text deltas (thinking deltas
filtered), qodercli stream-json per-turn snapshots; codex/gemini/opencode
stay one-shot. Frames are full-content and throttled at 800ms per card.
- --reply-card flag (default on, env DWS_REPLY_CARD=0) with full fallback
chain: any card failure → plain text/markdown webhook reply; stuck cards
are best-effort marked failed.
- Deliver responses are checked for business-level failures inside HTTP 200
({"result":[{"success":false,...}]} observed live), and every card API
response body is logged for operability.
- workbuddy persona now forbids tool use: headless codebuddy otherwise
stalls on permission gates trying to write memory files.
- Skill docs: reply-card flag, version-publish approver-selection workflow
(check-approval → present approver list to the user → publish --approver).
Known issue under investigation: after a batch of invalid-template test
cards, the reporting device renders all subsequent cards as "内容加载失败"
even though every API call succeeds and identical payloads rendered earlier
the same day — suspected client-side card/template cache poisoning; pending
verification on a second client.
Users reported the linked bot feels dumb. Root cause: the forwarder was
hard-pinned to a stateless one-shot haiku run from an empty directory. Expose
the trade-offs as command-set flags instead of hardcoding them:
- --agent-memory (default on): per-conversation session resume. First message
of a DingTalk conversation mints a UUID and passes `--session-id`,
follow-ups pass `--resume`, so multi-turn context survives. Only on CLIs
with addressable sessions (claudecode/codebuddy/workbuddy — verified against
their --help); qodercli has --resume but no --session-id, so the qoder
family stays stateless. Broken sessions self-heal: on forward error the
conversation mapping is dropped and the next message starts fresh.
- --agent-model / DWS_AGENT_MODEL: override the channel CLI's model via each
spec's model flag (replaces claudecode's built-in haiku pin in place).
- --agent-workdir / DWS_AGENT_WORKDIR: run the agent from a knowledge
directory for context, instead of the clean temp dir (which stays the
default to keep cold-start inside DingTalk's reply window).
A DWS_AGENT_CMD override disables flag splicing entirely — that argv is
user-owned and we cannot know which flags it accepts. Dry-run now previews
the effective agent tuning (model/workdir/memory) per channel.
Bring the channel-aware Stream linking ("建联") from PR #407 into the devapp
command tree as `dws devapp robot connect`, so the full lifecycle
(create app -> create robot -> link to a local agent) lives under one
`dws devapp` domain instead of a separate `dws connect` command.
- Reuse, not duplicate: provisioning ("建号") stays on devapp's existing
`robot create/submit/result`; this commit ports only the linking half.
- connect_stream.go: the Go-native in-process Stream forwarder + channel
agent registry, ported verbatim from #407 (package helpers, self-contained).
- devapp_connect.go: trimmed channel routing (resolveConnectChannel /
launchConnector / buildConnectPlan / ...) plus the new subcommand. The
standalone `connect` cobra command, `connect start` and `connect bot create`
are intentionally NOT brought over — the capability is consolidated under
`dws devapp robot`.
- Credentials: `--robot-client-id` / `--robot-client-secret` for an existing
robot, or `--unified-app-id` to auto-fetch via devapp's credentials get.
The flags are named `robot-client-*` (not `client-id`/`client-secret`) to
avoid shadowing the global OAuth client-override persistent flags.
- Adds the dingtalk-stream-sdk-go v0.9.1 dependency.
- Skill docs (devapp.md, robot.md mono+multi) document `robot connect`.
Known follow-up (marked in code + docs): the get_open_dev_app_credentials
response field names used by `--unified-app-id` auto-fetch are not yet
confirmed against the real gateway; the path degrades safely (empty -> fall
back to explicit flags) and must be verified against pre-prod before relying
on it.
Add `!**/credentials-webapp.md` to .gitignore so the skill reference
doc is not blocked by the `credentials*` rule. Revert the cred-webapp
rename from the previous commit.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
.gitignore rule `credentials*` was blocking the file from being tracked.
Rename to cred-webapp.md, update SKILL.md links, and fix workflows.md
stale text (version is now implemented, only event remains pending).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Permission list can return 150+ items. Document --limit and --offset
for paging across all three skill locations (standalone, multi, mono).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add missing flows: webapp get verification, member list/remove,
security config. All 17 devapp commands now E2E verified:
- member list/add/remove: tested on PR407验收 app
- security config: IP whitelist tested
- webapp get: verified returns after config
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>