Commit Graph

14 Commits

Author SHA1 Message Date
d5dee5326e feat(cli): align HITL pause envelope, split resume into top-level command, JSON purity
- Match server SSE envelope: HitlPausePayload now mirrors {event, task_id,
  workflow_run_id, data:{...}}; renamed user_actions → actions.
- New shared hitl-render.ts: text-mode block, JSON-mode pretty pure JSON
  (no ANSI), colored stderr hint. Exit 0 on pause (no longer a process error).
- Move RunAppResume → top-level ResumeApp at commands/resume/app/; rewire
  imports + regen tree.generated.ts. User-facing strings updated to
  `difyctl resume app`.
- Spinner gated on text mode: structured strategy passes
  enabled = isText && !livePrint so -o json/yaml never spin.
- Hint emits external-channel note when form_token is null (email-only
  delivery to OPENAPI/SERVICE_API surface returns no resume token).
- ColorScheme extended with dim/cyan/green/yellow/magenta methods.
- dify-mock fixture + tests updated to envelope shape; HITL pause test
  split into text + json variants.
2026-05-18 19:25:13 -07:00
badfd7689a feat(cli): build-time command-tree codegen + hidden/deprecated framework flags
Replaces the hand-written src/commands/tree.ts with a build-time-generated
artifact derived from src/commands/**/index.ts. tree.ts becomes a one-line
re-export of tree.generated.ts. Determinism: lexicographic sort, LF pinned
via .gitattributes, atomic write (tmp + rename), CI-gated by `pnpm tree:check`.

Codegen script (cli/scripts/generate-command-tree.ts) walks the commands
tree, derives canonical PascalCase identifiers (with reserved-word + hyphen
handling), and emits a static ESM module with sorted default imports and a
nested literal of shape CommandTree. Shared exclusion predicate
(isExcludedCommandPath) consumed by both codegen and coverage.test.ts so
underscore-prefixed segments stay non-commands.

Wired pre* lifecycle hooks (prebuild/predev/pretest) and ci composite
gating `tree:check` first. Pack now emits .js outputs (fixedExtension:false)
to drop .mjs; bin/run.js stays on .js. Vitest test.include extended to
cover scripts/.

Framework additions bundled in:
- static hidden = true       omits command from printTopLevelHelp listing
                              (still resolves and runs when invoked)
- static deprecated = '...'  prints "deprecated: <msg>" to stderr before
                              constructing the command

Verified: pnpm ci green (tree:check ok, tsc clean, lint clean, 702 tests
pass, build complete). Smoke: node bin/run.js version + auth login --help,
add-a-command flow, loose-file error case all behave as expected.
2026-05-18 18:25:57 -07:00
0ff00e742f fix(cli): restore BaseError catch routing post-oclif removal
PR #36328 (remove oclif) dropped the DifyCommand.catch() override that
routed BaseError through formatErrorForCli with semantic exit codes.
The replacement catch in framework/run.ts wrote raw err.message and
always exited 1, losing the code prefix, hint, http_status line, JSON
envelope path, and Auth/Usage/VersionCompat exit codes.

framework/run.ts:
- Add sniffOutputFormat(argv) helper: detects --output / -o (= and space
  forms), stops at --, first-occurrence-wins. Schema-free so it survives
  command-construction failures and pre-parse throws.
- Rewrite catch block: branch BaseError -> Error -> non-Error. BaseError
  branch routes through formatErrorForCli({ format: sniffOutputFormat(argv) })
  and exits via err.exit(). Explicit return after each process.exit
  defends against stubbed exits in tests.

run/app/sse-collector.ts:
- decodeStreamError now unwraps openapi-v1 InvokeError envelopes
  ({error_type, args, message}) buried inside env.message. Prefers
  args.description, falls back to inner.message, then raw on shape
  mismatch.

framework/command.ts:
- Sort named imports (fix pre-existing lint error).

Tests (run.test.ts new, sse-collector.test.ts extended):
- 10 sniffOutputFormat cases.
- 12 run() catch-routing cases: BaseError human/JSON, Usage/Server5xx
  exit codes, withRequest method+url in human and JSON, generic Error,
  non-Error throw, success path, constructor-time BaseError, --
  separator.
- 5 decodeStreamError unwrap cases.

Full suite: 675/675. type-check + lint clean. No subclass changes.
2026-05-18 16:34:32 -07:00
a89b43bccc simplify type signature 2026-05-18 20:30:57 +08:00
8918142ce1 refactor: remove oclif (#36328) 2026-05-18 19:07:23 +08:00
2fd7b82970 feat(cli,api): startSpinner export, local install scripts, OPENAPI enum mapping
- spinner.ts: extract startSpinner() returning ActiveSpinner handle for non-blocking use
- scripts/: add install-local.sh / uninstall-local.sh + pnpm install:local / uninstall:local
- api enums: add OPENAPI to InvokeFrom source mapping in both enum definitions
2026-05-17 20:10:01 -07:00
1cc7953f79 feat(cli): add --think flag to strip or show model thinking blocks
By default <think>...</think> blocks emitted by thinking-capable models
are silently stripped from the answer before printing. With --think,
thinking blocks are routed to stderr (with tags preserved) and the
clean answer goes to stdout.

- src/io/think-filter.ts: ThinkChunkFilter (stateful streaming filter
  that handles partial tags split across chunk boundaries), stripThinkBlocks
  and extractThinkBlocks for bulk non-stream processing; \r\n-aware
- stream-handlers.ts: ChatStreamPrinter and CompletionStreamPrinter use
  ThinkChunkFilter; streamPrinterFor(mode, think=false) backward-compat
- streaming-structured.ts: post-collect strip/extract on resp.answer
- streaming-text.ts + print-flags.ts: ctx.think threaded through
- run.ts, resume/run.ts, _strategies/index.ts: think field in types
- run/app/index.ts, resume/index.ts: --think oclif flag, default false
2026-05-17 19:18:34 -07:00
31cf656b35 feat(cli): app run overhaul — always stream, --inputs JSON, HITL pause/resume, Ctrl+C stop
- Remove blocking mode; all apps stream SSE, --stream controls live vs collect output
- Replace --input k=v with --inputs '{json}' (single object, mutually exclusive with --inputs-file)
- Add --workflow-id, --file flags
- HITL: human_input_required → pause JSON to stdout + hint to stderr + exit 2
- Ctrl+C: captures task_id from SSE, calls stop-task, exits 1
- New difyctl run app resume subcommand: POST form, reconnect SSE, stream to completion
- resume: --action (auto-select), --with-history (include_state_snapshot), --stream flags
- Delete BlockingStrategy; simplify pickStrategy(isText, livePrint)
- Add HitlPauseError, SILENT_EVENTS handling in sse-collector and stream-handlers
- Update dify-mock: always SSE, hitl-pause/hitl-resume scenarios, stop/form/events handlers
- Update agent guide: --inputs JSON syntax, HITL pause/resume instructions
2026-05-15 02:53:19 -07:00
c2b91d849d ci(cli): replace Makefile with pnpm scripts, add Dockerfile.dev and CI workflows
- Replace Makefile with package.json scripts (ci, clean, docker:build-dev,
  sync-models, version:info); update cli-tests.yml to use pnpm ci
- Add cli/Dockerfile.dev: multi-stage local build from monorepo source,
  proper cache layer order, non-root user, corepack-driven pnpm version
- Add .dockerignore at repo root to exclude node_modules/dist/.git from
  build context
- Add cli-docker-build.yml: PR + merge_group validation of Dockerfile.dev,
  amd64+arm64 via Depot for org; amd64-only for forks
- cli-release.yml: pin action SHAs, depot-ubuntu-24.04 runner, move
  verify-release step before build for fast-fail
- main-ci.yml: add packages/tsconfig/** and cli-docker-build.yml to cli
  path filter
- Drop cli/docs/specs/** and cli/docs/*.md (superseded)
2026-05-14 22:10:42 -07:00
e0f4e98a2f chore(cli): pre-merge cleanup — docker images, comments, tsconfig lib
- docker-compose.yaml: revert api/web from build: back to image tags
  (1.14.1); fix api_websocket/worker/worker_beat downgraded to 1.14.0
- Remove verbose internal design comments from openapi controllers
- web/next.config.ts: trim anti-framing comment to one line
- cli/tsconfig.json: drop lib:ES2015 override (broke Error.cause typing)
- eslint.config.mjs: ignore cli/context/** and cli/docs/** (local caches)
- pnpm-lock.yaml: regenerate after fresh install
2026-05-14 20:44:51 -07:00
9d554495cf feat(cli): add OPENAPI_ENABLED env switch, default false
Gates the entire /openapi/v1/* blueprint on a single env var.
When false (default), the blueprint is never registered so all
CLI requests return 404 before any auth or logic runs.

Set OPENAPI_ENABLED=true to activate the endpoint group.
2026-05-14 20:16:14 -07:00
1a83dfaf1f refactor: use BaseModel in openapi group. Generate ts code from swagger (#36076)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-13 12:56:42 +08:00
b21d0ae32d fix(cli): call this.parse in arg-less commands to silence oclif UnparsedCommand warning
oclif v4 warns "did not parse its arguments" for any command class whose
run() never calls this.parse(ClassName), independent of whether the
command declares args/flags. Add the call in the five arg-less commands.
2026-05-11 19:01:14 -07:00
6779366dca feat(api,web,cli): difyctl v1.0 — OAuth device flow, /openapi/v1 auth pipeline, CLI client 2026-05-11 18:40:39 -07:00