Skip to content

refactor(cli): unify token storage behind Store + add host/account switching#36830

Merged
wylswz merged 13 commits into
mainfrom
fix/cli-token-storage-unify
Jun 2, 2026
Merged

refactor(cli): unify token storage behind Store + add host/account switching#36830
wylswz merged 13 commits into
mainfrom
fix/cli-token-storage-unify

Conversation

@GareArc
Copy link
Copy Markdown
Contributor

@GareArc GareArc commented May 29, 2026

Overview

Unifies how difyctl reads and writes credentials, adds first-class multi-host/account switching, replaces the split output formatter system with a single protocol, and adds auth list.

Resolves WTA-356.

What changed

Token storage

  • All credential reads/writes go through the Store interface; keychain and file backends share one code path.
  • Host registry stripped of token fields and token-read logic; tokens.yml is authoritative.

Auth commands

  • difyctl auth list — table of all authenticated host+account pairs, supports -o json/yaml/name. Replaces auth status (redundant with auth whoami for single-context view).
  • difyctl use host [--domain <domain>] — switch the active Dify instance.
  • difyctl use account [--email <email>] — switch active account on the current host.
  • Interactive picker when flag is omitted in a TTY; fails with a hint in non-TTY (CI/agent) contexts.

Login UX

  • Blue spinner during device-flow authorization poll.
  • Omitting --host in a non-TTY context now errors with a usage hint instead of hanging.

Output formatter unification

  • Single source of truth for all CLI output: framework/output.ts (TablePrintable, FormattedPrintable) and framework/stream.ts (StreamPrinter).
  • src/printers/ deleted entirely (15 files). AppRunObject now implements FormattedPrintable directly; mode-dispatch (chat/completion/workflow) internalized.
  • StreamPrinter type moved to framework/stream.ts; concrete implementations stay command-scoped.
  • All get/* handlers migrated from printers/format-table type imports to framework/output.

Testing

  • pnpm type-check, pnpm lint, pnpm tree:check — clean.
  • pnpm test — 786 passing, including coverage for the interactive picker, use host/use account flows, and auth list output shapes.

…itching

Route all credential reads/writes through the Store interface so keychain
and file backends share one code path. Add `use host` / `use account`
commands for multi-account switching, with a zero-dependency arrow-key
dropdown (replaces @inquirer/prompts, which broke under bun --compile).

- login: blue dify spinner during device-flow poll; fail fast with a flag
  hint when host is omitted in a non-TTY (agent) context
- select: custom keypress picker, restores raw mode / cursor on any exit
  including synchronous setup failure
- hosts: remove() no longer clears the active host when a non-active
  account is removed

Tests: 836 passing.
@GareArc GareArc requested a review from a team as a code owner May 29, 2026 11:21
@dosubot dosubot Bot added size:XL This PR changes 500-999 lines, ignoring generated files. javascript refactor labels May 29, 2026
GareArc and others added 11 commits May 29, 2026 04:27
…-unify

# Conflicts:
#	cli/src/commands/auth/login/login.test.ts
#	cli/src/commands/auth/login/login.ts
Registry.load() now always returns a Registry (empty when no config file
exists) instead of Registry | undefined. The 'no config file' and 'no
active account' states were handled identically by every caller, so they
collapse into one signal: resolveActive() returning undefined.

Callers drop the reg?. guards and the '?? Registry.empty(mode)' fallback.
whoami and logout, which hand-reimplemented requireActive(), now call it
directly.
Resolve conflicts from PR #36822 (absolute path refactor): keep Registry/
ActiveContext model from this branch, adopt @/ alias import style from main.
Convert all remaining relative .js imports in branch-local files to @/ or
@test/ aliases. Fix ./_strategies/index nested path to @/commands/ prefix.
Convert remaining relative .js imports in use/host, use/account, sys/io/select
to @/ aliases. Fix perfectionist/sort-imports ordering in test and source files
missed by the merge commit.
…ommands

- auth list: table of all authenticated host+account pairs, supports
  -o json/yaml/name; replaces auth status (redundant with auth whoami
  for single-context view, no structured multi-context output)
- use host --domain: switch active Dify instance interactively or by flag
- use account --email: switch active account on current host
- help account: add tips for auth list, use host, use account
…ers/

Single source of truth for all CLI output: framework/output.ts
(TablePrintable, FormattedPrintable) and framework/stream.ts (StreamPrinter).

- Move StreamPrinter type from printers/stream-printer.ts to framework/stream.ts
- Migrate run app blocking output to FormattedPrintable: AppRunObject now
  implements text()+json() directly; mode-dispatch internalized
- Remove AppRunPrintFlags, TextPrintFlags, JsonYamlPrintFlags indirection;
  strategies call stringifyOutput(formatted({...})) and streamPrinterFor() directly
- Migrate all handlers (get/app, get/member, get/workspace) to import
  TableColumn from framework/output instead of printers/format-table
- Remove dead code: WorkspaceObject, workspaceTableHandler, payload-shape.ts
- Delete entire src/printers/ directory (15 files)
- Update ARD.md: document output protocol pattern, retire printer-chain section
…splay name in auth list

- streaming-structured: use handle/unhandle from sys/index instead of process.once/off directly
- auth/list/handlers: remove dead static tableColumns(); inline display name in ACCOUNT cell
  when present (email only when name is empty)
- auth/list/list.test: add coverage for inline-name and empty-name table rendering
Resolve HTTP client refactor conflicts (cfc1cf2): replace KyInstance
with HttpClient/createHttpClient across all authed commands, keeping
Registry/Store multi-account model. Fix bin/** no-top-level-await lint.
Comment thread cli/src/auth/hosts.ts
Comment thread cli/src/auth/hosts.ts
@dosubot dosubot Bot added the lgtm This PR has been approved by a maintainer label Jun 2, 2026
@wylswz wylswz added this pull request to the merge queue Jun 2, 2026
Merged via the queue into main with commit 0da13df Jun 2, 2026
32 checks passed
@wylswz wylswz deleted the fix/cli-token-storage-unify branch June 2, 2026 04:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm This PR has been approved by a maintainer refactor size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants