dsh-kingdee
English | Chinese
Kingdee Cloud Starry Sky secondary-development plugin for DeepSeek Harness (DSH).
dsh-kingdee gives the DSH agent a first-class, credential-safe way to act on a Kingdee Cloud Starry Sky tenant through its WebAPI: typed tools for querying, saving, submitting, auditing, un-auditing, viewing and deleting bills/base data, and for invoking BOS custom services. A companion domain skill (kingdee-bos) teaches the field/enum/status conventions and the boundary between the data layer and the platform-plugin layer.
- credential-safe — secrets are environment-variable references resolved through the DSH credential seam, never literal config.
- Kingdee V9.1 Enterprise Edition ready — fully adapted for Kingdee Cloud Starry Sky V9.1 Enterprise Edition, backward-compatible with V9.0 / V8.x, supporting the official
kdservice-sessionidsession (sent as both a request header and a cookie), stable cursor pagination (orderString,limit,startRow), direct bill number (numbers) workflow actions, and auto-submit/audit (isAutoSubmitAndAudit). - two real login paths — an account-set username/password against
AuthService.ValidateUser, or a third-party application againstAuthService.LoginByAppSecret(the mode Kingdee requires on public-cloud tenants opened after 2022-11-29). Both attach the samekdservice-sessionidsession; no fabricated auth header is used, and the login responses are classified by their ownLoginResultTypeshape rather than the business envelope. - SSRF network defense — strict protocol whitelist (http/https only) and host boundary verification blocking localhost, loopback, private subnets, and reserved network segments.
- typed tools — query, save, submit, audit, un-audit, view, delete and invoke BOS custom services through the
kingdee_*tools. Each one is listed below in the Tools table. - full state machine — create/update → submit → audit → un-audit flow, off the shelf.
- offline mock — a
mock: trueflag swaps in a local transport so you can demo and test the pipeline without a reachable tenant. - bilingual docs — English and Simplified Chinese.
🧩 Scope. This plugin covers the data/service layer of Kingdee Cloud secondary development. The platform-plugin layer (server-side C# form/list plugins, UI layout, background events) uses the BOS integration development environment and is not reachable through the WebAPI. The
kingdee-bosskill documents that boundary.
Install
# Add the bundle to a DSH profile and enable it
dsh plugin add dsh-kingdee
DeepSeek Harness 0.2.0-rc.2 compatibility. 0.12.0 is verified against DeepSeek Harness 0.2.0-rc.2 and moves its
@deepseek-ai/dsh-*devDependencies to that release. Its@deepseek-ai/dsh-credentialsand@deepseek-ai/dsh-toolspeers are unchanged at>=0.1.7-alpha.2 <0.3.0, the range 0.11.0 widened, so 0.11.1 is admitted on 0.2.0-rc.2 as well — 0.12.0 is not a mandatory upgrade. The older0.10.0declares^0.1.7-alpha.2, which excludes 0.2.x, and is refused at load on 0.2.0-rc.2: the harness checks every@deepseek-ai/dsh/@deepseek-ai/dsh-*peer entry against the single running runtime version before a plugin row loads, with prereleases participating in range matching (engines.dshis not what the gate reads). An incompatible row is refused and an incompatible bundle is skipped. On 0.2.0-rc.2, upgrade withdsh plugin add dsh-kingdee@0.12.0.The remedy the harness prints for a refusal is
dsh plugin allow-version <package@version> --dsh-version <runtime> --accept-risk(or the plugin manager), which records an exact-version exemption in the profile'scompatibility.json. That is a risk acknowledgement, not a compatibility fix, and it grants one exact plugin version on one exact runtime: a plugin upgrade or a harness upgrade does not inherit the grant.
Verified against deepseek-harness 0.2.0-rc.2 with plugin 0.12.0:
pnpm run typecheckclean,pnpm run buildclean, 15 unit tests passing (pnpm test), and the harness's own compatibility check admittingdsh-kingdee@0.12.0on runtime0.2.0-rc.2. No live-tenant verification was performed.
See CONFIG.md for full configuration, INSTALL.md for setup, USAGE.md for the tool reference, and UPDATE.md / UNINSTALL.md for upgrades and removal. Release history is in CHANGELOG.md / CHANGELOG.zh.md.
Quick start
Register the plugin and set connection details in the Plugins → kingdee settings card (or in
cordis.yml): WebAPI base URL,acctId, and the authentication mode.Put the secrets in the environment (or in the credentials store) under the references you configured. The same reference names work on every OS — only the way you set them differs:
# Linux / macOS (sh) export DSH_KINGDEE_USER=your_username export DSH_KINGDEE_PASSWORD=your_password # app mode: DSH_KINGDEE_USER holds the integration user, and is required export DSH_KINGDEE_APP_SECRET=your_app_secret# Windows — PowerShell (current session) $env:DSH_KINGDEE_USER = "your_username" $env:DSH_KINGDEE_PASSWORD = "your_password" $env:DSH_KINGDEE_APP_SECRET = "your_app_secret" # app mode (USER = integration user)REM Windows — Command Prompt (current session) set DSH_KINGDEE_USER=your_username set DSH_KINGDEE_PASSWORD=your_password set DSH_KINGDEE_APP_SECRET=your_app_secretOr store the value in the DSH credential store instead of the shell environment: set it once in the DSH settings UI (credential values are write-only — the page only ever sees a redacted descriptor), or edit
$DSH_HOME/.credentials.yamldirectly. The reference name is what the plugin config carries; the value never enters a config file.See INSTALL.md for the per-OS details (including persistent
setx/[Environment]::SetEnvironmentVariable).Ask the agent to query something:
Query sales order number SO-20260701 on Kingdee Cloud.The agent loads the
kingdee-bosskill and callskingdee_querywithformId=SAL_SaleOrder.
To try it without a real tenant, set mock: true in the plugin config — the tools then return canned Kingdee envelopes. The settings card exposes the non-secret connection fields but not mock, so this one is set in configuration:
config:
mock: true
See INSTALL.md for the full snippet.
Tools
| Tool | Description | Key parameters |
|---|---|---|
kingdee_query |
ExecuteBillQuery — query bills / base data |
formId, fieldKeys[], filter?, topCount?, organization? |
kingdee_query_business_data |
Structured query (QueryBusinessData) |
formId, fieldKeys[], filter?, topCount?, organization? |
kingdee_save |
Save (create/update) a bill or base record | formId, data, interaction? |
kingdee_batch_save |
Batch-save several records in one call | formId, records[], interaction? |
kingdee_submit |
Submit one or more records | formId, ids[], numbers? |
kingdee_unsubmit |
Un-submit records | formId, ids[] |
kingdee_audit |
Audit records | formId, ids[] |
kingdee_unaudit |
Un-audit records | formId, ids[] |
kingdee_view |
View a single record by id | formId, id |
kingdee_delete |
Delete records by id | formId, ids[] |
kingdee_delete_draft |
Delete draft records | formId, ids[] |
kingdee_invoke |
Invoke a BOS custom service | serviceName, payload?, formId? |
kingdee_logout |
Log out of the current session | — |
kingdee_list_datacenters |
List data centers / tenants at the base URL | — |
The table follows the same order as the per-tool reference in USAGE.md.
Every tool returns a normalized canonical value; a Kingdee IsSuccess=false message becomes a typed error (kd/business-error, kd/auth-failed, …) instead of prose for the model to parse.
Kingdee V9.1 conformance
dsh-kingdee targets Kingdee Cloud Starry Sky V9.1 Enterprise Edition (patch PT-163015 → product version 9.1.0.20250807) and stays backward-compatible with V9.0 / V8.x.
V9.1 has no breaking WebAPI changes. No renamed or removed operation, no cookie rename, no URL-convention change, and no new required header. The classic {baseUrl}/{stub path}.common.kdsvc + kdservice-sessionid session protocol this plugin speaks is unchanged.
What V9.1 did change at the interface layer:
Deletenow returns a correctFNumber—SuccessEntitys[].Numbercan be trusted as-is from9.1.0.20250807on.- Multi-file attachment fields may be assigned by file ID alone.
- WebAPI request-body logging was added server-side.
- The online documentation gained idempotency guidance.
- WebAPI rate limiting gained a whitelist.
- Report stubs and custom API endpoints were security-hardened.
- External-user access control was tightened.
Operational consequences:
- Because the server now logs request bodies, prefer the
app(third-party) mode over account/password where possible. - Because permissions were tightened, a missing query permission can surface as an empty result rather than an error — validate a probe query per
FormIdinstead of trusting an empty row set. - Put the plugin host's egress IP on the WebAPI rate-limit whitelist.
Evidence honesty. The login services' named request keys (acctID / username / appid / appsecret / lcid), the Limit row cap (~2000) and the listDataCenterService default name are community-attested, not officially published by Kingdee. The authoritative per-tenant source is the product itself: sign in as an administrator, then open Common Settings → Dynamic Service Definition → WebAPI, pick the business object and operation, and read that operation's parameter list and sample call.
Architecture
src/
├─ kd-core/ framework-free Kingdee WebAPI client (pure logic)
│ ├─ auth.ts user / app authentication
│ ├─ client.ts the operations set + session management
│ ├─ envelope.ts envelope parsing & normalization
│ ├─ errors.ts typed error mapping
│ ├─ transport.ts transport seam (real HTTP via fetch)
│ └─ mock.ts offline mock transport
├─ index.ts DSH host plugin: registers the kingdee_* tools + exports the Config schema
├─ tools.ts typed tool wrappers (defineTool)
├─ config.ts plugin config schema + credential resolution
└─ client/
└─ settings-card.ts browser settings card (scaffold)
skills/
└─ kingdee-bos/ domain skill: field/enum/status conventions + boundary
kd-core is published as dsh-kingdee/kd-core and has no DSH dependency, so the same logic can be wrapped later by a thin MCP server.
Build & test
The framework-free core is verified by 15 unit tests that run with the Node built-in test runner (Node ≥ 22, TS type-stripping). No DSH install is needed for the core:
pnpm test # node --test "test/**/*.test.ts"
The DSH host/plugin half (src/index.ts, tools.ts, config.ts, client/) imports @deepseek-ai/* peer packages and is compiled inside a DSH profile, where those peers resolve. Build and typecheck therefore use the DSH toolchain:
pnpm install && pnpm run typecheck # requires the deepseek-harness monorepo (or a DSH profile) for peers
The repository is TypeScript throughout; there is no JavaScript source to keep in
sync. The bilingual-documents gate is
scripts/check-docs-language.ts, which CI runs
with bare Node (no dependencies installed) before the install step:
node scripts/check-docs-language.ts
Known Limitations
- Public-cloud OpenAPI gateway not implemented. An increasing number of Kingdee public-cloud tenants require the OpenAPI gateway (
https://api.kingdee.com/galaxyapi/) with API-signature authentication (LoginByApiSignHeaders). This plugin does not implement that path — it speaks the classickdsvcsession protocol only. On such a tenant a classic session cannot be established at all, so every operation fails at login; a tenant/gateway that still exposes the classic WebAPI is required. - The platform-plugin layer is out of reach. Server-side C# form/list plugins, UI layout and background events belong to the BOS integration development environment and are not accessible through the WebAPI (see the scope note above).
- The
./clientbundle reproduces its artifact. The sharedclientBundletsdown preset lives inside the harness repository and is not published, so this package emits the documented factory format itself. - No live-tenant verification. Everything documented here is verified against the type checker, the build, the unit-test suite and the harness's own plugin compatibility check — not against a running Kingdee tenant.
Documentation
- INSTALL.md — installation and configuration
- CONFIG.md — configuration reference: fields, auth modes, credentials, SSRF baseline
- USAGE.md — tool reference with parameters and examples
- UPDATE.md — upgrading
- UNINSTALL.md — removal
- CHANGELOG.md — release history
- docs/RELEASE.md — release notes for the current version
License
This repository is under a proprietary license (all rights reserved). It is available for read/evaluation. Copying, forking, re-hosting, re-publishing, modifying, or creating derivative works — in whole or in part — is prohibited without prior written permission from the owner. See LICENSE.
No comments yet. Be the first to write one.