* Keep the Windows SID lookup alive on non-UTF-8 console output
`_resolve_current_user_sid` calls `whoami /user /fo csv /nh` in text mode
without an encoding. `make dev` and `make gateway` start the Gateway with
PYTHONUTF8=1, so on a Chinese Windows host the interpreter decodes as UTF-8
while whoami writes the account name in the console's ANSI code page. The
strict decode raises inside subprocess's reader thread; the exception is not
re-raised, so stdout comes back as None and the credential-tree hardening
walk dies with `AttributeError: 'NoneType' object has no attribute 'strip'`
before any directory is created or hardened.
Pin the encoding and keep an errors policy. The SID is the second CSV field
and is pure ASCII, as are the delimiters, so replacing the undecodable
account name is harmless. #6590 pinned the seven lark-cli/npm captures in
this file; this is the eighth text-mode capture and, unlike those, does not
emit UTF-8, so the errors policy is the part that matters here.
Add a cross-platform regression test next to the #6590 encoding tests.
* docs(lark): correct the SID capture wording
`undecodable` is the spelling used elsewhere in the repository, and the
comment about the console code page reads better as "which does not need to
match". No behaviour change.
---------
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
* fix(integrations): decode lark-cli and npm output as UTF-8
Every text-mode subprocess.run in lark_cli.py that captures lark-cli or npm
output omits encoding, so the bytes are decoded with the host locale. Both
write UTF-8 to a pipe: the @larksuite/cli npm package's bin is a Node wrapper
around a native binary that emits UTF-8 (lark-cli --help writes U+2014 as
E2 80 94), and npm output is UTF-8 too.
On a host whose ANSI code page is not UTF-8 (cp936, cp1252) the locale decode
silently mangles every non-ASCII field -- auth status --json returns a garbled
userName, so the status card shows mojibake -- and an undecodable byte raises
inside subprocess's reader thread, which is not re-raised: stdout comes back
as None or "", so a healthy CLI is reported as unavailable and a successful
run raises "lark-cli did not return JSON output."
Decode these captures as UTF-8, matching #5440 (PowerShell), #5904 (AIO
sandbox docker CLI) and #6548 (Git Bash output in LocalSandbox). The
whoami /user capture stays on the locale: whoami is a native tool that writes
the host code page, the same UTF-8/native split #6548 drew.
Tests drive the real functions with a stand-in CLI emitting UTF-8 CJK JSON
and pin the pre-fix decode path, so they fail on main and pass here on any
host locale.
Fixes#6589
* test(lark): isolate the paths singleton in the encoding suite
The new tests reached ensure_lark_cli_credential_tree through the global
get_paths() singleton, so every run created and hardened a real
<cwd>/.deer-flow/users/alice/integrations/lark-cli/{config,data} tree in
whatever directory pytest ran from -- the same runtime home a live deployment
keeps real per-user Lark credentials in. An autouse fixture now points the
singleton at tmp_path, matching what test_lark_cli_integration.py does.
Red/green is unchanged: reverting only lark_cli.py still fails the two
assertions that pin the decode, and the suite leaves no .deer-flow behind.
* test(lark): make the version probe pin the decode, drop the inert locale patch
Two test-rigor notes from review:
- test_probe_lark_cli_at_path only asserted available/error, and the probe
returns available=True with any non-empty output and a zero exit code, so
the test stayed green even with the encoding pin removed from
_probe_lark_cli_at_path. The stand-in now answers --version with a non-ASCII
payload and the test names the expected text, which fails on the unpinned
call site (verified) and passes with the pin.
- The locale.getencoding patch was inert: the subprocess.run wrapper injects
the codec for unpinned text-mode calls and lark_cli never consults the
locale itself, so nothing reached the real locale-decode path. Dropped it,
along with the now-unused import, rather than implying a redirection that
does not happen.
The Windows shim forwards its arguments (%*) so the stand-in sees --version.
---------
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>