Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
25d8d6d219 | ||
|
|
6cbef9af41 | ||
|
|
2fe9802e5a |
@@ -533,7 +533,7 @@ func main() {
|
|||||||
log.Printf("interaction principal history loaded: %d utterances", len(recentUserHistory))
|
log.Printf("interaction principal history loaded: %d utterances", len(recentUserHistory))
|
||||||
}
|
}
|
||||||
conversationHistory = append(conversationHistory, recentUserHistory...)
|
conversationHistory = append(conversationHistory, recentUserHistory...)
|
||||||
personalMemory := interactiondomain.CompilePersonalMemory(conversationHistory)
|
gen2Context := interactiondomain.BuildGen2Context(conversationHistory)
|
||||||
if !creativeUserRequest && locationReply == "" {
|
if !creativeUserRequest && locationReply == "" {
|
||||||
if continuation := interactiondomain.ContinueLocalSearch(effectiveTaskMessage, conversationHistory); continuation != "" {
|
if continuation := interactiondomain.ContinueLocalSearch(effectiveTaskMessage, conversationHistory); continuation != "" {
|
||||||
continuationMessage = continuation
|
continuationMessage = continuation
|
||||||
@@ -829,7 +829,7 @@ func main() {
|
|||||||
reply, backed := renderResearchReply(searchQuery, result, researchErr)
|
reply, backed := renderResearchReply(searchQuery, result, researchErr)
|
||||||
if !backed && cognitiveAvailable {
|
if !backed && cognitiveAvailable {
|
||||||
answerCtx, cancelAnswer := context.WithTimeout(r.Context(), 12*time.Second)
|
answerCtx, cancelAnswer := context.WithTimeout(r.Context(), 12*time.Second)
|
||||||
answer, answerErr := cognitiveClient.AnswerStableKnowledge(answerCtx, session, part, personalMemory.ContextText(), cognitive.TaskMeaning{
|
answer, answerErr := cognitiveClient.AnswerStableKnowledge(answerCtx, session, part, gen2Context.Text, cognitive.TaskMeaning{
|
||||||
SpeechAct: string(semantic.Interpretation.SpeechAct), CapabilityHints: toCapabilityKinds(semantic.CapabilityHints), RequestedOutcome: semantic.Interpretation.RequestedOutcome, InformationRequestKind: semantic.InformationRequestKind, ConfidenceMillis: semantic.Interpretation.ConfidenceMillis,
|
SpeechAct: string(semantic.Interpretation.SpeechAct), CapabilityHints: toCapabilityKinds(semantic.CapabilityHints), RequestedOutcome: semantic.Interpretation.RequestedOutcome, InformationRequestKind: semantic.InformationRequestKind, ConfidenceMillis: semantic.Interpretation.ConfidenceMillis,
|
||||||
})
|
})
|
||||||
cancelAnswer()
|
cancelAnswer()
|
||||||
@@ -869,7 +869,7 @@ func main() {
|
|||||||
canGenerateTextReply := shouldGenerateNonMutatingTextDirective(semantic, routePlan, helpPath, creativeRequest) && planningReply == deterministicReply
|
canGenerateTextReply := shouldGenerateNonMutatingTextDirective(semantic, routePlan, helpPath, creativeRequest) && planningReply == deterministicReply
|
||||||
if (planningReply == "" && needsCognition && semantic.Interpretation.SpeechAct == interaction.SpeechActQuestion || canGenerateTextReply) && !hasChatRoute(routePlan, chatRouteResearch) && !creativeRequest {
|
if (planningReply == "" && needsCognition && semantic.Interpretation.SpeechAct == interaction.SpeechActQuestion || canGenerateTextReply) && !hasChatRoute(routePlan, chatRouteResearch) && !creativeRequest {
|
||||||
answerCtx, cancelAnswer := context.WithTimeout(r.Context(), 12*time.Second)
|
answerCtx, cancelAnswer := context.WithTimeout(r.Context(), 12*time.Second)
|
||||||
answer, answerErr := cognitiveClient.AnswerStableKnowledge(answerCtx, session, effectiveTaskMessage, personalMemory.ContextText(), cognitive.TaskMeaning{
|
answer, answerErr := cognitiveClient.AnswerStableKnowledge(answerCtx, session, effectiveTaskMessage, gen2Context.Text, cognitive.TaskMeaning{
|
||||||
SpeechAct: string(semantic.Interpretation.SpeechAct), CapabilityHints: toCapabilityKinds(semantic.CapabilityHints), RequestedOutcome: semantic.Interpretation.RequestedOutcome, InformationRequestKind: semantic.InformationRequestKind, ConfidenceMillis: semantic.Interpretation.ConfidenceMillis,
|
SpeechAct: string(semantic.Interpretation.SpeechAct), CapabilityHints: toCapabilityKinds(semantic.CapabilityHints), RequestedOutcome: semantic.Interpretation.RequestedOutcome, InformationRequestKind: semantic.InformationRequestKind, ConfidenceMillis: semantic.Interpretation.ConfidenceMillis,
|
||||||
})
|
})
|
||||||
cancelAnswer()
|
cancelAnswer()
|
||||||
@@ -992,7 +992,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
if strings.TrimSpace(planningReply) != "" {
|
if strings.TrimSpace(planningReply) != "" {
|
||||||
reviewContext, cancelReview := context.WithTimeout(r.Context(), 12*time.Second)
|
reviewContext, cancelReview := context.WithTimeout(r.Context(), 12*time.Second)
|
||||||
reviewedReply, reviewErr := cognitiveClient.ReviewResponse(reviewContext, session, utterance.Content, planningReply, personalMemory.ContextText(), cognitive.TaskMeaning{
|
reviewedReply, reviewErr := cognitiveClient.ReviewResponse(reviewContext, session, utterance.Content, planningReply, gen2Context.Text, cognitive.TaskMeaning{
|
||||||
SpeechAct: string(semantic.Interpretation.SpeechAct),
|
SpeechAct: string(semantic.Interpretation.SpeechAct),
|
||||||
CapabilityHints: toCapabilityKinds(semantic.CapabilityHints),
|
CapabilityHints: toCapabilityKinds(semantic.CapabilityHints),
|
||||||
RequestedOutcome: semantic.Interpretation.RequestedOutcome,
|
RequestedOutcome: semantic.Interpretation.RequestedOutcome,
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"git.cin.su/m/Assistant/contracts/secrets"
|
||||||
|
"git.cin.su/m/Assistant/platform/ids"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SettingDefinitionID ids.StableID
|
||||||
|
type SettingAssignmentID ids.StableID
|
||||||
|
type ConfigurationRevision ids.Revision
|
||||||
|
type ValueType string
|
||||||
|
type ResolutionMode string
|
||||||
|
type SettingLifecycle string
|
||||||
|
type SettingSource string
|
||||||
|
|
||||||
|
const (
|
||||||
|
ValueString ValueType = "STRING"
|
||||||
|
ValueInteger ValueType = "INTEGER"
|
||||||
|
ValueBoolean ValueType = "BOOLEAN"
|
||||||
|
ValueSecretRef ValueType = "SECRET_REF"
|
||||||
|
ResolutionMostSpecific ResolutionMode = "MOST_SPECIFIC_WINS"
|
||||||
|
ResolutionFirstHuman ResolutionMode = "FIRST_EXPLICIT_HUMAN_WINS"
|
||||||
|
ResolutionMergeList ResolutionMode = "MERGE_LIST"
|
||||||
|
SettingActive SettingLifecycle = "ACTIVE"
|
||||||
|
SettingDeprecated SettingLifecycle = "DEPRECATED"
|
||||||
|
SettingRetired SettingLifecycle = "RETIRED"
|
||||||
|
SourceHumanDirective SettingSource = "HUMAN_DIRECTIVE"
|
||||||
|
SourceMigrated SettingSource = "MIGRATED_CONFIG"
|
||||||
|
SourceSkillDefault SettingSource = "SKILL_DEFAULT"
|
||||||
|
SourceSystemDefault SettingSource = "SYSTEM_DEFAULT"
|
||||||
|
SourceGovernedChange SettingSource = "GOVERNED_CHANGE"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SettingDefinition struct {
|
||||||
|
ID SettingDefinitionID
|
||||||
|
OwnerNamespace string
|
||||||
|
StableKey string
|
||||||
|
Revision ConfigurationRevision
|
||||||
|
ValueType ValueType
|
||||||
|
DefaultValue string
|
||||||
|
Sensitivity string
|
||||||
|
Lifecycle SettingLifecycle
|
||||||
|
RecordedAtUnixMillis int64
|
||||||
|
}
|
||||||
|
type ScopeSelector struct {
|
||||||
|
PrincipalRef string
|
||||||
|
RequiredContextBindings []string
|
||||||
|
ActivityRef string
|
||||||
|
SkillRef string
|
||||||
|
TaskRef string
|
||||||
|
SessionRef string
|
||||||
|
TemporaryOverride bool
|
||||||
|
}
|
||||||
|
type SettingAssignment struct {
|
||||||
|
ID SettingAssignmentID
|
||||||
|
PrincipalID string
|
||||||
|
DefinitionRef string
|
||||||
|
DefinitionRevision ConfigurationRevision
|
||||||
|
Revision ConfigurationRevision
|
||||||
|
Selector ScopeSelector
|
||||||
|
TypedValue string
|
||||||
|
SecretRef *secrets.CredentialRef
|
||||||
|
EffectiveFromUnixMillis int64
|
||||||
|
EffectiveUntilUnixMillis *int64
|
||||||
|
Source SettingSource
|
||||||
|
SourceRef string
|
||||||
|
Lifecycle SettingLifecycle
|
||||||
|
RecordedAtUnixMillis int64
|
||||||
|
}
|
||||||
|
type EffectiveSetting struct {
|
||||||
|
DefinitionRef string
|
||||||
|
Value string
|
||||||
|
WinningAssignmentRef string
|
||||||
|
ResolutionTrace []string
|
||||||
|
}
|
||||||
|
type BootstrapConfig struct {
|
||||||
|
NodeIdentity string
|
||||||
|
ControlDatabaseLocator string
|
||||||
|
RootSecretResolverLocator string
|
||||||
|
RecoveryLocator string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d SettingDefinition) Validate() error {
|
||||||
|
if d.ID == "" || d.OwnerNamespace == "" || d.StableKey == "" || !ids.Revision(d.Revision).Valid() || d.ValueType == "" || d.Lifecycle == "" || d.RecordedAtUnixMillis < 1 {
|
||||||
|
return fmt.Errorf("invalid setting definition")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (a SettingAssignment) Validate() error {
|
||||||
|
if a.ID == "" || a.PrincipalID == "" || a.DefinitionRef == "" || !ids.Revision(a.Revision).Valid() || a.Source == "" || a.Lifecycle == "" || a.RecordedAtUnixMillis < 1 {
|
||||||
|
return fmt.Errorf("invalid setting assignment")
|
||||||
|
}
|
||||||
|
if a.SecretRef != nil && a.TypedValue != "" {
|
||||||
|
return fmt.Errorf("secret assignment must not contain typed value")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
BEGIN;
|
||||||
|
SET ROLE configuration_role;
|
||||||
|
CREATE TABLE IF NOT EXISTS configuration.setting_definitions (setting_definition_id TEXT PRIMARY KEY, owner_namespace TEXT NOT NULL, stable_key TEXT NOT NULL, revision BIGINT NOT NULL CHECK(revision>0), value_type TEXT NOT NULL, default_value TEXT, sensitivity TEXT NOT NULL, lifecycle TEXT NOT NULL, recorded_at_unix_millis BIGINT NOT NULL);
|
||||||
|
CREATE TABLE IF NOT EXISTS configuration.setting_assignments (setting_assignment_id TEXT PRIMARY KEY, principal_id TEXT NOT NULL, definition_ref JSONB NOT NULL, revision BIGINT NOT NULL CHECK(revision>0), selector JSONB NOT NULL, typed_value TEXT, secret_ref TEXT, effective_from_unix_millis BIGINT NOT NULL, effective_until_unix_millis BIGINT, source TEXT NOT NULL, source_ref TEXT NOT NULL, lifecycle TEXT NOT NULL, recorded_at_unix_millis BIGINT NOT NULL);
|
||||||
|
GRANT SELECT, INSERT, UPDATE ON configuration.setting_definitions, configuration.setting_assignments TO configuration_role;
|
||||||
|
RESET ROLE;
|
||||||
|
COMMIT;
|
||||||
@@ -1 +1 @@
|
|||||||
{"task_file":"dev/tasks/GEN2-010-context-compiler-v2-with-budgets-coverage-and-iterative-retrieval.json","task_id":"GEN2-010","task_revision":1}
|
{"task_file":"dev/tasks/GEN2-012-add-typed-scoped-versioned-configuration-owner-and-bootstrap-boundary.json","task_id":"GEN2-012","task_revision":1}
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# configuration
|
||||||
|
|
||||||
|
Configuration owns typed, scoped, versioned settings. ENV is limited to
|
||||||
|
bootstrap primitives; secret values are never configuration values.
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"git.cin.su/m/Assistant/contracts/configuration"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Resolve(definition configuration.SettingDefinition, assignments []configuration.SettingAssignment, selector configuration.ScopeSelector) (configuration.EffectiveSetting,error){if err:=definition.Validate();err!=nil{return configuration.EffectiveSetting{},err}; var matches []configuration.SettingAssignment;for _,a:=range assignments{if err:=a.Validate();err!=nil{return configuration.EffectiveSetting{},err};if a.DefinitionRef==string(definition.ID)&&a.Lifecycle==configuration.SettingActive&&a.Selector.PrincipalRef==selector.PrincipalRef&&a.Selector.SkillRef==selector.SkillRef{matches=append(matches,a)}};if len(matches)==0{return configuration.EffectiveSetting{DefinitionRef:string(definition.ID),Value:definition.DefaultValue,ResolutionTrace:[]string{"system-default"}},nil};sort.SliceStable(matches,func(i,j int)bool{return specificity(matches[i].Selector)>specificity(matches[j].Selector)});if len(matches)>1&&specificity(matches[0].Selector)==specificity(matches[1].Selector){return configuration.EffectiveSetting{},fmt.Errorf("configuration conflict")};return configuration.EffectiveSetting{DefinitionRef:string(definition.ID),Value:matches[0].TypedValue,WinningAssignmentRef:string(matches[0].ID),ResolutionTrace:[]string{"specificity-selected"}},nil}
|
||||||
|
func specificity(s configuration.ScopeSelector)int{return len(s.RequiredContextBindings)+boolInt(s.SkillRef!="")+boolInt(s.TaskRef!="")+boolInt(s.SessionRef!="")+boolInt(s.TemporaryOverride)}
|
||||||
|
func boolInt(v bool)int{if v{return 1};return 0}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package domain_test
|
||||||
|
import("testing"; "git.cin.su/m/Assistant/contracts/configuration"; "git.cin.su/m/Assistant/modules/configuration/domain")
|
||||||
|
func TestConfigurationResolvesCompanyAndSkillScope(t *testing.T){d:=configuration.SettingDefinition{ID:"x",OwnerNamespace:"capability",StableKey:"endpoint",Revision:1,ValueType:configuration.ValueString,Lifecycle:configuration.SettingActive,RecordedAtUnixMillis:1};a:=configuration.SettingAssignment{ID:"a",PrincipalID:"company-a",DefinitionRef:"x",Revision:1,Selector:configuration.ScopeSelector{PrincipalRef:"company-a",SkillRef:"skill"},TypedValue:"a-value",Source:configuration.SourceHumanDirective,Lifecycle:configuration.SettingActive,RecordedAtUnixMillis:1};got,err:=domain.Resolve(d,[]configuration.SettingAssignment{a},configuration.ScopeSelector{PrincipalRef:"company-a",SkillRef:"skill"});if err!=nil||got.Value!="a-value"{t.Fatalf("got %#v err=%v",got,err)}}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
import "git.cin.su/m/Assistant/contracts/interaction"
|
||||||
|
|
||||||
|
type ContextProjection struct {
|
||||||
|
Text string
|
||||||
|
Source string
|
||||||
|
UsedPersonalMemoryFallback bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildGen2Context is a read-side projection over canonical utterance history.
|
||||||
|
// PersonalMemory remains a compatibility fallback and is never written here.
|
||||||
|
func BuildGen2Context(history []interaction.HumanUtterance) ContextProjection {
|
||||||
|
text := CompilePersonalMemory(history).ContextText()
|
||||||
|
if text != "" {
|
||||||
|
return ContextProjection{Text: text, Source: "retrieval:interaction-utterances"}
|
||||||
|
}
|
||||||
|
return ContextProjection{Text: text, Source: "personal-memory-v1-fallback", UsedPersonalMemoryFallback: true}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package domain_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.cin.su/m/Assistant/contracts/interaction"
|
||||||
|
"git.cin.su/m/Assistant/modules/interaction/domain"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGen2ContextUsesRetrievalProjectionAndKeepsV1Fallback(t *testing.T) {
|
||||||
|
got := domain.BuildGen2Context([]interaction.HumanUtterance{{ID: "u", Content: "Я сейчас в Москве", ReceivedAtUnixMillis: 1}})
|
||||||
|
if got.Source != "retrieval:interaction-utterances" || got.UsedPersonalMemoryFallback {
|
||||||
|
t.Fatalf("got %#v", got)
|
||||||
|
}
|
||||||
|
empty := domain.BuildGen2Context(nil)
|
||||||
|
if !empty.UsedPersonalMemoryFallback {
|
||||||
|
t.Fatalf("fallback missing: %#v", empty)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package secrets
|
||||||
|
|
||||||
|
import "git.cin.su/m/Assistant/contracts/configuration"
|
||||||
|
|
||||||
|
func ValidateBootstrap(value configuration.BootstrapConfig) bool {
|
||||||
|
return value.NodeIdentity != "" && value.ControlDatabaseLocator != "" && value.RootSecretResolverLocator != ""
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user