-
- delete queryData (QueryTool, sqlChatModel bean, llm.sql-model, jsqlparser dep) - delete kgSearch (findForms stays), delete loadSkill (SkillTool/SkillService) - single system prompt (domain map + 业务常识) replaces 3 ToolScope versions; ToolScope removed - intent gate reduced to 查询/新增/操作已有单据/其他 with class definitions only; write action derived from utterance in router - dedup: shared locateRecord() in ProposeWriteTool; name-field/label lookups consolidated into FormResolverService
-
P4 retirement + code slim-down (~18.5k lines deleted), on top of the intent-gate WIP (docs §17/§18 + agent/tool refinements): - Delete old 8-scene multi-agent stack: XlyErpService, SceneSelector/ Chati/ErpAi/DynamicTableNl2Sql agents, DynamicToolProvider (62 meta tools), Scene/ToolMeta/ParamRule entities+mappers+startup caches - Delete whole milvus/tts/ocr packages, /api/tts + /api/ocr endpoints, tts.html, python stream_server.py; strip dead TTS JS from chat.html (playByIndex/handleNormalResponse had no callers) - Three-pass orphan sweep: 17 dead utils, 16 dead entities, dead constants/exceptions, RedisService+RedisConfig, duplicate JacksonConfig, OperableChatMemoryProvider, old prompt generators; fold PageController into MvcConfig; trim OkHttpUtil 495→39 lines - pom: ~35→13 deps (drop mybatis/JPA/webflux/tika/pdfbox/poi/jieba/ jsoup/gson/fastjson2/springdoc/mapstruct/pagehelper/pinyin4j/ spring-retry/jnr-ffi/hutool/ocr/milvus/embeddings; add starter-jdbc); war 200M+→48M - application.yml: drop milvus/tts/ocr/tesseract/mybatis blocks; GlobalExceptionHandler returns plain {code,message} JSON - docs: mark P4 retirement done in agent-architecture §13/§18 Verified: mvn clean package OK; boot smoke on :8199 (Started 0.9s, /chat 200, health db UP). Old /api/tts & /api/ocr now 404 by design.
-
…ormCollect + Skills + KgSearch - AgentIdentity + AgentFactory: build agent per request with token+form-allowlist carried in tool instances (per-call context; robust vs LC4j callback threading) - ErpClient: token-aware read/write/examine; user-token expiry does NOT silently re-login as dev-admin (no privilege escalation) - AuthzService: devIdentity()/userIdentity() resolve granted-form set (sAuthsId) - proposeExamine tool + OpController examine dispatch + forward user Authorization on confirm - InteractionTool.askUser (structured options), FormCollectTool.collectForm (real gdsconfigformslave schema) - SkillService + SkillTool.loadSkill + ai_skill digest in system prompt - KgQueryTool.kgSearch: L2 neighbors/flow + L3 field->table - tools ErpReadTool/ProposeWriteTool/QueryTool/FormCollectTool now per-request (not @Component)
-
- AuthzService: form-level allowlist ported from backend getsAuthsIdNew (sysjurisdiction sKey set); sysadmin=all; wired into Read/lookupRecord/proposeUpdate/proposeDelete (admin dev-login => all-access; enforces per-user once prod passes through user token) - proposeDelete + ErpClient.deleteForm (handleType=del) + OpController branches op type; HITL-gated like update - docs/security-findings.md: report of the 5 current-system vulns (backend form-perm off, read-API-can-write, NL2SQL no-tenant/over-privilege/partial-SQL-safety/cache-skips-validation) for the business - Verified end-to-end: read after authz = 93; propose-delete card -> confirm -> row actually deleted; audit rows written.
-
- FormResolverService: shared KG resolution (entity->master table excl. viw_*, field 中文->column, name field, labels) - ErpReadTool.lookupRecord(entity, record): reliably resolves the master table + returns a single record's full labelled fields — fixes the 'specific field of a specific record' case (e.g. 必胜客的销售员 -> 马艺祖) - AuditService + ai_audit_log: immutable audit of propose/confirm/cancel/query (who/when/action/target/result) - QueryTool.queryData(question): read-only SQL escape hatch — coder-model NL2SQL grounded on 字段字典, jsqlparser single-SELECT guard, blocks OUTFILE/LOAD_FILE/information_schema/SLEEP, forced LIMIT, audited. SAFE by construction; NL2SQL table/join accuracy for complex questions is limited (architecture-flagged, deferred). Verified: lookupRecord works; audit rows written; Query guards + LIMIT + audit work (NL2SQL grounding still mis-picks entity master on multi-table questions).
-
- ErpReadTool: optional keyword -> LIKE filter on the form's resolved name field (viw_kg_field_dict, *Name); keyword doc clarified (only for locating a named record, empty for counts) - ErpClient.readForm: accepts filterField/filterValue -> bFilter - KgQueryTool.findForms: rank by bAiTool(curated) + table + flow-connectivity + name length so the top hit is usually the canonical form - SystemPromptService: hard 'always Simplified Chinese, no other language' rule (kills qwen language drift); prefer top form; read directly instead of over-asking - AgentConfig: qwen3 think(false)/returnThinking(false) -> fast + disciplined tool-calling, no leaked chain-of-thought - application-saaslocal.yml: chat model -> qwen3:14b Verified: no more foreign-language leaks; '多少客户'->92; keyword lookup finds 必胜客; proc-backed stock forms readable; greeting 2s, form lookup ~6s. Known limit: which form/columns get picked for a specific-field-of-specific-record query still varies (deferred KgSearch).
-
- ErpClient: thin HTTP client to ERP xlyEntry; dev-login (/checklogin admin) mints+caches a real session token, auto re-login on session expiry (code=-2); reads getBusinessDataByFormcustomId (read-only params only, never bUpdate) - ErpReadTool.readFormData(formId,moduleId): reads a form's real rows, renders Chinese column labels from viw_kg_field_dict, first 10 rows + total count - wired into the agent (tools = findForms + readFormData); system prompt now describes the findForms->readFormData flow (still read-only, writes still 'under development') - application-saaslocal.yml: erp.baseurl -> local xlyEntry :8697 + dev-login creds Verified: '我们有多少客户' -> agent finds the form, reads 92 real customers, renders a clean Chinese table (name/category/salesperson/tax).