Wire intent→coordinator DocResolver confirm cards→action_executor kinds for comment, reopen, pending-supplements query, and real submit-review execution.
193 lines
12 KiB
Go
193 lines
12 KiB
Go
package intent
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
)
|
|
|
|
// RiskLevel 动作风险等级
|
|
type RiskLevel string
|
|
|
|
const (
|
|
RiskLow RiskLevel = "low"
|
|
RiskMedium RiskLevel = "medium"
|
|
RiskHigh RiskLevel = "high"
|
|
)
|
|
|
|
// ActionAlias 自然语言别名
|
|
type ActionAlias struct {
|
|
Phrase string `json:"phrase"`
|
|
Acts []DialogueAct `json:"acts,omitempty"`
|
|
}
|
|
|
|
// SlotSpec 槽位规格
|
|
type SlotSpec struct {
|
|
Key string `json:"key"`
|
|
Required bool `json:"required"`
|
|
Label string `json:"label,omitempty"`
|
|
}
|
|
|
|
// ActionSpec 可识别、可授权、可执行的动作单一事实源
|
|
type ActionSpec struct {
|
|
Key string `json:"key"`
|
|
Domain string `json:"domain"`
|
|
Object string `json:"object"`
|
|
Goal GoalType `json:"goal"`
|
|
Risk RiskLevel `json:"risk"`
|
|
|
|
Aliases []ActionAlias `json:"aliases,omitempty"`
|
|
DialogueActs []DialogueAct `json:"dialogue_acts,omitempty"`
|
|
|
|
RequiredSlots []SlotSpec `json:"required_slots,omitempty"`
|
|
OptionalSlots []SlotSpec `json:"optional_slots,omitempty"`
|
|
|
|
CapabilityKey string `json:"capability_key,omitempty"`
|
|
AllowedStates []string `json:"allowed_states,omitempty"`
|
|
RequiresConfirm bool `json:"requires_confirm,omitempty"`
|
|
IdempotencyMode string `json:"idempotency_mode,omitempty"`
|
|
|
|
LegacyIntent IntentType `json:"legacy_intent"`
|
|
}
|
|
|
|
// ActionRegistry 动作注册表
|
|
type ActionRegistry struct {
|
|
mu sync.RWMutex
|
|
byKey map[string]*ActionSpec
|
|
byLegacy map[IntentType]*ActionSpec
|
|
}
|
|
|
|
var defaultRegistry *ActionRegistry
|
|
|
|
func init() {
|
|
defaultRegistry = NewActionRegistry()
|
|
registerBuiltinActions(defaultRegistry)
|
|
}
|
|
|
|
// DefaultRegistry 返回全局内置注册表
|
|
func DefaultRegistry() *ActionRegistry {
|
|
return defaultRegistry
|
|
}
|
|
|
|
// NewActionRegistry 创建空注册表
|
|
func NewActionRegistry() *ActionRegistry {
|
|
return &ActionRegistry{
|
|
byKey: make(map[string]*ActionSpec),
|
|
byLegacy: make(map[IntentType]*ActionSpec),
|
|
}
|
|
}
|
|
|
|
// Register 注册动作规格
|
|
func (r *ActionRegistry) Register(spec ActionSpec) error {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
if spec.Key == "" {
|
|
return fmt.Errorf("action spec key is required")
|
|
}
|
|
if spec.LegacyIntent == "" {
|
|
return fmt.Errorf("action spec %s: legacy_intent is required", spec.Key)
|
|
}
|
|
if existing, ok := r.byKey[spec.Key]; ok && existing.LegacyIntent != spec.LegacyIntent {
|
|
return fmt.Errorf("duplicate action key %s", spec.Key)
|
|
}
|
|
cp := spec
|
|
r.byKey[spec.Key] = &cp
|
|
r.byLegacy[spec.LegacyIntent] = &cp
|
|
return nil
|
|
}
|
|
|
|
// Get 按 action_key 查找
|
|
func (r *ActionRegistry) Get(key string) (*ActionSpec, bool) {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
spec, ok := r.byKey[key]
|
|
return spec, ok
|
|
}
|
|
|
|
// GetByLegacyIntent 按旧 IntentType 查找
|
|
func (r *ActionRegistry) GetByLegacyIntent(t IntentType) (*ActionSpec, bool) {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
spec, ok := r.byLegacy[t]
|
|
return spec, ok
|
|
}
|
|
|
|
// All 返回全部已注册动作
|
|
func (r *ActionRegistry) All() []*ActionSpec {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
out := make([]*ActionSpec, 0, len(r.byKey))
|
|
for _, s := range r.byKey {
|
|
out = append(out, s)
|
|
}
|
|
return out
|
|
}
|
|
|
|
// CapabilityKeys 派生能力键列表(供 AvailableActions 同源生成)
|
|
func (r *ActionRegistry) CapabilityKeys() []string {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
seen := make(map[string]struct{})
|
|
var keys []string
|
|
for _, s := range r.byKey {
|
|
if s.CapabilityKey == "" {
|
|
continue
|
|
}
|
|
if _, ok := seen[s.CapabilityKey]; ok {
|
|
continue
|
|
}
|
|
seen[s.CapabilityKey] = struct{}{}
|
|
keys = append(keys, s.CapabilityKey)
|
|
}
|
|
return keys
|
|
}
|
|
|
|
func registerBuiltinActions(r *ActionRegistry) {
|
|
specs := []ActionSpec{
|
|
{Key: "project.advisory", Domain: "project", Object: "project", Goal: GoalQuery, Risk: RiskLow, LegacyIntent: IntentQueryProgress, CapabilityKey: "QUERY_PROGRESS", DialogueActs: []DialogueAct{DialogueActAsk}},
|
|
{Key: "project.fact.supplement", Domain: "project", Object: "project_fact", Goal: GoalMutate, Risk: RiskMedium, LegacyIntent: IntentSupplementInfo, CapabilityKey: "SUPPLEMENT_INFO", DialogueActs: []DialogueAct{DialogueActCommand}},
|
|
{Key: "project.stage.advance", Domain: "project", Object: "project", Goal: GoalControl, Risk: RiskHigh, LegacyIntent: IntentAdvanceStage, CapabilityKey: "ADVANCE_STAGE", RequiresConfirm: true, DialogueActs: []DialogueAct{DialogueActCommand, DialogueActConfirm}},
|
|
{Key: "task.run", Domain: "project", Object: "task", Goal: GoalGenerate, Risk: RiskMedium, LegacyIntent: IntentTriggerTask, CapabilityKey: "TRIGGER_TASK", DialogueActs: []DialogueAct{DialogueActCommand}},
|
|
{Key: "task.run.adhoc", Domain: "project", Object: "task", Goal: GoalGenerate, Risk: RiskMedium, LegacyIntent: IntentTriggerAdhocTask, CapabilityKey: "TRIGGER_ADHOC_TASK"},
|
|
{Key: "conversation.chat", Domain: "conversation", Object: "system_ui", Goal: GoalConverse, Risk: RiskLow, LegacyIntent: IntentCasualChat},
|
|
{Key: "conversation.decline", Domain: "conversation", Object: "system_ui", Goal: GoalDecide, Risk: RiskLow, LegacyIntent: IntentDeclineExpectation, DialogueActs: []DialogueAct{DialogueActDecline}},
|
|
|
|
{Key: "document.claim", Domain: "document_gov", Object: "controlled_document", Goal: GoalMutate, Risk: RiskMedium, LegacyIntent: IntentDocGovClaim, CapabilityKey: "DOCGOV_CLAIM", DialogueActs: []DialogueAct{DialogueActCommand}},
|
|
{Key: "document.review.submit", Domain: "document_gov", Object: "controlled_document", Goal: GoalMutate, Risk: RiskMedium, LegacyIntent: IntentDocGovSubmitReview, CapabilityKey: "DOCGOV_SUBMIT_REVIEW", DialogueActs: []DialogueAct{DialogueActCommand}},
|
|
{Key: "document.review.approve", Domain: "document_gov", Object: "controlled_document", Goal: GoalMutate, Risk: RiskHigh, LegacyIntent: IntentDocGovReviewApprove, RequiresConfirm: true, DialogueActs: []DialogueAct{DialogueActCommand, DialogueActConfirm}},
|
|
{Key: "document.review.reject", Domain: "document_gov", Object: "controlled_document", Goal: GoalMutate, Risk: RiskHigh, LegacyIntent: IntentDocGovReviewReject, RequiresConfirm: true, RequiredSlots: []SlotSpec{{Key: SlotRejectReason, Required: true, Label: "驳回理由"}}, DialogueActs: []DialogueAct{DialogueActCommand}},
|
|
{Key: "document.final.approve", Domain: "document_gov", Object: "controlled_document", Goal: GoalMutate, Risk: RiskHigh, LegacyIntent: IntentDocGovFinalApprove, RequiresConfirm: true, DialogueActs: []DialogueAct{DialogueActCommand, DialogueActConfirm}},
|
|
{Key: "document.final.reject", Domain: "document_gov", Object: "controlled_document", Goal: GoalMutate, Risk: RiskHigh, LegacyIntent: IntentDocGovFinalReject, RequiresConfirm: true, RequiredSlots: []SlotSpec{{Key: SlotRejectReason, Required: true, Label: "驳回理由"}}, DialogueActs: []DialogueAct{DialogueActCommand}},
|
|
{Key: "document.proposal.decide", Domain: "document_gov", Object: "controlled_document", Goal: GoalDecide, Risk: RiskMedium, LegacyIntent: IntentDocGovProposalDecide, DialogueActs: []DialogueAct{DialogueActConfirm, DialogueActDecline}},
|
|
{Key: "document.comment.add", Domain: "document_gov", Object: "controlled_document", Goal: GoalMutate, Risk: RiskMedium, LegacyIntent: IntentDocGovCommentAdd, CapabilityKey: "DOCGOV_COMMENT_ADD", RequiresConfirm: true, RequiredSlots: []SlotSpec{{Key: SlotCommentContent, Required: true, Label: "批注内容"}}, DialogueActs: []DialogueAct{DialogueActCommand}},
|
|
{Key: "document.comment.resolve", Domain: "document_gov", Object: "controlled_document", Goal: GoalMutate, Risk: RiskMedium, LegacyIntent: IntentDocGovCommentResolve, CapabilityKey: "DOCGOV_COMMENT_RESOLVE", RequiresConfirm: true, DialogueActs: []DialogueAct{DialogueActCommand}},
|
|
{Key: "document.reopen.request", Domain: "document_gov", Object: "controlled_document", Goal: GoalMutate, Risk: RiskHigh, LegacyIntent: IntentDocGovReopenRequest, CapabilityKey: "DOCGOV_REOPEN_REQUEST", RequiresConfirm: true, RequiredSlots: []SlotSpec{{Key: SlotReopenReason, Required: true, Label: "重开原因"}}, DialogueActs: []DialogueAct{DialogueActCommand}},
|
|
{Key: "document.reopen.approve", Domain: "document_gov", Object: "controlled_document", Goal: GoalMutate, Risk: RiskHigh, LegacyIntent: IntentDocGovReopenApprove, CapabilityKey: "DOCGOV_REOPEN_APPROVE", RequiresConfirm: true, DialogueActs: []DialogueAct{DialogueActCommand, DialogueActConfirm}},
|
|
{Key: "document.pending_supplements.query", Domain: "document_gov", Object: "controlled_document", Goal: GoalQuery, Risk: RiskLow, LegacyIntent: IntentQueryPendingSupplements, CapabilityKey: "QUERY_PENDING_SUPPLEMENTS", DialogueActs: []DialogueAct{DialogueActAsk, DialogueActCommand}},
|
|
|
|
{Key: "regulation.query", Domain: "knowledge", Object: "regulation", Goal: GoalQuery, Risk: RiskLow, LegacyIntent: IntentQueryRegulations, CapabilityKey: "QUERY_REGULATIONS", DialogueActs: []DialogueAct{DialogueActAsk}},
|
|
{Key: "case.query", Domain: "knowledge", Object: "artifact", Goal: GoalQuery, Risk: RiskLow, LegacyIntent: IntentQuerySimilarCases, CapabilityKey: "QUERY_SIMILAR_CASES", DialogueActs: []DialogueAct{DialogueActAsk}},
|
|
{Key: "permission.query", Domain: "project", Object: "user_permission", Goal: GoalQuery, Risk: RiskLow, LegacyIntent: IntentQueryUserRights, CapabilityKey: "QUERY_USER_RIGHTS", DialogueActs: []DialogueAct{DialogueActAsk}},
|
|
{Key: "document.reject_reason.query", Domain: "document_gov", Object: "controlled_document", Goal: GoalQuery, Risk: RiskLow, LegacyIntent: IntentQueryRejectReason, DialogueActs: []DialogueAct{DialogueActAsk}},
|
|
|
|
{Key: "card.confirm", Domain: "conversation", Object: "system_ui", Goal: GoalDecide, Risk: RiskHigh, LegacyIntent: IntentConfirmAction, RequiresConfirm: true, DialogueActs: []DialogueAct{DialogueActConfirm}},
|
|
{Key: "project.stage.execute", Domain: "project", Object: "project", Goal: GoalControl, Risk: RiskHigh, LegacyIntent: IntentExecuteStageAdvance, RequiresConfirm: true},
|
|
{Key: "security.forbidden", Domain: "security", Object: "system_configuration", Goal: GoalConverse, Risk: RiskHigh, LegacyIntent: IntentSecurityForbidden},
|
|
|
|
{Key: "workflow.switch", Domain: "project_workflow", Object: "workflow", Goal: GoalControl, Risk: RiskHigh, LegacyIntent: IntentSwitchWorkflow, CapabilityKey: "SWITCH_WORKFLOW", RequiresConfirm: true, RequiredSlots: []SlotSpec{{Key: SlotTargetWorkflow, Required: true, Label: "目标工作流"}}, DialogueActs: []DialogueAct{DialogueActCommand}},
|
|
{Key: "workflow.run", Domain: "project_workflow", Object: "workflow_run", Goal: GoalControl, Risk: RiskMedium, LegacyIntent: IntentTriggerWorkflow, CapabilityKey: "TRIGGER_WORKFLOW", RequiresConfirm: true, DialogueActs: []DialogueAct{DialogueActCommand}},
|
|
{Key: "workflow.status.query", Domain: "project_workflow", Object: "workflow", Goal: GoalQuery, Risk: RiskLow, LegacyIntent: IntentQueryWorkflowStatus, CapabilityKey: "QUERY_WORKFLOW", DialogueActs: []DialogueAct{DialogueActAsk}},
|
|
{Key: "document.status.query", Domain: "document_gov", Object: "controlled_document", Goal: GoalQuery, Risk: RiskLow, LegacyIntent: IntentQueryDocStatus, CapabilityKey: "VIEW_DOC", DialogueActs: []DialogueAct{DialogueActAsk}},
|
|
{Key: "conversation.help", Domain: "conversation", Object: "system_ui", Goal: GoalQuery, Risk: RiskLow, LegacyIntent: IntentHelpCapabilities, DialogueActs: []DialogueAct{DialogueActAsk}},
|
|
{Key: "conversation.unsupported", Domain: "conversation", Object: "system_ui", Goal: GoalConverse, Risk: RiskLow, LegacyIntent: IntentUnsupportedAction},
|
|
|
|
{Key: "run.status.query", Domain: "project", Object: "workflow_run", Goal: GoalQuery, Risk: RiskLow, LegacyIntent: IntentRunStatusQuery, DialogueActs: []DialogueAct{DialogueActAsk}},
|
|
{Key: "run.resume", Domain: "project", Object: "workflow_run", Goal: GoalControl, Risk: RiskMedium, LegacyIntent: IntentRunResume, RequiresConfirm: true, DialogueActs: []DialogueAct{DialogueActCommand}},
|
|
{Key: "run.restart", Domain: "project", Object: "workflow_run", Goal: GoalControl, Risk: RiskHigh, LegacyIntent: IntentRunRestart, RequiresConfirm: true, DialogueActs: []DialogueAct{DialogueActCommand}},
|
|
{Key: "project.impact.analyze", Domain: "project", Object: "controlled_document", Goal: GoalQuery, Risk: RiskLow, LegacyIntent: IntentImpactAnalyze, CapabilityKey: "IMPACT_ANALYZE", DialogueActs: []DialogueAct{DialogueActAsk}},
|
|
{Key: "project.doc.revise_propose", Domain: "project", Object: "controlled_document", Goal: GoalMutate, Risk: RiskMedium, LegacyIntent: IntentRevisePropose, CapabilityKey: "REVISE_PROPOSE", RequiresConfirm: true, DialogueActs: []DialogueAct{DialogueActCommand, DialogueActConfirm}},
|
|
}
|
|
for _, s := range specs {
|
|
_ = r.Register(s)
|
|
}
|
|
}
|